<commit_before>/*
 * Copyright 2012 Michael Chen <omxcodec@gmail.com>
 *
 * 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "FFMPEG"
#include <utils/Log.h>

#include <stdlib.h>

#include <media/stagefright/DataSource.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "config.h"
#include "libavformat/url.h"

#ifdef __cplusplus
}
#endif

namespace android {

class FFSource
{
public:
    FFSource(DataSource *source);
    int init_check();
    int read(unsigned char *buf, size_t size);
    int64_t seek(int64_t pos);
    off64_t getSize();
    ~FFSource();
protected:
    sp<DataSource> mSource;
    int64_t mOffset;
};

FFSource::FFSource(DataSource *source)
    : mSource(source),
      mOffset(0)
{
}

FFSource::~FFSource()
{
	mSource = NULL;
}

int FFSource::init_check()
{
    if (mSource->initCheck() != OK) {
        ALOGE("FFSource initCheck failed");
        return -1;
    }

    return 0;
}

int FFSource::read(unsigned char *buf, size_t size)
{
    ssize_t n = 0;

    n = mSource->readAt(mOffset, buf, size);
    if (n == UNKNOWN_ERROR) {
        ALOGE("FFSource readAt failed");
        return AVERROR(errno);
    }
    if (n > 0) {
        mOffset += n;
    }

    return n;
}

int64_t FFSource::seek(int64_t pos)
{
    mOffset = pos;
    return 0;
}

off64_t FFSource::getSize()
{
    off64_t sz = -1;

    if (mSource->getSize(&sz) != OK) {
         ALOGE("FFSource getSize failed");
         return AVERROR(errno);
    }

    return sz;
}

/////////////////////////////////////////////////////////////////

static int android_open(URLContext *h, const char *url, int flags)
{
    // the url in form of "android-source:<DataSource Ptr>",
    // the DataSource Pointer passed by the ffmpeg extractor
    DataSource *source = NULL;

    ALOGV("android source begin open");

    if (!url) {
        ALOGE("android url is null!");
        return -1;
    }

    ALOGV("android open, url: %s", url);
    sscanf(url + strlen("android-source:"), "%p", &source);
    if(source == NULL){
        ALOGE("ffmpeg open data source error!");
        return -1;
    }
    ALOGV("ffmpeg open android data source success, source ptr: %p", source);

    FFSource *ffs = new FFSource(source);
    h->priv_data = (void *)ffs;

    ALOGV("android source open success");

    return 0;
}
static int android_read(URLContext *h, unsigned char *buf, int size)
{
    FFSource* ffs = (FFSource *)h->priv_data;
    return ffs->read(buf, size);
}

static int android_write(URLContext *h, const unsigned char *buf, int size)
{
    return -1;
}

static int64_t android_seek(URLContext *h, int64_t pos, int whence)
{
    FFSource* ffs = (FFSource*)h->priv_data;

    if (whence == AVSEEK_SIZE) {
        return ffs->getSize();
    }

    ffs->seek(pos);
    return 0;
}

static int android_close(URLContext *h)
{
    FFSource* ffs = (FFSource*)h->priv_data;
    ALOGV("android source close");
    delete ffs;
    return 0;
}

static int android_get_handle(URLContext *h)
{
    return (intptr_t)h->priv_data;
}

static int android_check(URLContext *h, int mask)
{
    FFSource* ffs = (FFSource*)h->priv_data;

    if (ffs->init_check() < 0)
        return AVERROR(EACCES); // FIXME

    return (mask & AVIO_FLAG_READ);
}

static URLProtocol ff_android_protocol;

void ffmpeg_register_android_source()
{
    memset(&ff_android_protocol, 0, sizeof(URLProtocol));
    ff_android_protocol.name                = "android-source";
    ff_android_protocol.url_open            = android_open;
    ff_android_protocol.url_read            = android_read;
    ff_android_protocol.url_write           = android_write;
    ff_android_protocol.url_seek            = android_seek;
    ff_android_protocol.url_close           = android_close;
    ff_android_protocol.url_get_file_handle = android_get_handle;
    ff_android_protocol.url_check           = android_check;

    ffurl_register_protocol(&ff_android_protocol, sizeof(URLProtocol));
}

}  // namespace android
<commit_msg>ffmpeg_source: add url check to android_open<commit_after>/*
 * Copyright 2012 Michael Chen <omxcodec@gmail.com>
 *
 * 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "FFMPEG"
#include <utils/Log.h>

#include <stdlib.h>

#include <media/stagefright/DataSource.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "config.h"
#include "libavformat/url.h"

#ifdef __cplusplus
}
#endif

namespace android {

class FFSource
{
public:
    FFSource(DataSource *source);
    int init_check();
    int read(unsigned char *buf, size_t size);
    int64_t seek(int64_t pos);
    off64_t getSize();
    ~FFSource();
protected:
    sp<DataSource> mSource;
    int64_t mOffset;
};

FFSource::FFSource(DataSource *source)
    : mSource(source),
      mOffset(0)
{
}

FFSource::~FFSource()
{
	mSource = NULL;
}

int FFSource::init_check()
{
    if (mSource->initCheck() != OK) {
        ALOGE("FFSource initCheck failed");
        return -1;
    }

    return 0;
}

int FFSource::read(unsigned char *buf, size_t size)
{
    ssize_t n = 0;

    n = mSource->readAt(mOffset, buf, size);
    if (n == UNKNOWN_ERROR) {
        ALOGE("FFSource readAt failed");
        return AVERROR(errno);
    }
    if (n > 0) {
        mOffset += n;
    }

    return n;
}

int64_t FFSource::seek(int64_t pos)
{
    mOffset = pos;
    return 0;
}

off64_t FFSource::getSize()
{
    off64_t sz = -1;

    if (mSource->getSize(&sz) != OK) {
         ALOGE("FFSource getSize failed");
         return AVERROR(errno);
    }

    return sz;
}

/////////////////////////////////////////////////////////////////

static int android_open(URLContext *h, const char *url, int flags)
{
    // the url in form of "android-source:<DataSource Ptr>",
    // the DataSource Pointer passed by the ffmpeg extractor
    DataSource *source = NULL;
    char url_check[PATH_MAX] = {0};

    ALOGV("android source begin open");

    if (!url) {
        ALOGE("android url is null!");
        return -1;
    }

    ALOGV("android open, url: %s", url);
    sscanf(url + strlen("android-source:"), "%p", &source);
    if(source == NULL){
        ALOGE("ffmpeg open data source error! (invalid source)");
        return -1;
    }

    snprintf(url_check, sizeof(url_check), "android-source:%p",
                source);

    if (strcmp(url_check, url) != 0) {

        String8 uri = source->getUri();
        if (!uri.string()) {
            ALOGE("ffmpeg open data source error! (source uri)");
            return -1;
        }

        snprintf(url_check, sizeof(url_check), "android-source:%p|file:%s",
                    source, uri.string());

        if (strcmp(url_check, url) != 0) {
            ALOGE("ffmpeg open data source error! (url check)");
            return -1;
        }
    }

    ALOGV("ffmpeg open android data source success, source ptr: %p", source);

    FFSource *ffs = new FFSource(source);
    h->priv_data = (void *)ffs;

    ALOGV("android source open success");

    return 0;
}
static int android_read(URLContext *h, unsigned char *buf, int size)
{
    FFSource* ffs = (FFSource *)h->priv_data;
    return ffs->read(buf, size);
}

static int android_write(URLContext *h, const unsigned char *buf, int size)
{
    return -1;
}

static int64_t android_seek(URLContext *h, int64_t pos, int whence)
{
    FFSource* ffs = (FFSource*)h->priv_data;

    if (whence == AVSEEK_SIZE) {
        return ffs->getSize();
    }

    ffs->seek(pos);
    return 0;
}

static int android_close(URLContext *h)
{
    FFSource* ffs = (FFSource*)h->priv_data;
    ALOGV("android source close");
    delete ffs;
    return 0;
}

static int android_get_handle(URLContext *h)
{
    return (intptr_t)h->priv_data;
}

static int android_check(URLContext *h, int mask)
{
    FFSource* ffs = (FFSource*)h->priv_data;

    if (ffs->init_check() < 0)
        return AVERROR(EACCES); // FIXME

    return (mask & AVIO_FLAG_READ);
}

static URLProtocol ff_android_protocol;

void ffmpeg_register_android_source()
{
    memset(&ff_android_protocol, 0, sizeof(URLProtocol));
    ff_android_protocol.name                = "android-source";
    ff_android_protocol.url_open            = android_open;
    ff_android_protocol.url_read            = android_read;
    ff_android_protocol.url_write           = android_write;
    ff_android_protocol.url_seek            = android_seek;
    ff_android_protocol.url_close           = android_close;
    ff_android_protocol.url_get_file_handle = android_get_handle;
    ff_android_protocol.url_check           = android_check;

    ffurl_register_protocol(&ff_android_protocol, sizeof(URLProtocol));
}

}  // namespace android
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <concepts>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/for_each.hpp>

#include "bytes.hh"

enum class mutable_view { no, yes, };

/// Fragmented buffer
///
/// Concept `FragmentedBuffer` is satisfied by any class that is a range of
/// fragments and provides a method `size_bytes()` which returns the total
/// size of the buffer. The interfaces accepting `FragmentedBuffer` will attempt
/// to avoid unnecessary linearisation.
template<typename T>
concept FragmentRange = requires (T range) {
    typename T::fragment_type;
    requires std::is_same_v<typename T::fragment_type, bytes_view>
        || std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
    { *range.begin() } -> std::convertible_to<const typename T::fragment_type&>;
    { *range.end() } -> std::convertible_to<const typename T::fragment_type&>;
    { range.size_bytes() } -> std::convertible_to<size_t>;
    { range.empty() } -> std::same_as<bool>; // returns true iff size_bytes() == 0.
};

template<typename T, typename = void>
struct is_fragment_range : std::false_type { };

template<typename T>
struct is_fragment_range<T, std::void_t<typename T::fragment_type>> : std::true_type { };

template<typename T>
static constexpr bool is_fragment_range_v = is_fragment_range<T>::value;

/// A non-mutable view of a FragmentRange
///
/// Provide a trivially copyable and movable, non-mutable view on a
/// fragment range. This allows uniform ownership semantics across
/// multi-fragment ranges and the single fragment and empty fragment
/// adaptors below, i.e. it allows treating all fragment ranges
/// uniformly as views.
template <typename T>
requires FragmentRange<T>
class fragment_range_view {
    const T* _range;
public:
    using fragment_type = typename T::fragment_type;
    using iterator = typename T::const_iterator;
    using const_iterator = typename T::const_iterator;

public:
    explicit fragment_range_view(const T& range) : _range(&range) { }

    const_iterator begin() const { return _range->begin(); }
    const_iterator end() const { return _range->end(); }

    size_t size_bytes() const { return _range->size_bytes(); }
    bool empty() const { return _range->empty(); }
};

/// Single-element fragment range
///
/// This is a helper that allows converting a bytes_view into a FragmentRange.
template<mutable_view is_mutable>
class single_fragment_range {
public:
    using fragment_type = std::conditional_t<is_mutable == mutable_view::no,
                                             bytes_view, bytes_mutable_view>;
private:
    fragment_type _view;
public:
    using iterator = const fragment_type*;
    using const_iterator = const fragment_type*;

    explicit single_fragment_range(fragment_type f) : _view { f } { }

    const_iterator begin() const { return &_view; }
    const_iterator end() const { return &_view + 1; }

    size_t size_bytes() const { return _view.size(); }
    bool empty() const { return _view.empty(); }
};

single_fragment_range(bytes_view) -> single_fragment_range<mutable_view::no>;
single_fragment_range(bytes_mutable_view) -> single_fragment_range<mutable_view::yes>;

/// Empty fragment range.
struct empty_fragment_range {
    using fragment_type = bytes_view;
    using iterator = bytes_view*;
    using const_iterator = bytes_view*;

    iterator begin() const { return nullptr; }
    iterator end() const { return nullptr; }

    size_t size_bytes() const { return 0; }
    bool empty() const { return true; }
};

static_assert(FragmentRange<empty_fragment_range>);
static_assert(FragmentRange<single_fragment_range<mutable_view::no>>);
static_assert(FragmentRange<single_fragment_range<mutable_view::yes>>);

template<typename FragmentedBuffer>
requires FragmentRange<FragmentedBuffer>
bytes linearized(const FragmentedBuffer& buffer)
{
    bytes b(bytes::initialized_later(), buffer.size_bytes());
    auto dst = b.begin();
    using boost::range::for_each;
    for_each(buffer, [&] (bytes_view fragment) {
        dst = boost::copy(fragment, dst);
    });
    return b;
}

template<typename FragmentedBuffer, typename Function>
requires FragmentRange<FragmentedBuffer> && requires (Function fn, bytes_view bv) {
    fn(bv);
}
decltype(auto) with_linearized(const FragmentedBuffer& buffer, Function&& fn)
{
    bytes b;
    bytes_view bv;
    if (__builtin_expect(!buffer.empty() && std::next(buffer.begin()) == buffer.end(), true)) {
        bv = *buffer.begin();
    } else if (!buffer.empty()) {
        b = linearized(buffer);
        bv = b;
    }
    return fn(bv);
}

template<typename T>
concept FragmentedView = requires (T view, size_t n) {
    typename T::fragment_type;
    requires std::is_same_v<typename T::fragment_type, bytes_view>
            || std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
    // No preconditions.
    { view.current_fragment() } -> std::convertible_to<const typename T::fragment_type&>;
    // No preconditions.
    { view.empty() } -> std::same_as<bool>;
    // No preconditions.
    { view.size_bytes() } -> std::convertible_to<size_t>;
    // Precondition: n <= size_bytes()
    { view.prefix(n) } -> std::same_as<T>;
    // Precondition: n <= size_bytes()
    view.remove_prefix(n);
    // Precondition: size_bytes() > 0
    view.remove_current();
};

template<typename T>
concept FragmentedMutableView = requires (T view) {
    requires FragmentedView<T>;
    requires std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
};

template<FragmentedView View>
requires (!FragmentRange<View>)
bytes linearized(View v)
{
    bytes b(bytes::initialized_later(), v.size_bytes());
    auto out = b.begin();
    while (v.size_bytes()) {
        out = std::copy(v.current_fragment().begin(), v.current_fragment().end(), out);
        v.remove_current();
    }
    return b;
}

template<FragmentedView View, typename Function>
requires (!FragmentRange<View>) && std::invocable<Function, bytes_view>
decltype(auto) with_linearized(const View& v, Function&& fn)
{
    if (v.size_bytes() == v.current_fragment().size()) [[likely]] {
        return fn(v.current_fragment());
    } else {
        return fn(linearized(v));
    }
}

class single_fragmented_view {
    bytes_view _view;
public:
    using fragment_type = bytes_view;
    explicit single_fragmented_view(bytes_view bv) : _view(bv) {}
    size_t size_bytes() const { return _view.size(); }
    bool empty() const { return _view.empty(); }
    void remove_prefix(size_t n) { _view.remove_prefix(n); }
    void remove_current() { _view = bytes_view(); }
    bytes_view current_fragment() const { return _view; }
    single_fragmented_view prefix(size_t n) { return single_fragmented_view(_view.substr(0, n)); }
};
static_assert(FragmentedView<single_fragmented_view>);
<commit_msg>utils: fragment_range: add with_simplified()<commit_after>/*
 * Copyright (C) 2018 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <concepts>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/for_each.hpp>

#include "bytes.hh"

enum class mutable_view { no, yes, };

/// Fragmented buffer
///
/// Concept `FragmentedBuffer` is satisfied by any class that is a range of
/// fragments and provides a method `size_bytes()` which returns the total
/// size of the buffer. The interfaces accepting `FragmentedBuffer` will attempt
/// to avoid unnecessary linearisation.
template<typename T>
concept FragmentRange = requires (T range) {
    typename T::fragment_type;
    requires std::is_same_v<typename T::fragment_type, bytes_view>
        || std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
    { *range.begin() } -> std::convertible_to<const typename T::fragment_type&>;
    { *range.end() } -> std::convertible_to<const typename T::fragment_type&>;
    { range.size_bytes() } -> std::convertible_to<size_t>;
    { range.empty() } -> std::same_as<bool>; // returns true iff size_bytes() == 0.
};

template<typename T, typename = void>
struct is_fragment_range : std::false_type { };

template<typename T>
struct is_fragment_range<T, std::void_t<typename T::fragment_type>> : std::true_type { };

template<typename T>
static constexpr bool is_fragment_range_v = is_fragment_range<T>::value;

/// A non-mutable view of a FragmentRange
///
/// Provide a trivially copyable and movable, non-mutable view on a
/// fragment range. This allows uniform ownership semantics across
/// multi-fragment ranges and the single fragment and empty fragment
/// adaptors below, i.e. it allows treating all fragment ranges
/// uniformly as views.
template <typename T>
requires FragmentRange<T>
class fragment_range_view {
    const T* _range;
public:
    using fragment_type = typename T::fragment_type;
    using iterator = typename T::const_iterator;
    using const_iterator = typename T::const_iterator;

public:
    explicit fragment_range_view(const T& range) : _range(&range) { }

    const_iterator begin() const { return _range->begin(); }
    const_iterator end() const { return _range->end(); }

    size_t size_bytes() const { return _range->size_bytes(); }
    bool empty() const { return _range->empty(); }
};

/// Single-element fragment range
///
/// This is a helper that allows converting a bytes_view into a FragmentRange.
template<mutable_view is_mutable>
class single_fragment_range {
public:
    using fragment_type = std::conditional_t<is_mutable == mutable_view::no,
                                             bytes_view, bytes_mutable_view>;
private:
    fragment_type _view;
public:
    using iterator = const fragment_type*;
    using const_iterator = const fragment_type*;

    explicit single_fragment_range(fragment_type f) : _view { f } { }

    const_iterator begin() const { return &_view; }
    const_iterator end() const { return &_view + 1; }

    size_t size_bytes() const { return _view.size(); }
    bool empty() const { return _view.empty(); }
};

single_fragment_range(bytes_view) -> single_fragment_range<mutable_view::no>;
single_fragment_range(bytes_mutable_view) -> single_fragment_range<mutable_view::yes>;

/// Empty fragment range.
struct empty_fragment_range {
    using fragment_type = bytes_view;
    using iterator = bytes_view*;
    using const_iterator = bytes_view*;

    iterator begin() const { return nullptr; }
    iterator end() const { return nullptr; }

    size_t size_bytes() const { return 0; }
    bool empty() const { return true; }
};

static_assert(FragmentRange<empty_fragment_range>);
static_assert(FragmentRange<single_fragment_range<mutable_view::no>>);
static_assert(FragmentRange<single_fragment_range<mutable_view::yes>>);

template<typename FragmentedBuffer>
requires FragmentRange<FragmentedBuffer>
bytes linearized(const FragmentedBuffer& buffer)
{
    bytes b(bytes::initialized_later(), buffer.size_bytes());
    auto dst = b.begin();
    using boost::range::for_each;
    for_each(buffer, [&] (bytes_view fragment) {
        dst = boost::copy(fragment, dst);
    });
    return b;
}

template<typename FragmentedBuffer, typename Function>
requires FragmentRange<FragmentedBuffer> && requires (Function fn, bytes_view bv) {
    fn(bv);
}
decltype(auto) with_linearized(const FragmentedBuffer& buffer, Function&& fn)
{
    bytes b;
    bytes_view bv;
    if (__builtin_expect(!buffer.empty() && std::next(buffer.begin()) == buffer.end(), true)) {
        bv = *buffer.begin();
    } else if (!buffer.empty()) {
        b = linearized(buffer);
        bv = b;
    }
    return fn(bv);
}

template<typename T>
concept FragmentedView = requires (T view, size_t n) {
    typename T::fragment_type;
    requires std::is_same_v<typename T::fragment_type, bytes_view>
            || std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
    // No preconditions.
    { view.current_fragment() } -> std::convertible_to<const typename T::fragment_type&>;
    // No preconditions.
    { view.empty() } -> std::same_as<bool>;
    // No preconditions.
    { view.size_bytes() } -> std::convertible_to<size_t>;
    // Precondition: n <= size_bytes()
    { view.prefix(n) } -> std::same_as<T>;
    // Precondition: n <= size_bytes()
    view.remove_prefix(n);
    // Precondition: size_bytes() > 0
    view.remove_current();
};

template<typename T>
concept FragmentedMutableView = requires (T view) {
    requires FragmentedView<T>;
    requires std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
};

template<FragmentedView View>
requires (!FragmentRange<View>)
bytes linearized(View v)
{
    bytes b(bytes::initialized_later(), v.size_bytes());
    auto out = b.begin();
    while (v.size_bytes()) {
        out = std::copy(v.current_fragment().begin(), v.current_fragment().end(), out);
        v.remove_current();
    }
    return b;
}

template<FragmentedView View, typename Function>
requires (!FragmentRange<View>) && std::invocable<Function, bytes_view>
decltype(auto) with_linearized(const View& v, Function&& fn)
{
    if (v.size_bytes() == v.current_fragment().size()) [[likely]] {
        return fn(v.current_fragment());
    } else {
        return fn(linearized(v));
    }
}

class single_fragmented_view {
    bytes_view _view;
public:
    using fragment_type = bytes_view;
    explicit single_fragmented_view(bytes_view bv) : _view(bv) {}
    size_t size_bytes() const { return _view.size(); }
    bool empty() const { return _view.empty(); }
    void remove_prefix(size_t n) { _view.remove_prefix(n); }
    void remove_current() { _view = bytes_view(); }
    bytes_view current_fragment() const { return _view; }
    single_fragmented_view prefix(size_t n) { return single_fragmented_view(_view.substr(0, n)); }
};
static_assert(FragmentedView<single_fragmented_view>);

template<FragmentedView View, typename Function>
requires std::invocable<Function, View> && std::invocable<Function, single_fragmented_view>
decltype(auto) with_simplified(const View& v, Function&& fn)
{
    if (v.size_bytes() == v.current_fragment().size()) [[likely]] {
        return fn(single_fragmented_view(v.current_fragment()));
    } else {
        return fn(v);
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: waitsymbol.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-03-30 08:01:45 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#if ! defined(WAITSYMBOL_HXX_INCLUDED)
#define WAITSYMBOL_HXX_INCLUDED

#include <com/sun/star/rendering/XBitmap.hpp>

#include "cppcanvas/customsprite.hxx"
#include "disposable.hxx"
#include "eventmultiplexer.hxx"
#include "unoview.hxx"

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/utility.hpp> // for noncopyable

#include <vector>

namespace presentation {
namespace internal {

class WaitSymbol : public Disposable, private boost::noncopyable
{
public:
    WaitSymbol( const com::sun::star::uno::Reference<
                    com::sun::star::rendering::XBitmap>&    xBitmap,
                EventMultiplexer&                           rEventMultiplexer );

    /** Shows the wait symbol.
     */
    void show() { setVisible(true); }

    /** Hides the wait symbol.
     */
    void hide() { setVisible(false); }

    /** Adds a view for display.
     */
    void addView( UnoViewSharedPtr const & rView );

    void removeView( UnoViewSharedPtr const & rView );

    void notifyViewChange();

    // Disposable:
    virtual void dispose();

private:
    com::sun::star::uno::Reference<
        com::sun::star::rendering::XBitmap> m_xBitmap;

    basegfx::B2DPoint calcSpritePos( UnoViewSharedPtr const & rView ) const;

    typedef std::vector<
        std::pair<UnoViewSharedPtr,
                  cppcanvas::CustomSpriteSharedPtr> > ViewsVecT;
    ViewsVecT m_views;

    EventMultiplexer& mrEventMultiplexer;

    template <typename func_type>
    void for_each_sprite( func_type const & func ) const
    {
        ViewsVecT::const_iterator iPos( m_views.begin() );
        const ViewsVecT::const_iterator iEnd( m_views.end() );
        for ( ; iPos != iEnd; ++iPos )
            func( iPos->second );
    }

    bool m_bVisible;
    void setVisible( const bool bVisible );
};

} // namespace internal
} // namespace presentation

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.5.22); FILE MERGED 2005/09/05 17:41:09 rt 1.5.22.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: waitsymbol.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 20:33:31 $
 *
 *  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
 *
 ************************************************************************/

#if ! defined(WAITSYMBOL_HXX_INCLUDED)
#define WAITSYMBOL_HXX_INCLUDED

#include <com/sun/star/rendering/XBitmap.hpp>

#include "cppcanvas/customsprite.hxx"
#include "disposable.hxx"
#include "eventmultiplexer.hxx"
#include "unoview.hxx"

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/utility.hpp> // for noncopyable

#include <vector>

namespace presentation {
namespace internal {

class WaitSymbol : public Disposable, private boost::noncopyable
{
public:
    WaitSymbol( const com::sun::star::uno::Reference<
                    com::sun::star::rendering::XBitmap>&    xBitmap,
                EventMultiplexer&                           rEventMultiplexer );

    /** Shows the wait symbol.
     */
    void show() { setVisible(true); }

    /** Hides the wait symbol.
     */
    void hide() { setVisible(false); }

    /** Adds a view for display.
     */
    void addView( UnoViewSharedPtr const & rView );

    void removeView( UnoViewSharedPtr const & rView );

    void notifyViewChange();

    // Disposable:
    virtual void dispose();

private:
    com::sun::star::uno::Reference<
        com::sun::star::rendering::XBitmap> m_xBitmap;

    basegfx::B2DPoint calcSpritePos( UnoViewSharedPtr const & rView ) const;

    typedef std::vector<
        std::pair<UnoViewSharedPtr,
                  cppcanvas::CustomSpriteSharedPtr> > ViewsVecT;
    ViewsVecT m_views;

    EventMultiplexer& mrEventMultiplexer;

    template <typename func_type>
    void for_each_sprite( func_type const & func ) const
    {
        ViewsVecT::const_iterator iPos( m_views.begin() );
        const ViewsVecT::const_iterator iEnd( m_views.end() );
        for ( ; iPos != iEnd; ++iPos )
            func( iPos->second );
    }

    bool m_bVisible;
    void setVisible( const bool bVisible );
};

} // namespace internal
} // namespace presentation

#endif
<|endoftext|>


<commit_before>// @(#)root/tree:$Name:  $:$Id: TLeaf.cxx,v 1.6 2001/11/17 15:56:00 brun Exp $
// Author: Rene Brun   12/01/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// A TLeaf describes individual elements of a TBranch                   //
//       See TBranch structure in TTree.                                //
//////////////////////////////////////////////////////////////////////////

#include "TLeaf.h"
#include "TBranch.h"
#include "TTree.h"
#include "TVirtualPad.h"
#include "TBrowser.h"

#include <ctype.h>

R__EXTERN TTree *gTree;
R__EXTERN TBranch *gBranch;

ClassImp(TLeaf)

//______________________________________________________________________________
TLeaf::TLeaf(): TNamed()
{
//*-*-*-*-*-*Default constructor for Leaf*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*        ============================
   fLen        = 0;
   //fBranch     = 0;
   fBranch     = gBranch;
   fLeafCount  = 0;
   fNdata      = 0;
   fOffset     = 0;
}

//______________________________________________________________________________
TLeaf::TLeaf(const char *name, const char *)
    :TNamed(name,name)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Create a Leaf*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      =============
//
//     See the TTree and TBranch constructors for explanation of parameters.

   fLeafCount  = GetLeafCounter(fLen);
   if (fLen == -1) {MakeZombie(); return;}
   fIsRange    = 0;
   fIsUnsigned = 0;
   fLenType    = 4;
   fNdata      = 0;
   fOffset     = 0;
   if (fLeafCount || strchr(name,'[')) {
      char newname[64];
      strcpy(newname,name);
      char *bracket = strchr(newname,'[');
      *bracket = 0;
      SetName(newname);
   }
   fBranch     = gBranch;
}

//______________________________________________________________________________
TLeaf::~TLeaf()
{
//*-*-*-*-*-*Default destructor for a Leaf*-*-*-*-*-*-*-*-*-*-*-*
//*-*        ===============================

//   if (fBranch) fBranch->GetListOfLeaves().Remove(this);
   if (!fBranch) return;
   TTree *tree = fBranch->GetTree();
   fBranch = 0;
   if (!tree) return;
   tree->GetListOfLeaves()->Remove(this);
}

//______________________________________________________________________________
void TLeaf::Browse(TBrowser *)
{
   char name[64];
   if (strchr(GetName(),'.')) {
      fBranch->GetTree()->Draw(GetName());
   } else {
      sprintf(name,"%s.%s",fBranch->GetName(),GetName());
      fBranch->GetTree()->Draw(name);
   }
   if (gPad) gPad->Update();
}

//______________________________________________________________________________
void TLeaf::FillBasket(TBuffer &)
{
//*-*-*-*-*-*-*-*-*-*-*Pack leaf elements in Basket output buffer*-*-*-*-*-*-*
//*-*                  =========================================

}

//______________________________________________________________________________
TLeaf *TLeaf::GetLeafCounter(Int_t &countval) const
{
//*-*-*-*-*-*-*Return Pointer to counter of referenced Leaf*-*-*-*-*-*-*-*
//*-*          ============================================
//
//  If leaf name has the forme var[nelem], where nelem is alphanumeric, then
//     If nelem is a leaf name, return countval = 1 and the pointer to
//     the leaf named nelem.
//  If leaf name has the forme var[nelem], where nelem is a digit, then
//     return countval = nelem and a null pointer.
//  Otherwise return countval=0 and a null pointer.
//

   countval = 1;
   const char *name = GetTitle();
   char *bleft = (char*)strchr(name,'[');
   if (!bleft) return 0;
   bleft++;
   Int_t nch = strlen(bleft);
   char *countname = new char[nch+1];
   strcpy(countname,bleft);
   char *bright = (char*)strchr(countname,']');
   if (!bright) { delete [] countname; return 0;}
   char *bleft2 = (char*)strchr(countname,'[');
   *bright = 0; nch = strlen(countname);

//*-* Now search a branch name with a leave name = countname
  TLeaf *leaf = (TLeaf*)gTree->GetListOfLeaves()->FindObject(countname);
  Int_t i;
  if (leaf) {
     countval = 1;
     leaf->SetRange();
     if (bleft2) {
        sscanf(bleft2,"[%d]",&i);
        countval *= i;
     }
     bleft = bleft2;
     while(bleft) {
        bleft2++;
        bleft = (char*)strchr(bleft2,'[');
        if (!bleft) break;
        sscanf(bleft,"[%d]",&i);
        countval *= i;
        bleft2 = bleft;
     }
     delete [] countname;
     return leaf;
  }
//*-* not found in a branch/leaf. Is it a numerical value?
   for (i=0;i<nch;i++) {
      if (!isdigit(countname[i])) {
        delete [] countname;
        countval = -1;
        return 0;
      }
   }
   sscanf(countname,"%d",&countval);
   if (bleft2) {
      sscanf(bleft2,"[%d]",&i);
      countval *= i;
   }
   bleft = bleft2;
   while(bleft) {
      bleft2++;
      bleft = (char*)strchr(bleft2,'[');
      if (!bleft) break;
      sscanf(bleft,"[%d]",&i);
      countval *= i;
      bleft2 = bleft;
   }
//*/
   delete [] countname;
   return 0;
}

//______________________________________________________________________________
Int_t TLeaf::GetLen() const
{
//*-*-*-*-*-*-*-*-*Return the number of effective elements of this leaf*-*-*-*
//*-*              ====================================================

   Int_t len;
   if (fLeafCount) {
      len = Int_t(fLeafCount->GetValue());
      if (len > fLeafCount->GetMaximum()) {
         printf("ERROR leaf:%s, len=%d and max=%d\n",GetName(),len,fLeafCount->GetMaximum());
         len = fLeafCount->GetMaximum();
      }
      return len*fLen;
   } else {
      return fLen;
   }
}

//______________________________________________________________________________
Int_t TLeaf::ResetAddress(void *add, Bool_t destructor)
{
//*-*-*-*-*-*-*-*-*-*-*Set leaf buffer data address*-*-*-*-*-*
//*-*                  ============================
//
//  This function is called by all TLeafX::SetAddress

   Int_t todelete = 0;
   if (TestBit(kNewValue)) todelete = 1;
   if (destructor) return todelete;

   if (fLeafCount) fNdata = fLen*(fLeafCount->GetMaximum() + 1);
   else            fNdata = fLen;

   ResetBit(kNewValue);
   if (!add) SetBit(kNewValue);
   return todelete;
}

//_______________________________________________________________________
void TLeaf::Streamer(TBuffer &b)
{
//*-*-*-*-*-*-*-*-*Stream a class object*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*              =========================================

   if (b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = b.ReadVersion(&R__s, &R__c);
      if (R__v > 1) {
         TLeaf::Class()->ReadBuffer(b, this, R__v, R__s, R__c);
      } else {
         //====process old versions before automatic schema evolution
         TNamed::Streamer(b);
         b >> fLen;
         b >> fLenType;
         b >> fOffset;
         b >> fIsRange;
         b >> fIsUnsigned;
         b >> fLeafCount;
         b.CheckByteCount(R__s, R__c, TLeaf::IsA());
         //====end of old versions
      }
      if (fLen == 0) fLen = 1;
      ResetBit(kNewValue);
      SetAddress();
   } else {
      TLeaf::Class()->WriteBuffer(b,this);
   }
}
<commit_msg>fix proposed by Paul Balm in GetLeafCounter in case the function is called and the fBranch pointer is not yet set.<commit_after>// @(#)root/tree:$Name:  $:$Id: TLeaf.cxx,v 1.7 2002/02/01 07:47:24 brun Exp $
// Author: Rene Brun   12/01/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// A TLeaf describes individual elements of a TBranch                   //
//       See TBranch structure in TTree.                                //
//////////////////////////////////////////////////////////////////////////

#include "TLeaf.h"
#include "TBranch.h"
#include "TTree.h"
#include "TVirtualPad.h"
#include "TBrowser.h"

#include <ctype.h>

R__EXTERN TTree *gTree;
R__EXTERN TBranch *gBranch;

ClassImp(TLeaf)

//______________________________________________________________________________
TLeaf::TLeaf(): TNamed()
{
//*-*-*-*-*-*Default constructor for Leaf*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*        ============================
   fLen        = 0;
   //fBranch     = 0;
   fBranch     = gBranch;
   fLeafCount  = 0;
   fNdata      = 0;
   fOffset     = 0;
}

//______________________________________________________________________________
TLeaf::TLeaf(const char *name, const char *)
    :TNamed(name,name)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Create a Leaf*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      =============
//
//     See the TTree and TBranch constructors for explanation of parameters.

   fLeafCount  = GetLeafCounter(fLen);
   if (fLen == -1) {MakeZombie(); return;}
   fIsRange    = 0;
   fIsUnsigned = 0;
   fLenType    = 4;
   fNdata      = 0;
   fOffset     = 0;
   if (fLeafCount || strchr(name,'[')) {
      char newname[64];
      strcpy(newname,name);
      char *bracket = strchr(newname,'[');
      *bracket = 0;
      SetName(newname);
   }
   fBranch     = gBranch;
}

//______________________________________________________________________________
TLeaf::~TLeaf()
{
//*-*-*-*-*-*Default destructor for a Leaf*-*-*-*-*-*-*-*-*-*-*-*
//*-*        ===============================

//   if (fBranch) fBranch->GetListOfLeaves().Remove(this);
   if (!fBranch) return;
   TTree *tree = fBranch->GetTree();
   fBranch = 0;
   if (!tree) return;
   tree->GetListOfLeaves()->Remove(this);
}

//______________________________________________________________________________
void TLeaf::Browse(TBrowser *)
{
   char name[64];
   if (strchr(GetName(),'.')) {
      fBranch->GetTree()->Draw(GetName());
   } else {
      sprintf(name,"%s.%s",fBranch->GetName(),GetName());
      fBranch->GetTree()->Draw(name);
   }
   if (gPad) gPad->Update();
}

//______________________________________________________________________________
void TLeaf::FillBasket(TBuffer &)
{
//*-*-*-*-*-*-*-*-*-*-*Pack leaf elements in Basket output buffer*-*-*-*-*-*-*
//*-*                  =========================================

}

//______________________________________________________________________________
TLeaf *TLeaf::GetLeafCounter(Int_t &countval) const
{
//*-*-*-*-*-*-*Return Pointer to counter of referenced Leaf*-*-*-*-*-*-*-*
//*-*          ============================================
//
//  If leaf name has the forme var[nelem], where nelem is alphanumeric, then
//     If nelem is a leaf name, return countval = 1 and the pointer to
//     the leaf named nelem.
//  If leaf name has the forme var[nelem], where nelem is a digit, then
//     return countval = nelem and a null pointer.
//  Otherwise return countval=0 and a null pointer.
//

   countval = 1;
   const char *name = GetTitle();
   char *bleft = (char*)strchr(name,'[');
   if (!bleft) return 0;
   bleft++;
   Int_t nch = strlen(bleft);
   char *countname = new char[nch+1];
   strcpy(countname,bleft);
   char *bright = (char*)strchr(countname,']');
   if (!bright) { delete [] countname; return 0;}
   char *bleft2 = (char*)strchr(countname,'[');
   *bright = 0; nch = strlen(countname);

   //*-* Now search a branch name with a leave name = countname
   //    We search for the leaf in the ListOfLeaves from the TTree. We can in principle
   //    access the TTree by calling fBranch()->GetTree(), but fBranch is not set if this
   //    method is called from the TLeaf constructor. In that case, use global pointer
   //    gTree.
   //    Also, if fBranch is set, but fBranch->GetTree() returns NULL, use gTree.
  TTree* pTree = fBranch ? fBranch->GetTree() : gTree;
  if(pTree==NULL) pTree = gTree;
  TLeaf *leaf = (TLeaf*) pTree->GetListOfLeaves()->FindObject(countname);
  Int_t i;
  if (leaf) {
     countval = 1;
     leaf->SetRange();
     if (bleft2) {
        sscanf(bleft2,"[%d]",&i);
        countval *= i;
     }
     bleft = bleft2;
     while(bleft) {
        bleft2++;
        bleft = (char*)strchr(bleft2,'[');
        if (!bleft) break;
        sscanf(bleft,"[%d]",&i);
        countval *= i;
        bleft2 = bleft;
     }
     delete [] countname;
     return leaf;
  }
//*-* not found in a branch/leaf. Is it a numerical value?
   for (i=0;i<nch;i++) {
      if (!isdigit(countname[i])) {
        delete [] countname;
        countval = -1;
        return 0;
      }
   }
   sscanf(countname,"%d",&countval);
   if (bleft2) {
      sscanf(bleft2,"[%d]",&i);
      countval *= i;
   }
   bleft = bleft2;
   while(bleft) {
      bleft2++;
      bleft = (char*)strchr(bleft2,'[');
      if (!bleft) break;
      sscanf(bleft,"[%d]",&i);
      countval *= i;
      bleft2 = bleft;
   }
//*/
   delete [] countname;
   return 0;
}

//______________________________________________________________________________
Int_t TLeaf::GetLen() const
{
//*-*-*-*-*-*-*-*-*Return the number of effective elements of this leaf*-*-*-*
//*-*              ====================================================

   Int_t len;
   if (fLeafCount) {
      len = Int_t(fLeafCount->GetValue());
      if (len > fLeafCount->GetMaximum()) {
         printf("ERROR leaf:%s, len=%d and max=%d\n",GetName(),len,fLeafCount->GetMaximum());
         len = fLeafCount->GetMaximum();
      }
      return len*fLen;
   } else {
      return fLen;
   }
}

//______________________________________________________________________________
Int_t TLeaf::ResetAddress(void *add, Bool_t destructor)
{
//*-*-*-*-*-*-*-*-*-*-*Set leaf buffer data address*-*-*-*-*-*
//*-*                  ============================
//
//  This function is called by all TLeafX::SetAddress

   Int_t todelete = 0;
   if (TestBit(kNewValue)) todelete = 1;
   if (destructor) return todelete;

   if (fLeafCount) fNdata = fLen*(fLeafCount->GetMaximum() + 1);
   else            fNdata = fLen;

   ResetBit(kNewValue);
   if (!add) SetBit(kNewValue);
   return todelete;
}

//_______________________________________________________________________
void TLeaf::Streamer(TBuffer &b)
{
//*-*-*-*-*-*-*-*-*Stream a class object*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*              =========================================

   if (b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = b.ReadVersion(&R__s, &R__c);
      if (R__v > 1) {
         TLeaf::Class()->ReadBuffer(b, this, R__v, R__s, R__c);
      } else {
         //====process old versions before automatic schema evolution
         TNamed::Streamer(b);
         b >> fLen;
         b >> fLenType;
         b >> fOffset;
         b >> fIsRange;
         b >> fIsUnsigned;
         b >> fLeafCount;
         b.CheckByteCount(R__s, R__c, TLeaf::IsA());
         //====end of old versions
      }
      if (fLen == 0) fLen = 1;
      ResetBit(kNewValue);
      SetAddress();
   } else {
      TLeaf::Class()->WriteBuffer(b,this);
   }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: kdedata.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: hr $ $Date: 2006-08-11 17:48:02 $
 *
 *  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
 *
 ************************************************************************/

#define _SV_SALDATA_CXX

#ifndef INCLUDED_VCL_KDE_HEADERS_H
#include "kde_headers.h"
#endif

#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <poll.h>
#ifdef FREEBSD
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#ifndef _VCL_KDEDATA_HXX
#include <plugins/kde/kdedata.hxx>
#endif
#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#include <osl/module.h>

#include <tools/debug.hxx>

#ifndef _SAL_I18N_INPUTMETHOD_HXX
#include "i18n_im.hxx"
#endif
#ifndef _SAL_I18N_XKBDEXTENSION_HXX
#include "i18n_xkb.hxx"
#endif

#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif
#ifndef _VOS_MUTEX_HXX
#include <vos/mutex.hxx>
#endif

/* #i59042# override KApplications method for session management
 * since it will interfere badly with our own.
 */
class VCLKDEApplication : public KApplication
{
    public:
    VCLKDEApplication() : KApplication() {}

    virtual void commitData(QSessionManager &sm);
};

void VCLKDEApplication::commitData(QSessionManager&)
{
}

/***************************************************************************
 * class SalKDEDisplay                                                     *
 ***************************************************************************/

SalKDEDisplay::SalKDEDisplay( Display* pDisp, Visual* pVisual, Colormap aColMap )
    : SalX11Display( pDisp, pVisual, aColMap, false )
{
}

SalKDEDisplay::~SalKDEDisplay()
{
    // in case never a frame opened
    static_cast<KDEXLib*>(GetXLib())->doStartup();
    // clean up own members
    doDestruct();
    // prevent SalDisplay from closing KApplication's display
    pDisp_ = NULL;
}

/***************************************************************************
 * class KDEXLib                                                           *
 ***************************************************************************/

KDEXLib::~KDEXLib()
{
    // properly deinitialize KApplication
    delete (VCLKDEApplication*)m_pApplication;
    // free the faked cmdline arguments no longer needed by KApplication
    for( int i = 0; i < m_nFakeCmdLineArgs; i++ )
        free( m_pFreeCmdLineArgs[i] );
    delete [] m_pFreeCmdLineArgs;
    delete [] m_pAppCmdLineArgs;
}

void KDEXLib::Init()
{
    SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod;
    pInputMethod->SetLocale();
    XrmInitialize();

    KAboutData *kAboutData = new KAboutData( "OpenOffice.org",
            I18N_NOOP( "OpenOffice.org" ),
            "1.1.0",
            I18N_NOOP( "OpenOffice.org with KDE Native Widget Support." ),
            KAboutData::License_LGPL,
            "(c) 2003, 2004 Novell, Inc",
            I18N_NOOP( "OpenOffice.org is an office suite.\n" ),
            "http://kde.openoffice.org/index.html",
            "dev@kde.openoffice.org");
    kAboutData->addAuthor( "Jan Holesovsky",
            I18N_NOOP( "Original author and maintainer of the KDE NWF." ),
            "kendy@artax.karlin.mff.cuni.cz",
            "http://artax.karlin.mff.cuni.cz/~kendy" );

    m_nFakeCmdLineArgs = 1;
    USHORT nIdx;
    vos::OExtCommandLine aCommandLine;
    int nParams = aCommandLine.getCommandArgCount();
    rtl::OString aDisplay;
    rtl::OUString aParam, aBin;

    for ( nIdx = 0; nIdx < nParams; ++nIdx )
    {
        aCommandLine.getCommandArg( nIdx, aParam );
        if ( !m_pFreeCmdLineArgs && aParam.equalsAscii( "-display" ) && nIdx + 1 < nParams )
        {
            aCommandLine.getCommandArg( nIdx + 1, aParam );
            aDisplay = rtl::OUStringToOString( aParam, osl_getThreadTextEncoding() );

            m_nFakeCmdLineArgs = 3;
            m_pFreeCmdLineArgs = new char*[ m_nFakeCmdLineArgs ];
            m_pFreeCmdLineArgs[ 1 ] = strdup( "-display" );
            m_pFreeCmdLineArgs[ 2 ] = strdup( aDisplay.getStr() );
        }
    }
    if ( !m_pFreeCmdLineArgs )
        m_pFreeCmdLineArgs = new char*[ m_nFakeCmdLineArgs ];

    osl_getExecutableFile( &aParam.pData );
    osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
    rtl::OString aExec = rtl::OUStringToOString( aBin, osl_getThreadTextEncoding() );
    m_pFreeCmdLineArgs[0] = strdup( aExec.getStr() );

    // make a copy of the string list for freeing it since
    // KApplication manipulates the pointers inside the argument vector
    // note: KApplication bad !
    m_pAppCmdLineArgs = new char*[ m_nFakeCmdLineArgs ];
    for( int i = 0; i < m_nFakeCmdLineArgs; i++ )
        m_pAppCmdLineArgs[i] = m_pFreeCmdLineArgs[i];

    KCmdLineArgs::init( m_nFakeCmdLineArgs, m_pAppCmdLineArgs, kAboutData );

    KApplication::disableAutoDcopRegistration();
    m_pApplication = new VCLKDEApplication();
    kapp->disableSessionManagement();

    Display* pDisp = QPaintDevice::x11AppDisplay();

    SalDisplay *pSalDisplay = new SalKDEDisplay( pDisp,
            static_cast< Visual * >( QPaintDevice::x11AppVisual() ),
            QPaintDevice::x11AppColormap() );

    XSetIOErrorHandler    ( (XIOErrorHandler)X11SalData::XIOErrorHdl );
    XSetErrorHandler      ( (XErrorHandler)X11SalData::XErrorHdl );

    pInputMethod->CreateMethod( pDisp );
    pInputMethod->AddConnectionWatch( pDisp, (void*)this );
    pSalDisplay->SetInputMethod( pInputMethod );

    sal_Bool bOldErrorSetting = GetIgnoreXErrors();
    SetIgnoreXErrors( True );
    SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
    XSync( pDisp, False );

    pKbdExtension->UseExtension( ! WasXError() );
    SetIgnoreXErrors( bOldErrorSetting );

    pSalDisplay->SetKbdExtension( pKbdExtension );
}

void KDEXLib::doStartup()
{
    if( ! m_bStartupDone )
    {
        KStartupInfo::appStarted();
        m_bStartupDone = true;
        #if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "called KStartupInfo::appStarted()\n" );
        #endif
    }
}

/**********************************************************************
 * class KDEData                                                      *
 **********************************************************************/

KDEData::~KDEData()
{
}

void KDEData::Init()
{
    pXLib_ = new KDEXLib();
    pXLib_->Init();
}

/**********************************************************************
 * plugin entry point                                                 *
 **********************************************************************/

extern "C" {
    VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule )
    {
        rtl::OString aVersion( qVersion() );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "qt version string is \"%s\"\n", aVersion.getStr() );
#endif
        sal_Int32 nIndex = 0, nMajor = 0, nMinor = 0, nMicro = 0;
        nMajor = aVersion.getToken( 0, '.', nIndex ).toInt32();
        if( nIndex > 0 )
            nMinor = aVersion.getToken( 0, '.', nIndex ).toInt32();
        if( nIndex > 0 )
            nMicro = aVersion.getToken( 0, '.', nIndex ).toInt32();
        if( nMajor != 3 || nMinor < 2 || (nMinor == 2 && nMicro < 2) )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "unsuitable qt version %d.%d.%d\n", nMajor, nMinor, nMicro );
#endif
            return NULL;
        }

        KDESalInstance* pInstance = new KDESalInstance( new SalYieldMutex() );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "created KDESalInstance 0x%p\n", pInstance );
#endif

        // initialize SalData
        KDEData *pSalData = new KDEData();
        SetSalData( pSalData );
        pSalData->m_pInstance = pInstance;
        pSalData->Init();
        pSalData->initNWF();

        return pInstance;
    }
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.15.4); FILE MERGED 2006/09/01 17:58:03 kaib 1.15.4.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: kdedata.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 12:30:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#define _SV_SALDATA_CXX

#ifndef INCLUDED_VCL_KDE_HEADERS_H
#include "kde_headers.h"
#endif

#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <poll.h>
#ifdef FREEBSD
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#ifndef _VCL_KDEDATA_HXX
#include <plugins/kde/kdedata.hxx>
#endif
#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#include <osl/module.h>

#include <tools/debug.hxx>

#ifndef _SAL_I18N_INPUTMETHOD_HXX
#include "i18n_im.hxx"
#endif
#ifndef _SAL_I18N_XKBDEXTENSION_HXX
#include "i18n_xkb.hxx"
#endif

#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif
#ifndef _VOS_MUTEX_HXX
#include <vos/mutex.hxx>
#endif

/* #i59042# override KApplications method for session management
 * since it will interfere badly with our own.
 */
class VCLKDEApplication : public KApplication
{
    public:
    VCLKDEApplication() : KApplication() {}

    virtual void commitData(QSessionManager &sm);
};

void VCLKDEApplication::commitData(QSessionManager&)
{
}

/***************************************************************************
 * class SalKDEDisplay                                                     *
 ***************************************************************************/

SalKDEDisplay::SalKDEDisplay( Display* pDisp, Visual* pVisual, Colormap aColMap )
    : SalX11Display( pDisp, pVisual, aColMap, false )
{
}

SalKDEDisplay::~SalKDEDisplay()
{
    // in case never a frame opened
    static_cast<KDEXLib*>(GetXLib())->doStartup();
    // clean up own members
    doDestruct();
    // prevent SalDisplay from closing KApplication's display
    pDisp_ = NULL;
}

/***************************************************************************
 * class KDEXLib                                                           *
 ***************************************************************************/

KDEXLib::~KDEXLib()
{
    // properly deinitialize KApplication
    delete (VCLKDEApplication*)m_pApplication;
    // free the faked cmdline arguments no longer needed by KApplication
    for( int i = 0; i < m_nFakeCmdLineArgs; i++ )
        free( m_pFreeCmdLineArgs[i] );
    delete [] m_pFreeCmdLineArgs;
    delete [] m_pAppCmdLineArgs;
}

void KDEXLib::Init()
{
    SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod;
    pInputMethod->SetLocale();
    XrmInitialize();

    KAboutData *kAboutData = new KAboutData( "OpenOffice.org",
            I18N_NOOP( "OpenOffice.org" ),
            "1.1.0",
            I18N_NOOP( "OpenOffice.org with KDE Native Widget Support." ),
            KAboutData::License_LGPL,
            "(c) 2003, 2004 Novell, Inc",
            I18N_NOOP( "OpenOffice.org is an office suite.\n" ),
            "http://kde.openoffice.org/index.html",
            "dev@kde.openoffice.org");
    kAboutData->addAuthor( "Jan Holesovsky",
            I18N_NOOP( "Original author and maintainer of the KDE NWF." ),
            "kendy@artax.karlin.mff.cuni.cz",
            "http://artax.karlin.mff.cuni.cz/~kendy" );

    m_nFakeCmdLineArgs = 1;
    USHORT nIdx;
    vos::OExtCommandLine aCommandLine;
    int nParams = aCommandLine.getCommandArgCount();
    rtl::OString aDisplay;
    rtl::OUString aParam, aBin;

    for ( nIdx = 0; nIdx < nParams; ++nIdx )
    {
        aCommandLine.getCommandArg( nIdx, aParam );
        if ( !m_pFreeCmdLineArgs && aParam.equalsAscii( "-display" ) && nIdx + 1 < nParams )
        {
            aCommandLine.getCommandArg( nIdx + 1, aParam );
            aDisplay = rtl::OUStringToOString( aParam, osl_getThreadTextEncoding() );

            m_nFakeCmdLineArgs = 3;
            m_pFreeCmdLineArgs = new char*[ m_nFakeCmdLineArgs ];
            m_pFreeCmdLineArgs[ 1 ] = strdup( "-display" );
            m_pFreeCmdLineArgs[ 2 ] = strdup( aDisplay.getStr() );
        }
    }
    if ( !m_pFreeCmdLineArgs )
        m_pFreeCmdLineArgs = new char*[ m_nFakeCmdLineArgs ];

    osl_getExecutableFile( &aParam.pData );
    osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
    rtl::OString aExec = rtl::OUStringToOString( aBin, osl_getThreadTextEncoding() );
    m_pFreeCmdLineArgs[0] = strdup( aExec.getStr() );

    // make a copy of the string list for freeing it since
    // KApplication manipulates the pointers inside the argument vector
    // note: KApplication bad !
    m_pAppCmdLineArgs = new char*[ m_nFakeCmdLineArgs ];
    for( int i = 0; i < m_nFakeCmdLineArgs; i++ )
        m_pAppCmdLineArgs[i] = m_pFreeCmdLineArgs[i];

    KCmdLineArgs::init( m_nFakeCmdLineArgs, m_pAppCmdLineArgs, kAboutData );

    KApplication::disableAutoDcopRegistration();
    m_pApplication = new VCLKDEApplication();
    kapp->disableSessionManagement();

    Display* pDisp = QPaintDevice::x11AppDisplay();

    SalDisplay *pSalDisplay = new SalKDEDisplay( pDisp,
            static_cast< Visual * >( QPaintDevice::x11AppVisual() ),
            QPaintDevice::x11AppColormap() );

    XSetIOErrorHandler    ( (XIOErrorHandler)X11SalData::XIOErrorHdl );
    XSetErrorHandler      ( (XErrorHandler)X11SalData::XErrorHdl );

    pInputMethod->CreateMethod( pDisp );
    pInputMethod->AddConnectionWatch( pDisp, (void*)this );
    pSalDisplay->SetInputMethod( pInputMethod );

    sal_Bool bOldErrorSetting = GetIgnoreXErrors();
    SetIgnoreXErrors( True );
    SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
    XSync( pDisp, False );

    pKbdExtension->UseExtension( ! WasXError() );
    SetIgnoreXErrors( bOldErrorSetting );

    pSalDisplay->SetKbdExtension( pKbdExtension );
}

void KDEXLib::doStartup()
{
    if( ! m_bStartupDone )
    {
        KStartupInfo::appStarted();
        m_bStartupDone = true;
        #if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "called KStartupInfo::appStarted()\n" );
        #endif
    }
}

/**********************************************************************
 * class KDEData                                                      *
 **********************************************************************/

KDEData::~KDEData()
{
}

void KDEData::Init()
{
    pXLib_ = new KDEXLib();
    pXLib_->Init();
}

/**********************************************************************
 * plugin entry point                                                 *
 **********************************************************************/

extern "C" {
    VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule )
    {
        rtl::OString aVersion( qVersion() );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "qt version string is \"%s\"\n", aVersion.getStr() );
#endif
        sal_Int32 nIndex = 0, nMajor = 0, nMinor = 0, nMicro = 0;
        nMajor = aVersion.getToken( 0, '.', nIndex ).toInt32();
        if( nIndex > 0 )
            nMinor = aVersion.getToken( 0, '.', nIndex ).toInt32();
        if( nIndex > 0 )
            nMicro = aVersion.getToken( 0, '.', nIndex ).toInt32();
        if( nMajor != 3 || nMinor < 2 || (nMinor == 2 && nMicro < 2) )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "unsuitable qt version %d.%d.%d\n", nMajor, nMinor, nMicro );
#endif
            return NULL;
        }

        KDESalInstance* pInstance = new KDESalInstance( new SalYieldMutex() );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "created KDESalInstance 0x%p\n", pInstance );
#endif

        // initialize SalData
        KDEData *pSalData = new KDEData();
        SetSalData( pSalData );
        pSalData->m_pInstance = pInstance;
        pSalData->Init();
        pSalData->initNWF();

        return pInstance;
    }
}
<|endoftext|>


<commit_before>#include "Transcriptome.h"
#include "ReadAlign.h"
#include "serviceFuns.cpp"
#include "AlignVsTranscript.h"
#include "ReadAnnotations.h"
#include <bitset>

int alignToTranscript(Transcript &aG, uint trS1, uint8 trStr1, uint32 *exSE1, uint32 *exLenCum1, uint16 exN1)
{
    //returned values: 1: align fully agrees with transcript, including splices
    //                 2: align is fully exonic, but not concordant
    //                 3: align is fully intronic
    //                 4: align has blocks mapping to exons and introns, but no spanning
    //                 5: align spans exon/intron boundary

    bool alignIntronic      =false;
    bool alignExonic        =false;
    bool alignSpansExonIntr =false;
    bool alignSJconcordant  =true;

    //we assume that align is fully contained in the transcript, i.e. alignStart>=trStart, alignEnd<=trEnd
    //find exon that overlaps beginning of the read
    //uint32 g1=aG.exons[0][EX_G]-trS1;//start of the align
    //uint32 ex1=binarySearch1<uint32>(g1, exSE1, 2*exN1) / 2;// ex1start<=alignStart

    //TODO
    //iab=0;
    //distTSS=aG.exons[iab][EX_G]-trS1-exSE1[2*ex1]+exLenCum1[ex1];
    //iab=aG.nExons-1;
    //distTTS=trLen[tr1]-(gthaG.exons[iab][EX_G]-trS1-exSE1[2*ex1]+exLenCum1[ex1]+aG.exons[iab][EX_L]);
    //if trStr1==2: TTS=trLen[tr1]-TTS, TSS=trLen[tr1]-TSS

    //aG.canonSJ[aG.nExons-1]=-999; //marks the last block
    for (uint32 iab=0, ex1=0, bS=0, bE=0, eE=0, enS=0;
                iab<aG.nExons; iab++) {//scan through all blocks of the align

        uint64 bEprev=bE;

        bS=(uint32) (aG.exons[iab][EX_G]-trS1);//block start
        bE=bS+aG.exons[iab][EX_L]-1;//block end

        if (iab==0 || aG.canonSJ[iab-1]==-3) {//start of alig, or jump to another mate
            ex1=binarySearch1<uint32>(bS, exSE1, 2*exN1) / 2;// alignStart>=ex1start
        } else if (aG.canonSJ[iab-1]>=0) {//splice junction
            if (bEprev == eE && bS == enS) {//eE and enS are still from the old ex1
                ++ex1; //junction agrees
            } else {
                alignSJconcordant = false;
                ex1=binarySearch1<uint32>(bS, exSE1, 2*exN1) / 2;// alignStart>=ex1start
            };
        };

        //uint64 eS=exSE1[2*ex1];
        eE  = exSE1[2*ex1+1];
        enS = ex1+1<exN1 ? exSE1[2*(ex1+1)] : 0;//next exon start

        if (bS <= eE) {//block starts in the ex1 exon
            if (bE > eE) {
                alignSpansExonIntr = true;
                break;//if ex/in span is detected, no need to check anything else
            };
            alignExonic = true;
        } else {//block starts in the intron
            if (bE >= enS) {//block overlaps next exon
                alignSpansExonIntr = true;
                break;//if ex/in span is detected, no need to check anything else
            };
            alignIntronic = true;
        };
    };//cycle over align blocks

    if (!alignSJconcordant) //if align has a junction, it's always checked for concordance
        return -1;          //even for exon/intron aligns, sjs have to be concordant, otherwise align is not consistent with this transcript model

    if (alignSpansExonIntr) {
        return AlignVsTranscript::ExonIntronSpan; //align spans exon/intron boundary
    } else if (!alignIntronic) {//align is purely exonic
        return AlignVsTranscript::Concordant; //align is fully exonic and concordant
        //this cannot happen anymore, since we are non-concordant alignments return -1 above
        //if (alignSJconcordant) {
        //    return AlignVsTranscript::Concordant; //align is concordant with the transcript, i.e. fully agrees with transcript, including splices
        // } else {
        //    return AlignVsTranscript::Exon; //align is fully exonic, but not concordant
        //};
    } else {//align has introns
        if (alignExonic) {
            return AlignVsTranscript::ExonIntron; //mixed exonic/intronic align, but no span
        } else {
            return AlignVsTranscript::Intron; //purely intronic align
        };
    };

    return (uint32)-1; //this should not happen
};

void Transcriptome::classifyAlign (Transcript **alignG, uint64 nAlignG, ReadAnnotations &readAnnot)
{
    readAnnot.transcriptConcordant={};
    readAnnot.geneConcordant={};

    //array<bool,AlignVsTranscript::N> reAnn={false};
    uint32 reGe=(uint32)-2;//so that the first gene can be recorded
    std::bitset<velocytoTypeGeneBits> reAnn; //initialized to 0 (false)

    for (uint iag=0; iag<nAlignG; iag++) {

        Transcript &aG=*alignG[iag];

        //binary search through transcript starts
        uint32 tr1=binarySearch1a<uint>(aG.exons[0][EX_G], trS, nTr);//tr1 has the maximum transcript start such that it is still <= align start
        if (tr1==(uint32) -1)
            continue; //this alignment is outside of range of all transcripts

        uint aGend=aG.exons[aG.nExons-1][EX_G]+aG.exons[aG.nExons-1][EX_L]-1;

        ++tr1;
        do {//cycle back through all the transcripts
            --tr1;
            if ( aGend>trE[tr1] ||
                 (P.pSolo.strand >= 0 && (trStr[tr1]==1 ? aG.Str : 1-aG.Str) != (uint32)P.pSolo.strand) ) //!(this transcript contains the read, and has correct strand)
                     continue;

            int aStatus=alignToTranscript(aG, trS[tr1], trStr[tr1], exSE+2*trExI[tr1], exLenCum+trExI[tr1], trExN[tr1]);

            if (aStatus<0)
                continue; //align is not concordant with this transcript because one of the align junctions does not match transcript junction

            if (aStatus==AlignVsTranscript::Concordant) {//align conforms with the transcript

                //TODO!!!FIX THIS//uint32 distTTS=trLen[tr1]-(aTall[nAtr].exons[aTall[nAtr].nExons-1][EX_G] + aTall[nAtr].exons[aTall[nAtr].nExons-1][EX_L]);
                //readAnnot.transcriptConcordant.push_back({tr1,distTTS});

                readAnnot.geneConcordant.insert(trGene[tr1]);//genes for all alignments
                aG.alignGenes.insert(trGene[tr1]);//genes for each alignment
            };

            if (reGe==(uint32)-2) //first gene
                reGe=trGene[tr1];
            if (reGe!=trGene[tr1])
                reGe=(uint32)-1; //marks multi-gene align

            if (aStatus!=AlignVsTranscript::ExonIntronSpan) {
                reAnn.set(AlignVsTranscript::ExonIntronSpan, true);//meaning of this bit is NoExonIntronSpan
                reAnn.set(aStatus, true);
            };

        } while (trEmax[tr1]>=aGend && tr1>0);
    };

    //velocyto logic
    readAnnot.geneVelocyto[0]=(reGe+2==0 ? (uint32)-1 : reGe);//-2 marks no gene, convert to -1 which marks either no gene or multigene - no output
    readAnnot.geneVelocyto[1]=reAnn.to_ulong();

//     if (reAnn[AlignVsTranscript::ExonIntronSpan]) {
//         readAnnot.geneVelocyto[1]=0;
//     } else if (reAnn[AlignVsTranscript::Concordant] || reAnn[AlignVsTranscript::Exon]) {//at least one model is exonic
//         if (!reAnn[AlignVsTranscript::Intron] && !reAnn[AlignVsTranscript::ExonIntron]) {
//             readAnnot.geneVelocyto[1]=1; //spliced
//         } else {
//             readAnnot.geneVelocyto[1]=3; //ambiguous <= exonic * ( intronic || mixed)
//         };
//     } else {//all other combinations are unspliced, as they do not contain a single purely exonic model
//         readAnnot.geneVelocyto[1]=2;
//     };

//     if (reGe==(uint32)-1) {//multi-gene
//         readAnnot.geneVelocyto[1]=0;//value does not matter, it will not be recorded
//     } else if (reAnn[AlignVsTranscript::ExonIntronSpan]) {
//         readAnnot.geneVelocyto[1]=2; //unspliced
//     } else if (reAnn[AlignVsTranscript::Concordant] || reAnn[AlignVsTranscript::Exon]) {//at least one model is exonic
//         if (!reAnn[AlignVsTranscript::Intron] && !reAnn[AlignVsTranscript::ExonIntron]) {
//             readAnnot.geneVelocyto[1]=1; //spliced
//         } else {
//             readAnnot.geneVelocyto[1]=3; //ambiguous <= exonic * ( intronic || mixed)
//         };
//     } else {//all other combinations are unspliced, as they do not contain a single purely exonic model
//         readAnnot.geneVelocyto[1]=2;
//     };
};
<commit_msg>Multimapping aligns are no longer considered for Velocyto counting.<commit_after>#include "Transcriptome.h"
#include "ReadAlign.h"
#include "serviceFuns.cpp"
#include "AlignVsTranscript.h"
#include "ReadAnnotations.h"
#include <bitset>

int alignToTranscript(Transcript &aG, uint trS1, uint8 trStr1, uint32 *exSE1, uint32 *exLenCum1, uint16 exN1)
{
    //returned values: 1: align fully agrees with transcript, including splices
    //                 2: align is fully exonic, but not concordant
    //                 3: align is fully intronic
    //                 4: align has blocks mapping to exons and introns, but no spanning
    //                 5: align spans exon/intron boundary

    bool alignIntronic      =false;
    bool alignExonic        =false;
    bool alignSpansExonIntr =false;
    bool alignSJconcordant  =true;

    //we assume that align is fully contained in the transcript, i.e. alignStart>=trStart, alignEnd<=trEnd
    //find exon that overlaps beginning of the read
    //uint32 g1=aG.exons[0][EX_G]-trS1;//start of the align
    //uint32 ex1=binarySearch1<uint32>(g1, exSE1, 2*exN1) / 2;// ex1start<=alignStart

    //TODO
    //iab=0;
    //distTSS=aG.exons[iab][EX_G]-trS1-exSE1[2*ex1]+exLenCum1[ex1];
    //iab=aG.nExons-1;
    //distTTS=trLen[tr1]-(gthaG.exons[iab][EX_G]-trS1-exSE1[2*ex1]+exLenCum1[ex1]+aG.exons[iab][EX_L]);
    //if trStr1==2: TTS=trLen[tr1]-TTS, TSS=trLen[tr1]-TSS

    //aG.canonSJ[aG.nExons-1]=-999; //marks the last block
    for (uint32 iab=0, ex1=0, bS=0, bE=0, eE=0, enS=0;
                iab<aG.nExons; iab++) {//scan through all blocks of the align

        uint64 bEprev=bE;

        bS=(uint32) (aG.exons[iab][EX_G]-trS1);//block start
        bE=bS+aG.exons[iab][EX_L]-1;//block end

        if (iab==0 || aG.canonSJ[iab-1]==-3) {//start of alig, or jump to another mate
            ex1=binarySearch1<uint32>(bS, exSE1, 2*exN1) / 2;// alignStart>=ex1start
        } else if (aG.canonSJ[iab-1]>=0) {//splice junction
            if (bEprev == eE && bS == enS) {//eE and enS are still from the old ex1
                ++ex1; //junction agrees
            } else {
                alignSJconcordant = false;
                ex1=binarySearch1<uint32>(bS, exSE1, 2*exN1) / 2;// alignStart>=ex1start
            };
        };

        //uint64 eS=exSE1[2*ex1];
        eE  = exSE1[2*ex1+1];
        enS = ex1+1<exN1 ? exSE1[2*(ex1+1)] : 0;//next exon start

        if (bS <= eE) {//block starts in the ex1 exon
            if (bE > eE) {
                alignSpansExonIntr = true;
                //break;//if ex/in span is detected, no need to check anything else - no true : might still have non-concordant junction
            };
            alignExonic = true;
        } else {//block starts in the intron
            if (bE >= enS) {//block overlaps next exon
                alignSpansExonIntr = true;
                //break;//if ex/in span is detected, no need to check anything else
            };
            alignIntronic = true;
        };
    };//cycle over align blocks

    if (!alignSJconcordant) //if align has a junction, it's always checked for concordance
        return -1;          //even for exon/intron aligns, sjs have to be concordant, otherwise align is not consistent with this transcript model

    if (alignSpansExonIntr) {
        return AlignVsTranscript::ExonIntronSpan; //align spans exon/intron boundary
    } else if (!alignIntronic) {//align is purely exonic
        return AlignVsTranscript::Concordant; //align is fully exonic and concordant
        //this cannot happen anymore, since we are non-concordant alignments return -1 above
        //if (alignSJconcordant) {
        //    return AlignVsTranscript::Concordant; //align is concordant with the transcript, i.e. fully agrees with transcript, including splices
        // } else {
        //    return AlignVsTranscript::Exon; //align is fully exonic, but not concordant
        //};
    } else {//align has introns
        if (alignExonic) {
            return AlignVsTranscript::ExonIntron; //mixed exonic/intronic align, but no span
        } else {
            return AlignVsTranscript::Intron; //purely intronic align
        };
    };

    return (uint32)-1; //this should not happen
};

void Transcriptome::classifyAlign (Transcript **alignG, uint64 nAlignG, ReadAnnotations &readAnnot)
{
    readAnnot.transcriptConcordant={};
    readAnnot.geneConcordant={};

    //array<bool,AlignVsTranscript::N> reAnn={false};
    uint32 reGe=(uint32)-2;//so that the first gene can be recorded
    std::bitset<velocytoTypeGeneBits> reAnn; //initialized to 0 (false)

    for (uint iag=0; iag<nAlignG; iag++) {

        Transcript &aG=*alignG[iag];

        //binary search through transcript starts
        uint32 tr1=binarySearch1a<uint>(aG.exons[0][EX_G], trS, nTr);//tr1 has the maximum transcript start such that it is still <= align start
        if (tr1==(uint32) -1)
            continue; //this alignment is outside of range of all transcripts

        uint aGend=aG.exons[aG.nExons-1][EX_G]+aG.exons[aG.nExons-1][EX_L]-1;

        ++tr1;
        do {//cycle back through all the transcripts
            --tr1;
            if ( aGend>trE[tr1] ||
                 (P.pSolo.strand >= 0 && (trStr[tr1]==1 ? aG.Str : 1-aG.Str) != (uint32)P.pSolo.strand) ) //!(this transcript contains the read, and has correct strand)
                     continue;

            int aStatus=alignToTranscript(aG, trS[tr1], trStr[tr1], exSE+2*trExI[tr1], exLenCum+trExI[tr1], trExN[tr1]);

            if (aStatus<0)
                continue; //align is not concordant with this transcript because one of the align junctions does not match transcript junction

            if (aStatus==AlignVsTranscript::Concordant) {//align conforms with the transcript

                //TODO!!!FIX THIS//uint32 distTTS=trLen[tr1]-(aTall[nAtr].exons[aTall[nAtr].nExons-1][EX_G] + aTall[nAtr].exons[aTall[nAtr].nExons-1][EX_L]);
                //readAnnot.transcriptConcordant.push_back({tr1,distTTS});

                readAnnot.geneConcordant.insert(trGene[tr1]);//genes for all alignments
                aG.alignGenes.insert(trGene[tr1]);//genes for each alignment
            };

            if (nAlignG>1)
                reGe=(uint32)-1; //marks multi-gene align

            //calculate reAnn
            if (reGe+1!=0) {//not multi-mapper

                if (reGe+2==0) //first gene
                    reGe=trGene[tr1];

                if (reGe!=trGene[tr1]) {//
                    reGe=(uint32)-1; //marks multi-gene align
                } else {
                    if (aStatus!=AlignVsTranscript::ExonIntronSpan) {
                        reAnn.set(AlignVsTranscript::ExonIntronSpan, true);//meaning of this bit is NoExonIntronSpan
                        reAnn.set(aStatus, true);
                    };
                };
            };

        } while (trEmax[tr1]>=aGend && tr1>0);
    };

    //velocyto logic
    readAnnot.geneVelocyto[0]=(reGe+2==0 ? (uint32)-1 : reGe);//-2 marks no gene, convert to -1 which marks either no gene or multigene - no output
    readAnnot.geneVelocyto[1]=reAnn.to_ulong();

//     if (reAnn[AlignVsTranscript::ExonIntronSpan]) {
//         readAnnot.geneVelocyto[1]=0;
//     } else if (reAnn[AlignVsTranscript::Concordant] || reAnn[AlignVsTranscript::Exon]) {//at least one model is exonic
//         if (!reAnn[AlignVsTranscript::Intron] && !reAnn[AlignVsTranscript::ExonIntron]) {
//             readAnnot.geneVelocyto[1]=1; //spliced
//         } else {
//             readAnnot.geneVelocyto[1]=3; //ambiguous <= exonic * ( intronic || mixed)
//         };
//     } else {//all other combinations are unspliced, as they do not contain a single purely exonic model
//         readAnnot.geneVelocyto[1]=2;
//     };

//     if (reGe==(uint32)-1) {//multi-gene
//         readAnnot.geneVelocyto[1]=0;//value does not matter, it will not be recorded
//     } else if (reAnn[AlignVsTranscript::ExonIntronSpan]) {
//         readAnnot.geneVelocyto[1]=2; //unspliced
//     } else if (reAnn[AlignVsTranscript::Concordant] || reAnn[AlignVsTranscript::Exon]) {//at least one model is exonic
//         if (!reAnn[AlignVsTranscript::Intron] && !reAnn[AlignVsTranscript::ExonIntron]) {
//             readAnnot.geneVelocyto[1]=1; //spliced
//         } else {
//             readAnnot.geneVelocyto[1]=3; //ambiguous <= exonic * ( intronic || mixed)
//         };
//     } else {//all other combinations are unspliced, as they do not contain a single purely exonic model
//         readAnnot.geneVelocyto[1]=2;
//     };
};
<|endoftext|>