<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * [ Copyright (C) 2011 <NAME>, Red Hat <<EMAIL>> (initial
 *   developer) ]
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#ifndef INCLUDED_SAL_LOG_HXX
#define INCLUDED_SAL_LOG_HXX

#include "sal/config.h"

#include <cstdlib>
#include <sstream>
#include <string>

#include "sal/detail/log.h"
#include "sal/types.h"

// Avoid the use of other sal code in this header as much as possible, so that
// this code can be called from other sal code without causing endless
// recursion.

/// @internal
extern "C" void SAL_CALL sal_detail_log(
    enum sal_detail_LogLevel level, char const * area, char const * where,
    char const * message);

/// @internal
namespace sal { namespace detail {

inline void SAL_CALL log(
    sal_detail_LogLevel level, char const * area, char const * where,
    std::ostringstream const & stream)
{
    // An alternative would be to have sal_detail_log take a std::ostringstream
    // pointer (via a C void pointer); the advantage would be smaller client
    // code (the ".str().c_str()" part would move into the implementation of
    // sal_detail_log) and potential for proper support of embedded null
    // characters within the message, but the disadvantage would be dependence
    // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved
    // to this inline function so that it is potentially only emitted once per
    // dynamic library:
    sal_detail_log(level, area, where, stream.str().c_str());
}

// Special handling of the common case where the message consists of just a
// string literal, to produce smaller call-site code:

struct StreamStart {};

struct StreamString {
    StreamString(char const * s): string(s) {}

    char const * string;

    typedef char Result;
};

struct StreamIgnore {
    typedef struct { char a[2]; } Result;
};

inline StreamString operator <<(StreamStart const &, char const * s) {
    return StreamString(s);
}

template< typename T > inline StreamIgnore operator <<(
    StreamStart const &, T const &)
{
    std::abort();
}

template< typename T > inline StreamIgnore operator <<(
    StreamString const &, T const &)
{
    std::abort();
}

template< typename T > inline StreamIgnore operator <<(
    StreamIgnore const &, T const &)
{
    std::abort();
}

template< typename T > typename T::Result getResult(T const &);

inline char const * unwrapStream(StreamString const & s) { return s.string; }

inline char const * unwrapStream(StreamIgnore const &) { std::abort(); }

} }

/// @internal
#define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
    do { \
        if (condition) { \
            if (sizeof getResult(::sal::detail::StreamStart() << stream) == 1) \
            { \
                ::sal_detail_log( \
                    (level), (area), (where), \
                    ::sal::detail::unwrapStream( \
                        ::sal::detail::StreamStart() << stream)); \
            } else { \
                ::std::ostringstream sal_detail_stream; \
                sal_detail_stream << stream; \
                ::sal::detail::log( \
                    (level), (area), (where), sal_detail_stream); \
            } \
        } \
    } while (false)

/** A simple macro to create a "file and line number" string.

    Potentially not only useful within the log framework (where it is used
    automatically), but also when creating exception messages.

    @since LibreOffice 3.5<commit_msg>Silence bogus MSC "must return a value" errors.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * [ Copyright (C) 2011 <NAME>, Red Hat <<EMAIL>> (initial
 *   developer) ]
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#ifndef INCLUDED_SAL_LOG_HXX
#define INCLUDED_SAL_LOG_HXX

#include "sal/config.h"

#include <cstdlib>
#include <sstream>
#include <string>

#include "sal/detail/log.h"
#include "sal/types.h"

// Avoid the use of other sal code in this header as much as possible, so that
// this code can be called from other sal code without causing endless
// recursion.

/// @internal
extern "C" void SAL_CALL sal_detail_log(
    enum sal_detail_LogLevel level, char const * area, char const * where,
    char const * message);

/// @internal
namespace sal { namespace detail {

inline void SAL_CALL log(
    sal_detail_LogLevel level, char const * area, char const * where,
    std::ostringstream const & stream)
{
    // An alternative would be to have sal_detail_log take a std::ostringstream
    // pointer (via a C void pointer); the advantage would be smaller client
    // code (the ".str().c_str()" part would move into the implementation of
    // sal_detail_log) and potential for proper support of embedded null
    // characters within the message, but the disadvantage would be dependence
    // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved
    // to this inline function so that it is potentially only emitted once per
    // dynamic library:
    sal_detail_log(level, area, where, stream.str().c_str());
}

// Special handling of the common case where the message consists of just a
// string literal, to produce smaller call-site code:

struct StreamStart {};

struct StreamString {
    StreamString(char const * s): string(s) {}

    char const * string;

    typedef char Result;
};

struct StreamIgnore {
    typedef struct { char a[2]; } Result;
};

inline StreamString operator <<(StreamStart const &, char const * s) {
    return StreamString(s);
}

template< typename T > inline StreamIgnore operator <<(
    StreamStart const &, T const &)
{
    std::abort();
#if defined _MSC_VER
    return StreamIgnore();
#endif
}

template< typename T > inline StreamIgnore operator <<(
    StreamString const &, T const &)
{
    std::abort();
#if defined _MSC_VER
    return StreamIgnore();
#endif
}

template< typename T > inline StreamIgnore operator <<(
    StreamIgnore const &, T const &)
{
    std::abort();
#if defined _MSC_VER
    return StreamIgnore();
#endif
}

template< typename T > typename T::Result getResult(T const &);

inline char const * unwrapStream(StreamString const & s) { return s.string; }

inline char const * unwrapStream(StreamIgnore const &) {
    std::abort();
#if defined _MSC_VER
    return 0;
#endif
}

} }

/// @internal
#define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
    do { \
        if (condition) { \
            if (sizeof getResult(::sal::detail::StreamStart() << stream) == 1) \
            { \
                ::sal_detail_log( \
                    (level), (area), (where), \
                    ::sal::detail::unwrapStream( \
                        ::sal::detail::StreamStart() << stream)); \
            } else { \
                ::std::ostringstream sal_detail_stream; \
                sal_detail_stream << stream; \
                ::sal::detail::log( \
                    (level), (area), (where), sal_detail_stream); \
            } \
        } \
    } while (false)

/** A simple macro to create a "file and line number" string.

    Potentially not only useful within the log framework (where it is used
    automatically), but also when creating exception messages.

    @since LibreOffice 3.5
{'fraction_non_alphanumeric': 0.10805245475235721, 'fraction_numerical': 0.004876991438170586, 'mean_word_length': 3.0244221543829046, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4968701', 'n_tokens_mistral': 2668, 'n_tokens_neox': 2575, 'n_words': 1042}