// bsls_platformutil.h                                                -*-C++-*-
#ifndef INCLUDED_BSLS_PLATFORMUTIL
#define INCLUDED_BSLS_PLATFORMUTIL

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide consistent interface for platform-dependent functionality.
//
//@DEPRECATED: Use `bsls_alignmentutil`, `bsls_byteorder`, `bsls_platform`, and
//  `bsls_types` instead.
//
//@CLASSES:
//  bsls::PlatformUtil: namespace for platform-neutral type names and API
//
//@MACROS:
//  BSLS_PLATFORMUTIL_IS_LITTLE_ENDIAN: flag set on little-endian platforms
//  BSLS_PLATFORMUTIL_IS_BIG_ENDIAN:    flag set on    big-endian platforms
//  BSLS_PLATFORMUTIL_HTONS(x): convert 16-bit from host to network byte order
//  BSLS_PLATFORMUTIL_HTONL(x): convert 32-bit from host to network byte order
//  BSLS_PLATFORMUTIL_NTOHS(x): convert 16-bit from network to host byte order
//  BSLS_PLATFORMUTIL_NTOHL(x): convert 32-bit from network to host byte order
//
//@SEE_ALSO: bsls_platform, bsls_types
//
//@DESCRIPTION: This component provides a namespace for a set of `typedef`s and
// functions that provide a stable, portable interface to platform-dependent
// functionality.  In particular, this component supplies portable typenames
// for signed and unsigned 64-bit integers, and provides compile-time
// preprocessor macros that characterize the "endian-ness" of the underlying
// processor on the current platform.  Runtime functionality to return the
// "endian-ness", and to round up to a multiple of the maximum required
// alignment for the processor, are also provided.
//
///Usage
///-----
// The following illustrates how some of the types and functions supplied by
// this component might be used.
//
///Types
///- - -
// `bsls::PlatformUtil::Int64` and `bsls::PlatformUtil::Uint64` identify the
// preferred fundamental types denoting signed and unsigned 64-bit integers,
// respectively:
// ```
// bsls::PlatformUtil::Uint64 stimulus = 787000000000ULL;
// ```
// Clients can use these types in the same way as an `int`.  Clients can also
// mix usage with other fundamental integral types:
// ```
// bsls::PlatformUtil::Uint64 nationalDebt = 1000000000000ULL;
// nationalDebt += stimulus;
//
// unsigned int deficitReduction = 1000000000;
// nationalDebt -= deficitReduction;
//
// std::cout << "National Debt Level: " << nationalDebt << std::endl;
// ```
// `bsls::PlatformUtil::size_type` identifies the preferred integral type
// denoting the number of elements in a container, and the number of bytes in a
// single block of memory supplied by an allocator.  For example, a typical use
// is as a `typedef` in an STL container:
// ```
// class vector {
//
//     // ...
//
//   public:
//     typedef bsls::PlatformUtil::size_type size_type;
//
//     // ...
// };
// ```
//
///Functions and Macros
/// - - - - - - - - - -
// The functions:
// ```
// bool bsls::PlatformUtil::isLittleEndian();
// bool bsls::PlatformUtil::isBigEndian();
// ```
// encapsulate the capability of determining whether a machine is big- or
// little-endian across all supported platforms.  In addition, certain
// compile-time constants are also provided as preprocessor macros to
// facilitate conditional compilation:
// ```
// BSLS_PLATFORMUTIL_IS_BIG_ENDIAN
// BSLS_PLATFORMUTIL_IS_LITTLE_ENDIAN
// ```
// These functions and macros are useful for writing platform-independent code,
// such as a function that converts the bytes in a `short` to network byte
// order (which is consistent with big-endian):
// ```
// short convertToNetworkByteOrder(short input)
//     // Return the specified 'input' in network byte order.
// {
// #ifdef BSLS_PLATFORMUTIL_IS_BIG_ENDIAN
//     return input;
// #else
//     return static_cast<short>(
//                             ((input >> 8) & 0xFF) | ((input & 0xFF) << 8));
// #endif
// }
// ```
// Note that in the above usage example, either the macros or the functions can
// be used to test whether a platform is big- or little-endian.

#ifdef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
#error "bsls_platformutil is deprecated"
#endif
#include <bsls_alignmentutil.h>
#include <bsls_platform.h>
#include <bsls_types.h>

#include <cstddef>

namespace BloombergLP {

namespace bsls {

                          // ===================
                          // struct PlatformUtil
                          // ===================

/// Provide a namespace for a suite of `typedef`s and pure procedures that
/// encapsulate, platform-dependent types and APIs.
struct PlatformUtil {

    // TYPES

    /// The alias `size_type` refers to the preferred type for denoting a
    /// number of elements in either `bslma` allocators or container types.
    /// Note that this type is signed, as negative values may make sense in
    /// certain contexts.  Also note that the standard-compliant allocators
    /// (e.g., `bsl::allocator` and `std::allocator`) use an *unsigned*
    /// size type, but that is fine because they also have a mechanism
    /// (`max_size`) to determine overflows resulting from converting from
    /// one size type to the other.
    ///
    /// @DEPRECATED: Use `Types::size_type` instead.
    typedef Types::size_type size_type;

    typedef Types::UintPtr UintPtr;

    /// The aliases `UintPtr` and `IntPtr` are guaranteed to have the same
    /// size as pointers.
    ///
    /// @DEPRECATED: Use `Types::UintPtr` and `Types::IntPtr` instead.
    typedef Types::IntPtr  IntPtr;

    typedef Types::Int64  Int64;

    /// The aliases `Int64` and `Uint64` stand for whatever type `Types`
    /// implements for the appropriate supported platforms.
    ///
    /// @DEPRECATED: Use `Types::Int64` and `Types::Uint64` instead.
    typedef Types::Uint64 Uint64;

#ifndef BDE_OMIT_INTERNAL_DEPRECATED
    /// The alias `MaxAlign` refers to a type that is maximally-aligned on
    /// the current platform.
    ///
    /// @DEPRECATED: Use `AlignmentUtil::MaxAlignedType` instead.
    typedef AlignmentUtil::MaxAlignedType MaxAlign;
#endif // BDE_OMIT_INTERNAL_DEPRECATED

    // CLASS METHODS

    /// Return `true` if this platform is "big-endian", and `false`
    /// otherwise.  Note that "big-endian" (i.e., the most significant byte
    /// of data at the lowest byte address) is consistent with network byte
    /// order.
    ///
    /// @DEPRECATED: Use preprocessor macro `BSLS_PLATFORM_IS_BIG_ENDIAN`
    /// defined in `bsls_platform` instead.
    static bool isBigEndian();

    /// Return `true` if this platform is "little-endian", and `false`
    /// otherwise.  Note that "little-endian" (i.e., the least significant
    /// byte of data at the lowest byte address) is inconsistent with
    /// network byte order.
    ///
    /// @DEPRECATED: Use preprocessor macro
    /// `BSLS_PLATFORMUTIL_IS_BIG_ENDIAN` defined in `bsls_platform`
    /// instead.
    static bool isLittleEndian();

    /// Return the specified `size` (in bytes) rounded up to the smallest
    /// integral multiple of the maximum alignment.  The behavior is
    /// undefined unless `0 <= size`.
    ///
    /// lmf_ForwardingTypeDEPRECATED: Use `AlignmentUtil::roundUpToMaximalAlignment` instead.
    static int roundUpToMaximalAlignment(int size);
};

}  // close package namespace

// ============================================================================
//                 COMPILE-TIME CONSTANT PRE-PROCESSOR MACROS
// ============================================================================

// The following preprocessor macros are **DEPRECATED**.  Please use their
// replacements in `bsls_byteorder` and `bsls_platform` instead.

#if defined(BSLS_PLATFORM_CPU_X86_64)
    /// @DEPRECATED: Use preprocessor macro `BSLS_PLATFORM_IS_LITTLE_ENDIAN`
    /// defined in `bsls_platform` instead.
    #define BSLS_PLATFORMUTIL_IS_LITTLE_ENDIAN BSLS_PLATFORM_IS_LITTLE_ENDIAN
#endif

#if defined(BSLS_PLATFORM_CPU_X86)
    /// @DEPRECATED: Use preprocessor macro `BSLS_PLATFORM_IS_LITTLE_ENDIAN`
    /// defined in `bsls_platform` instead.
    #define BSLS_PLATFORMUTIL_IS_LITTLE_ENDIAN \
                                                BSLS_PLATFORM_IS_LITTLE_ENDIAN
#endif

#if defined(BSLS_PLATFORM_CPU_ARM)
    /// @DEPRECATED: Use preprocessor macro `BSLS_PLATFORM_IS_LITTLE_ENDIAN`
    /// defined in `bsls_platform` instead.
    #define BSLS_PLATFORMUTIL_IS_LITTLE_ENDIAN \
                                                BSLS_PLATFORM_IS_LITTLE_ENDIAN
#endif

#if !defined(BSLS_PLATFORMUTIL_IS_LITTLE_ENDIAN)
   /// @DEPRECATED: Use preprocessor macro `BSLS_PLATFORM_IS_BIG_ENDIAN`
   /// defined in `bsls_platform` instead.
   #define BSLS_PLATFORMUTIL_IS_BIG_ENDIAN BSLS_PLATFORM_IS_BIG_ENDIAN
#endif

#ifndef BDE_OMIT_INTERNAL_DEPRECATED

#if defined(BSLS_PLATFORMUTIL_IS_BIG_ENDIAN)
#define BSLS_PLATFORMUTIL_HTONL(x) (x)
#define BSLS_PLATFORMUTIL_HTONS(x) (x)
#define BSLS_PLATFORMUTIL_NTOHL(x) (x)
#define BSLS_PLATFORMUTIL_NTOHS(x) (x)
    /// @DEPRECATED: Use preprocessor macros `BSLS_BYTEORDER_*TO*` defined in
    /// `bsls_byteorder` instead.
#else
    /// Use built-in if using gcc 4.3.

#if (defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VER_MAJOR >= 40300) \
 || defined(BSLS_PLATFORM_CMP_CLANG)
#define BSLS_PLATFORMUTIL_NTOHL(x) (unsigned) __builtin_bswap32(x)
#else
#define BSLS_PLATFORMUTIL_NTOHL(x) \
                   ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
                   (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
#endif
#define BSLS_PLATFORMUTIL_HTONL(x) BSLS_PLATFORMUTIL_NTOHL(x)
#define BSLS_PLATFORMUTIL_NTOHS(x) \
                                    ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
#define BSLS_PLATFORMUTIL_HTONS(x) BSLS_PLATFORMUTIL_NTOHS(x)
#endif

#endif // BDE_OMIT_INTERNAL_DEPRECATED

namespace bsls {

// ============================================================================
//                        INLINE FUNCTION DEFINITIONS
// ============================================================================

                          // -------------------
                          // struct PlatformUtil
                          // -------------------

// CLASS METHODS
inline
bool PlatformUtil::isLittleEndian()
{
#if defined(BSLS_PLATFORM_IS_LITTLE_ENDIAN)
    return BSLS_PLATFORM_IS_LITTLE_ENDIAN;
#else
    return false;
#endif
}

inline
bool PlatformUtil::isBigEndian()
{
#if defined(BSLS_PLATFORM_IS_BIG_ENDIAN)
    return BSLS_PLATFORM_IS_BIG_ENDIAN;
#else
    return false;
#endif
}

inline
int PlatformUtil::roundUpToMaximalAlignment(int size)
{
    enum { BSLS_MAX_ALIGN = AlignmentUtil::BSLS_MAX_ALIGNMENT };
    return ((size + BSLS_MAX_ALIGN - 1) / BSLS_MAX_ALIGN) * BSLS_MAX_ALIGN;
}

}  // close package namespace

#ifndef BDE_OPENSOURCE_PUBLICATION  // BACKWARD_COMPATIBILITY
// ============================================================================
//                           BACKWARD COMPATIBILITY
// ============================================================================

/// This alias is defined for backward compatibility.
typedef bsls::PlatformUtil bsls_PlatformUtil;
#endif  // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY

}  // close enterprise namespace

#if !defined(BSL_DOUBLE_UNDERSCORE_XLAT) || 1 == BSL_DOUBLE_UNDERSCORE_XLAT

#ifdef BSLS_PLATFORMUTIL_IS_BIG_ENDIAN
# define BSLS_PLATFORMUTIL__IS_BIG_ENDIAN BSLS_PLATFORMUTIL_IS_BIG_ENDIAN
#endif
#ifdef BSLS_PLATFORMUTIL_IS_LITTLE_ENDIAN
# define BSLS_PLATFORMUTIL__IS_LITTLE_ENDIAN BSLS_PLATFORMUTIL_IS_LITTLE_ENDIAN
#endif
#define BSLS_PLATFORMUTIL__HTONL(x) BSLS_PLATFORMUTIL_HTONL(x)
#define BSLS_PLATFORMUTIL__HTONS(x) BSLS_PLATFORMUTIL_HTONS(x)
#define BSLS_PLATFORMUTIL__NTOHL(x) BSLS_PLATFORMUTIL_NTOHL(x)
#define BSLS_PLATFORMUTIL__NTOHS(x) BSLS_PLATFORMUTIL_NTOHS(x)

#endif

#endif

// ----------------------------------------------------------------------------
// Copyright 2013 Bloomberg Finance L.P.
//
// 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.
// ----------------------------- END-OF-FILE ----------------------------------
