<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#ifndef _STRING_HXX
#define _STRING_HXX

#include <tools/solar.h>
#include <osl/thread.h>
#include <rtl/textenc.h>
#include <rtl/textcvt.h>
#include <rtl/ustrbuf.h>
#include <rtl/string.hxx>
#include <rtl/ustring.hxx>
#include "tools/toolsdllapi.h"
#include "tools/lineend.hxx"

/*******************************************************************************
 *
 * THIS CODE IS DEPRECATED.  DO NOT USE IT IN ANY NEW CODE.
 *
 * Use the string classes in rtl/ustring.hxx and rtl/ustrbuf.hxx (and
 * rtl/string.hxx and rtl/strbuf.hxx for byte-sized strings) instead.  If you
 * feel functionality missing from those string classes, please request
 * improvements on discuss@openoffice.org.
 *
 * There will not be any fixes to the code here.
 ******************************************************************************/

class ResId;
class String;
class UniString;

#define BYTESTRING_TO_UNISTRING_CVTFLAGS    (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |\
                                             RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |\
                                             RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT)

// CharSet

#ifndef ENUM_CHARSET_DECLARED
#define ENUM_CHARSET_DECLARED

typedef rtl_TextEncoding CharSet;

#endif

// String-Types

#ifdef STRING32
#define STRING_NOTFOUND    ((xub_StrLen)0x7FFFFFFF)
#define STRING_MATCH       ((xub_StrLen)0x7FFFFFFF)
#define STRING_LEN         ((xub_StrLen)0x7FFFFFFF)
#define STRING_MAXLEN      ((xub_StrLen)0x7FFFFFFF)
#else
#define STRING_NOTFOUND    ((xub_StrLen)0xFFFF)
#define STRING_MATCH       ((xub_StrLen)0xFFFF)
#define STRING_LEN         ((xub_StrLen)0xFFFF)
#define STRING_MAXLEN      ((xub_StrLen)0xFFFF)
#endif

enum StringCompare { COMPARE_LESS = -1, COMPARE_EQUAL = 0, COMPARE_GREATER = 1 };

//Internal String data

// Data used for the management of this String
// use only for debugging purposes (never assign to String directly!)

#ifdef SAL_W32
#pragma pack(push, 4)
#endif

typedef struct _UniStringData
{
    sal_Int32           mnRefCount;     // reference counter
    sal_Int32           mnLen;          // Length of the String
    sal_Unicode         maStr[1];       // CharArray (String)
} UniStringData;

#ifdef SAL_W32
#pragma pack(pop)
#endif

// UniString

class TOOLS_DLLPUBLIC SAL_WARN_UNUSED UniString
{
private:
    UniStringData*      mpData;

    TOOLS_DLLPRIVATE inline void ImplCopyData();
    TOOLS_DLLPRIVATE inline sal_Unicode * ImplCopyStringData(sal_Unicode *);

    StringCompare       CompareTo( const UniString& rStr,
                                   xub_StrLen nLen = STRING_LEN ) const;

                        UniString( const int* pDummy );    // not implemented: to prevent UniString( NULL )
                        UniString(int); // not implemented; to detect misuses of
                                        // UniString(sal_Unicode)
    void                Assign(int); // not implemented; to detect misuses of
                                     // Assign(sal_Unicode)
    void                operator =(int); // not implemented; to detect misuses
                                         // of operator =(sal_Unicode)
    void                Append(int); // not implemented; to detect misuses of
                                     // Append(sal_Unicode)
    void                operator +=(int); // not implemented; to detect misuses
                                          // of operator +=(sal_Unicode)

    //detect and reject use of RTL_CONSTASCII_STRINGPARAM instead of RTL_CONSTASCII_USTRINGPARAM
    TOOLS_DLLPRIVATE UniString( const sal_Char*, sal_Int32 );

    //detect and reject wrong way to attempt to create a UniString from a substring of
    //a OString
    TOOLS_DLLPRIVATE UniString(const OString& rByteStr, xub_StrLen nPos, xub_StrLen nLen,
    sal_uInt32       nCvtFlags = BYTESTRING_TO_UNISTRING_CVTFLAGS);

    //no longer implemented
    TOOLS_DLLPRIVATE UniString( const OString& rByteStr,
                                   rtl_TextEncoding eTextEncoding,
                                   sal_uInt32 nCvtFlags = BYTESTRING_TO_UNISTRING_CVTFLAGS );
    TOOLS_DLLPRIVATE UniString( const sal_Unicode* pCharStr );
    TOOLS_DLLPRIVATE UniString( const sal_Unicode* pCharStr, xub_StrLen nLen );
    TOOLS_DLLPRIVATE UniString( sal_Unicode c );
    TOOLS_DLLPRIVATE UniString& Assign( const sal_Unicode* pCharStr, xub_StrLen nLen );
    TOOLS_DLLPRIVATE UniString& Append( const sal_Unicode* pCharStr );
    TOOLS_DLLPRIVATE UniString& Append( const sal_Unicode* pCharStr, xub_StrLen nLen );
    TOOLS_DLLPRIVATE UniString& Expand( xub_StrLen nCount, sal_Unicode cExpandChar );
    TOOLS_DLLPRIVATE sal_Bool   Equals( const sal_Unicode* pCharStr,
                                xub_StrLen nIndex, xub_StrLen nLen ) const;
    TOOLS_DLLPRIVATE xub_StrLen Search( const sal_Unicode* pCharStr, xub_StrLen nIndex = 0 ) const;

    TOOLS_DLLPRIVATE UniString& operator +=( const sal_Unicode* pCharStr );

public:
                        UniString();
                        UniString( const ResId& rResId );
                        UniString( const UniString& rStr );
                        UniString( const UniString& rStr, xub_StrLen nPos, xub_StrLen nLen );
                        UniString( const OUString& rStr );
                        UniString(char c); // ...but allow "UniString('a')"
                        UniString( const sal_Char* pByteStr,
                                   rtl_TextEncoding eTextEncoding,
                                   sal_uInt32 nCvtFlags = BYTESTRING_TO_UNISTRING_CVTFLAGS );
                        UniString( const sal_Char* pByteStr, xub_StrLen nLen,
                                   rtl_TextEncoding eTextEncoding,
                                   sal_uInt32 nCvtFlags = BYTESTRING_TO_UNISTRING_CVTFLAGS );
                        ~UniString();

    operator OUString () const
    {
        return OUString( rtl_uStringBuffer_refReturn(
                                reinterpret_cast<rtl_uString*>(mpData)), SAL_NO_ACQUIRE );
    }

#ifdef RTL_FAST_STRING
    template< typename T1, typename T2 >
    UniString( const rtl::OUStringConcat< T1, T2 >& concat )
        : mpData(NULL) { Assign( OUString( concat )); }
    template< typename T1, typename T2 >
    UniString&          operator =( const rtl::OUStringConcat< T1, T2 >& concat )
                            { return Assign( OUString( concat )); }
    template< typename T1, typename T2 >
    UniString&          operator +=( const rtl::OUStringConcat< T1, T2 >& concat )
                            { return Append( UniString( concat ) ); }
#endif

    sal_Int32           ToInt32() const;

    UniString&          Assign( const UniString& rStr );
    UniString&          Assign( const OUString& rStr );
    UniString&          Assign( const sal_Unicode* pCharStr );
    UniString&          Assign( sal_Unicode c );
    inline UniString & Assign(char c) // ...but allow "Assign('a')"
        { return Assign(static_cast< sal_Unicode >(c)); }

    UniString&          operator =( const UniString& rStr )
                            { return Assign( rStr ); }
    UniString&          operator =( const OUString& rStr )
                            { return Assign( rStr ); }
    UniString&          operator =( const sal_Unicode* pCharStr )
                            { return Assign( pCharStr ); }
    UniString&          operator =( sal_Unicode c )
                            { return Assign( c ); }
    inline UniString & operator =(char c) // ...but allow "= 'a'"
        { return operator =(static_cast< sal_Unicode >(c)); }

    UniString&          Append( const UniString& rStr );
    UniString&          Append( sal_Unicode c );
    inline UniString & Append(char c) // ...but allow "Append('a')"
        { return Append(static_cast< sal_Unicode >(c)); }
    UniString&          operator +=( const UniString& rStr )
                            { return Append( rStr ); }
    UniString&          operator +=( const OUString& rStr )
                            { return Append( UniString(rStr) ); }
    UniString&          operator +=( sal_Unicode c )
                            { return Append( c ); }
    inline UniString & operator +=(char c) // ...but allow "+= 'a'"
        { return operator +=(static_cast< sal_Unicode >(c)); }

    void                SetChar( xub_StrLen nIndex, sal_Unicode c );
    sal_Unicode         GetChar( xub_StrLen nIndex ) const
                            { return mpData->maStr[nIndex]; }

    xub_StrLen          Len() const { return (xub_StrLen)mpData->mnLen; }

    UniString&          Insert( const UniString& rStr, xub_StrLen nIndex = STRING_LEN );
    UniString&          Insert( const UniString& rStr, xub_StrLen nPos, xub_StrLen nLen,
                                xub_StrLen nIndex = STRING_LEN );
    UniString&          Insert( sal_Unicode c, xub_StrLen nIndex = STRING_LEN );
    UniString&          Replace( xub_StrLen nIndex, xub_StrLen nLen, const UniString& rStr );
    UniString&          Erase( xub_StrLen nIndex = 0, xub_StrLen nCount = STRING_LEN );
    UniString           Copy( xub_StrLen nIndex = 0, xub_StrLen nCount = STRING_LEN ) const;

    sal_Bool            Equals( const UniString& rStr ) const;
    sal_Bool            Equals( const UniString& rStr,
                                xub_StrLen nIndex, xub_StrLen nLen ) const;

    xub_StrLen          Search( sal_Unicode c, xub_StrLen nIndex = 0 ) const;
    xub_StrLen          Search( const UniString& rStr, xub_StrLen nIndex = 0 ) const;

    const sal_Unicode*  GetBuffer() const { return mpData->maStr; }

    friend sal_Bool     operator == ( const UniString& rStr1,   const UniString& rStr2 )
                            { return rStr1.Equals( rStr2 ); }
    friend sal_Bool     operator != ( const UniString& rStr1,   const UniString& rStr2 )
                            { return !(operator == ( rStr1, rStr2 )); }
    friend sal_Bool     operator <  ( const UniString& rStr1,   const UniString& rStr2 )
                            { return (rStr1.CompareTo( rStr2 ) == COMPARE_LESS); }
    friend sal_Bool     operator >  ( const UniString& rStr1,   const UniString& rStr2 )
                            { return (rStr1.CompareTo( rStr2 ) == COMPARE_GREATER); }
    friend sal_Bool     operator <= ( const UniString& rStr1,   const UniString& rStr2 )
                            { return !(operator > ( rStr1, rStr2 )); }
    friend sal_Bool     operator >= ( const UniString& rStr1,   const UniString& rStr2 )
                            { return !(operator < ( rStr1, rStr2 )); }
};

inline UniString UniString::Copy( xub_StrLen nIndex, xub_StrLen nCount ) const
{
    return UniString( *this, nIndex, nCount );
}

template< typename charT, typename traits > std::basic_ostream<charT, traits> &
operator <<(
    std::basic_ostream<charT, traits> & stream, UniString const & string)
{
    return stream <<
        OUStringToOString(string, RTL_TEXTENCODING_UTF8).getStr();
        // best effort; potentially loses data due to conversion failures
        // (stray surrogate halves) and embedded null characters
}

#ifdef RTL_FAST_STRING
namespace rtl
{
template<>
struct ToStringHelper< UniString >
    {
    static int length( const UniString& s ) { return s.Len(); }
    static sal_Unicode* addData( sal_Unicode* buffer, const UniString& s ) { return addDataHelper( buffer, s.GetBuffer(), s.Len()); }
    static const bool allowOStringConcat = false;
    static const bool allowOUStringConcat = true;
    };
}

#endif

// some compare operators, so that conversions from String to OUString don't
// have to insert conversions all over the place
inline bool operator==(UniString const& rLeft, OUString const& rRight)
{
    return OUString(rLeft) == rRight;
}

inline bool operator==(OUString const& rLeft, UniString const& rRight)
{
    return rLeft == OUString(rRight);
}

inline bool operator!=(UniString const& rLeft, OUString const& rRight)
{
    return OUString(rLeft) != rRight;
}

inline bool operator!=(OUString const& rLeft, UniString const& rRight)
{
    return rLeft != OUString(rRight);
}

#ifdef RTL_FAST_STRING
// The above operators make comparisons involving fast string concatenation ambiguous, so provide explicit overloads.
template< typename T1, typename T2 >
inline bool operator==( const rtl::OUStringConcat< T1, T2 >& concat, const OUString& str )
{
    return OUString( concat ) == str;
}

template< typename T1, typename T2 >
inline bool operator!=( const rtl::OUStringConcat< T1, T2 >& concat, const OUString& str )
{
    return OUString( concat ) == str;
}

template< typename T1, typename T2 >
inline bool operator==( const OUString& str, const rtl::OUStringConcat< T1, T2 >& concat )
{
    return str == OUString( concat );
}

template< typename T1, typename T2 >
inline bool operator!=( const OUString& str, const rtl::OUStringConcat< T1, T2 >& concat )
{
    return str != OUString( concat );
}

template< typename T1, typename T2 >
inline bool operator==( const rtl::OUStringConcat< T1, T2 >& concat, const UniString& str )
{
    return UniString( concat ) == str;
}

template< typename T1, typename T2 >
inline bool operator!=( const rtl::OUStringConcat< T1, T2 >& concat, const UniString& str )
{
    return UniString( concat ) == str;
}

template< typename T1, typename T2 >
inline bool operator==( const UniString& str, const rtl::OUStringConcat< T1, T2 >& concat )
{
    return str == UniString( concat );
}

template< typename T1, typename T2 >
inline bool operator!=( const UniString& str, const rtl::OUStringConcat< T1, T2 >& concat )
{
    return str != UniString( concat );
}

#endif

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Related: fdo#38838 make String::Erase private<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#ifndef _STRING_HXX
#define _STRING_HXX

#include <tools/solar.h>
#include <osl/thread.h>
#include <rtl/textenc.h>
#include <rtl/textcvt.h>
#include <rtl/ustrbuf.h>
#include <rtl/string.hxx>
#include <rtl/ustring.hxx>
#include "tools/toolsdllapi.h"
#include "tools/lineend.hxx"

/*******************************************************************************
 *
 * THIS CODE IS DEPRECATED.  DO NOT USE IT IN ANY NEW CODE.
 *
 * Use the string classes in rtl/ustring.hxx and rtl/ustrbuf.hxx (and
 * rtl/string.hxx and rtl/strbuf.hxx for byte-sized strings) instead.  If you
 * feel functionality missing from those string classes, please request
 * improvements on discuss@openoffice.org.
 *
 * There will not be any fixes to the code here.
 ******************************************************************************/

class ResId;
class String;
class UniString;

#define BYTESTRING_TO_UNISTRING_CVTFLAGS    (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |\
                                             RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |\
                                             RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT)

// CharSet

#ifndef ENUM_CHARSET_DECLARED
#define ENUM_CHARSET_DECLARED

typedef rtl_TextEncoding CharSet;

#endif

// String-Types

#ifdef STRING32
#define STRING_NOTFOUND    ((xub_StrLen)0x7FFFFFFF)
#define STRING_MATCH       ((xub_StrLen)0x7FFFFFFF)
#define STRING_LEN         ((xub_StrLen)0x7FFFFFFF)
#define STRING_MAXLEN      ((xub_StrLen)0x7FFFFFFF)
#else
#define STRING_NOTFOUND    ((xub_StrLen)0xFFFF)
#define STRING_MATCH       ((xub_StrLen)0xFFFF)
#define STRING_LEN         ((xub_StrLen)0xFFFF)
#define STRING_MAXLEN      ((xub_StrLen)0xFFFF)
#endif

enum StringCompare { COMPARE_LESS = -1, COMPARE_EQUAL = 0, COMPARE_GREATER = 1 };

//Internal String data

// Data used for the management of this String
// use only for debugging purposes (never assign to String directly!)

#ifdef SAL_W32
#pragma pack(push, 4)
#endif

typedef struct _UniStringData
{
    sal_Int32           mnRefCount;     // reference counter
    sal_Int32           mnLen;          // Length of the String
    sal_Unicode         maStr[1];       // CharArray (String)
} UniStringData;

#ifdef SAL_W32
#pragma pack(pop)
#endif

// UniString

class TOOLS_DLLPUBLIC SAL_WARN_UNUSED UniString
{
private:
    UniStringData*      mpData;

    TOOLS_DLLPRIVATE inline void ImplCopyData();
    TOOLS_DLLPRIVATE inline sal_Unicode * ImplCopyStringData(sal_Unicode *);

    StringCompare       CompareTo( const UniString& rStr,
                                   xub_StrLen nLen = STRING_LEN ) const;
    UniString&          Erase( xub_StrLen nIndex = 0, xub_StrLen nCount = STRING_LEN );

                        UniString( const int* pDummy );    // not implemented: to prevent UniString( NULL )
                        UniString(int); // not implemented; to detect misuses of
                                        // UniString(sal_Unicode)
    void                Assign(int); // not implemented; to detect misuses of
                                     // Assign(sal_Unicode)
    void                operator =(int); // not implemented; to detect misuses
                                         // of operator =(sal_Unicode)
    void                Append(int); // not implemented; to detect misuses of
                                     // Append(sal_Unicode)
    void                operator +=(int); // not implemented; to detect misuses
                                          // of operator +=(sal_Unicode)

    //detect and reject use of RTL_CONSTASCII_STRINGPARAM instead of RTL_CONSTASCII_USTRINGPARAM
    TOOLS_DLLPRIVATE UniString( const sal_Char*, sal_Int32 );

    //detect and reject wrong way to attempt to create a UniString from a substring of
    //a OString
    TOOLS_DLLPRIVATE UniString(const OString& rByteStr, xub_StrLen nPos, xub_StrLen nLen,
    sal_uInt32       nCvtFlags = BYTESTRING_TO_UNISTRING_CVTFLAGS);

    //no longer implemented
    TOOLS_DLLPRIVATE UniString( const OString& rByteStr,
                                   rtl_TextEncoding eTextEncoding,
                                   sal_uInt32 nCvtFlags = BYTESTRING_TO_UNISTRING_CVTFLAGS );
    TOOLS_DLLPRIVATE UniString( const sal_Unicode* pCharStr );
    TOOLS_DLLPRIVATE UniString( const sal_Unicode* pCharStr, xub_StrLen nLen );
    TOOLS_DLLPRIVATE UniString( sal_Unicode c );
    TOOLS_DLLPRIVATE UniString& Assign( const sal_Unicode* pCharStr, xub_StrLen nLen );
    TOOLS_DLLPRIVATE UniString& Append( const sal_Unicode* pCharStr );
    TOOLS_DLLPRIVATE UniString& Append( const sal_Unicode* pCharStr, xub_StrLen nLen );
    TOOLS_DLLPRIVATE UniString& Expand( xub_StrLen nCount, sal_Unicode cExpandChar );
    TOOLS_DLLPRIVATE sal_Bool   Equals( const sal_Unicode* pCharStr,
                                xub_StrLen nIndex, xub_StrLen nLen ) const;
    TOOLS_DLLPRIVATE xub_StrLen Search( const sal_Unicode* pCharStr, xub_StrLen nIndex = 0 ) const;

    TOOLS_DLLPRIVATE UniString& operator +=( const sal_Unicode* pCharStr );

public:
                        UniString();
                        UniString( const ResId& rResId );
                        UniString( const UniString& rStr );
                        UniString( const UniString& rStr, xub_StrLen nPos, xub_StrLen nLen );
                        UniString( const OUString& rStr );
                        UniString(char c); // ...but allow "UniString('a')"
                        UniString( const sal_Char* pByteStr,
                                   rtl_TextEncoding eTextEncoding,
                                   sal_uInt32 nCvtFlags = BYTESTRING_TO_UNISTRING_CVTFLAGS );
                        UniString( const sal_Char* pByteStr, xub_StrLen nLen,
                                   rtl_TextEncoding eTextEncoding,
                                   sal_uInt32 nCvtFlags = BYTESTRING_TO_UNISTRING_CVTFLAGS );
                        ~UniString();

    operator OUString () const
    {
        return OUString( rtl_uStringBuffer_refReturn(
                                reinterpret_cast<rtl_uString*>(mpData)), SAL_NO_ACQUIRE );
    }

#ifdef RTL_FAST_STRING
    template< typename T1, typename T2 >
    UniString( const rtl::OUStringConcat< T1, T2 >& concat )
        : mpData(NULL) { Assign( OUString( concat )); }
    template< typename T1, typename T2 >
    UniString&          operator =( const rtl::OUStringConcat< T1, T2 >& concat )
                            { return Assign( OUString( concat )); }
    template< typename T1, typename T2 >
    UniString&          operator +=( const rtl::OUStringConcat< T1, T2 >& concat )
                            { return Append( UniString( concat ) ); }
#endif

    sal_Int32           ToInt32() const;

    UniString&          Assign( const UniString& rStr );
    UniString&          Assign( const OUString& rStr );
    UniString&          Assign( const sal_Unicode* pCharStr );
    UniString&          Assign( sal_Unicode c );
    inline UniString & Assign(char c) // ...but allow "Assign('a')"
        { return Assign(static_cast< sal_Unicode >(c)); }

    UniString&          operator =( const UniString& rStr )
                            { return Assign( rStr ); }
    UniString&          operator =( const OUString& rStr )
                            { return Assign( rStr ); }
    UniString&          operator =( const sal_Unicode* pCharStr )
                            { return Assign( pCharStr ); }
    UniString&          operator =( sal_Unicode c )
                            { return Assign( c ); }
    inline UniString & operator =(char c) // ...but allow "= 'a'"
        { return operator =(static_cast< sal_Unicode >(c)); }

    UniString&          Append( const UniString& rStr );
    UniString&          Append( sal_Unicode c );
    inline UniString & Append(char c) // ...but allow "Append('a')"
        { return Append(static_cast< sal_Unicode >(c)); }
    UniString&          operator +=( const UniString& rStr )
                            { return Append( rStr ); }
    UniString&          operator +=( const OUString& rStr )
                            { return Append( UniString(rStr) ); }
    UniString&          operator +=( sal_Unicode c )
                            { return Append( c ); }
    inline UniString & operator +=(char c) // ...but allow "+= 'a'"
        { return operator +=(static_cast< sal_Unicode >(c)); }

    void                SetChar( xub_StrLen nIndex, sal_Unicode c );
    sal_Unicode         GetChar( xub_StrLen nIndex ) const
                            { return mpData->maStr[nIndex]; }

    xub_StrLen          Len() const { return (xub_StrLen)mpData->mnLen; }

    UniString&          Insert( const UniString& rStr, xub_StrLen nIndex = STRING_LEN );
    UniString&          Insert( const UniString& rStr, xub_StrLen nPos, xub_StrLen nLen,
                                xub_StrLen nIndex = STRING_LEN );
    UniString&          Insert( sal_Unicode c, xub_StrLen nIndex = STRING_LEN );
    UniString&          Replace( xub_StrLen nIndex, xub_StrLen nLen, const UniString& rStr );
    UniString           Copy( xub_StrLen nIndex = 0, xub_StrLen nCount = STRING_LEN ) const;

    sal_Bool            Equals( const UniString& rStr ) const;
    sal_Bool            Equals( const UniString& rStr,
                                xub_StrLen nIndex, xub_StrLen nLen ) const;

    xub_StrLen          Search( sal_Unicode c, xub_StrLen nIndex = 0 ) const;
    xub_StrLen          Search( const UniString& rStr, xub_StrLen nIndex = 0 ) const;

    const sal_Unicode*  GetBuffer() const { return mpData->maStr; }

    friend sal_Bool     operator == ( const UniString& rStr1,   const UniString& rStr2 )
                            { return rStr1.Equals( rStr2 ); }
    friend sal_Bool     operator != ( const UniString& rStr1,   const UniString& rStr2 )
                            { return !(operator == ( rStr1, rStr2 )); }
    friend sal_Bool     operator <  ( const UniString& rStr1,   const UniString& rStr2 )
                            { return (rStr1.CompareTo( rStr2 ) == COMPARE_LESS); }
    friend sal_Bool     operator >  ( const UniString& rStr1,   const UniString& rStr2 )
                            { return (rStr1.CompareTo( rStr2 ) == COMPARE_GREATER); }
    friend sal_Bool     operator <= ( const UniString& rStr1,   const UniString& rStr2 )
                            { return !(operator > ( rStr1, rStr2 )); }
    friend sal_Bool     operator >= ( const UniString& rStr1,   const UniString& rStr2 )
                            { return !(operator < ( rStr1, rStr2 )); }
};

inline UniString UniString::Copy( xub_StrLen nIndex, xub_StrLen nCount ) const
{
    return UniString( *this, nIndex, nCount );
}

template< typename charT, typename traits > std::basic_ostream<charT, traits> &
operator <<(
    std::basic_ostream<charT, traits> & stream, UniString const & string)
{
    return stream <<
        OUStringToOString(string, RTL_TEXTENCODING_UTF8).getStr();
        // best effort; potentially loses data due to conversion failures
        // (stray surrogate halves) and embedded null characters
}

#ifdef RTL_FAST_STRING
namespace rtl
{
template<>
struct ToStringHelper< UniString >
    {
    static int length( const UniString& s ) { return s.Len(); }
    static sal_Unicode* addData( sal_Unicode* buffer, const UniString& s ) { return addDataHelper( buffer, s.GetBuffer(), s.Len()); }
    static const bool allowOStringConcat = false;
    static const bool allowOUStringConcat = true;
    };
}

#endif

// some compare operators, so that conversions from String to OUString don't
// have to insert conversions all over the place
inline bool operator==(UniString const& rLeft, OUString const& rRight)
{
    return OUString(rLeft) == rRight;
}

inline bool operator==(OUString const& rLeft, UniString const& rRight)
{
    return rLeft == OUString(rRight);
}

inline bool operator!=(UniString const& rLeft, OUString const& rRight)
{
    return OUString(rLeft) != rRight;
}

inline bool operator!=(OUString const& rLeft, UniString const& rRight)
{
    return rLeft != OUString(rRight);
}

#ifdef RTL_FAST_STRING
// The above operators make comparisons involving fast string concatenation ambiguous, so provide explicit overloads.
template< typename T1, typename T2 >
inline bool operator==( const rtl::OUStringConcat< T1, T2 >& concat, const OUString& str )
{
    return OUString( concat ) == str;
}

template< typename T1, typename T2 >
inline bool operator!=( const rtl::OUStringConcat< T1, T2 >& concat, const OUString& str )
{
    return OUString( concat ) == str;
}

template< typename T1, typename T2 >
inline bool operator==( const OUString& str, const rtl::OUStringConcat< T1, T2 >& concat )
{
    return str == OUString( concat );
}

template< typename T1, typename T2 >
inline bool operator!=( const OUString& str, const rtl::OUStringConcat< T1, T2 >& concat )
{
    return str != OUString( concat );
}

template< typename T1, typename T2 >
inline bool operator==( const rtl::OUStringConcat< T1, T2 >& concat, const UniString& str )
{
    return UniString( concat ) == str;
}

template< typename T1, typename T2 >
inline bool operator!=( const rtl::OUStringConcat< T1, T2 >& concat, const UniString& str )
{
    return UniString( concat ) == str;
}

template< typename T1, typename T2 >
inline bool operator==( const UniString& str, const rtl::OUStringConcat< T1, T2 >& concat )
{
    return str == UniString( concat );
}

template< typename T1, typename T2 >
inline bool operator!=( const UniString& str, const rtl::OUStringConcat< T1, T2 >& concat )
{
    return str != UniString( concat );
}

#endif

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef NIXPY_TRANSMORGIFY_H
#define NIXPY_TRANSMORGIFY_H

#include <boost/python.hpp>

namespace nixpy {

template<typename T>
struct vector_transmogrify {
    static PyObject* convert(const std::vector<T>& vec) {
        boost::python::list l = boost::python::list();

        for(auto& item : vec) {
            l.append(item);
        }

        return boost::python::incref(l.ptr());
    }
};

template<typename T>
struct option_transmogrify {
    static PyObject* convert(const boost::optional<T>& opt) {
        if (opt == boost::none) {
            Py_RETURN_NONE;
        }

        return boost::python::incref(boost::python::object(*opt).ptr());
    }

    typedef boost::python::converter::rvalue_from_python_stage1_data py_s1_data;
    typedef boost::python::converter::rvalue_from_python_storage<boost::optional<T>> py_storage;

    static void register_from_python() {
        boost::python::converter::registry::push_back(is_convertible,
                                                        construct,
                                                        boost::python::type_id<boost::optional<T>>());
    }

    static void* is_convertible(PyObject *obj) {
        return (obj == Py_None || PyString_Check(obj)) ? obj : nullptr;
    }

    static void construct(PyObject *obj, py_s1_data *data) {
        using namespace boost::python::converter;

        void *raw = static_cast<void *>(reinterpret_cast<py_storage *>(data)->storage.bytes);
        if (obj == Py_None) {
            new (raw) boost::optional<T>{};
        } else {
            std::string value(PyString_AsString(obj));
            std::cout << value << std::endl;
            new (raw) boost::optional<T>(value);
        }
        data->convertible = raw;
    }
};

}

#endif // NIXPY_TRANSMORGIFY_H
<commit_msg>TODO added<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef NIXPY_TRANSMORGIFY_H
#define NIXPY_TRANSMORGIFY_H

#include <boost/python.hpp>

namespace nixpy {

// TODO transmorgify time_t;

template<typename T>
struct vector_transmogrify {
    static PyObject* convert(const std::vector<T>& vec) {
        boost::python::list l = boost::python::list();

        for(auto& item : vec) {
            l.append(item);
        }

        return boost::python::incref(l.ptr());
    }
};

template<typename T>
struct option_transmogrify {
    static PyObject* convert(const boost::optional<T>& opt) {
        if (opt == boost::none) {
            Py_RETURN_NONE;
        }

        return boost::python::incref(boost::python::object(*opt).ptr());
    }

    typedef boost::python::converter::rvalue_from_python_stage1_data py_s1_data;
    typedef boost::python::converter::rvalue_from_python_storage<boost::optional<T>> py_storage;

    static void register_from_python() {
        boost::python::converter::registry::push_back(is_convertible,
                                                        construct,
                                                        boost::python::type_id<boost::optional<T>>());
    }

    static void* is_convertible(PyObject *obj) {
        return (obj == Py_None || PyString_Check(obj)) ? obj : nullptr;
    }

    static void construct(PyObject *obj, py_s1_data *data) {
        using namespace boost::python::converter;

        void *raw = static_cast<void *>(reinterpret_cast<py_storage *>(data)->storage.bytes);
        if (obj == Py_None) {
            new (raw) boost::optional<T>{};
        } else {
            std::string value(PyString_AsString(obj));
            std::cout << value << std::endl;
            new (raw) boost::optional<T>(value);
        }
        data->convertible = raw;
    }
};

}

#endif // NIXPY_TRANSMORGIFY_H
<|endoftext|>


<commit_before>/* Copyright 2014 Dietrich Epp.
   This file is part of Legend of Feleria.  Legend of Feleria is
   licensed under the terms of the 2-clause BSD license.  For more
   information, see LICENSE.txt. */
#include "defs.hpp"
#include "sprite.hpp"
#include "sg/sprite.h"
#include "base/chunk.hpp"
#include <cstring>
namespace Graphics {
using Game::SPRITE_COUNT;

namespace {

const char SPRITE_MAGIC[16] = "Feleria Sprites";

#include "data/sprite.array.hpp"

struct FileGroupInfo {
    unsigned short w, h, offset;
};

const sg_sprite ZERO_SPRITE = { 0, 0, 0, 0, 0, 0 };

}

struct SpriteSheet::GroupInfo {
    int w, h;
    const sg_sprite *sprites;
};

SpriteSheet::SpriteSheet() {
    GroupInfo gifo { 0, 0, nullptr };
    m_group.resize(SPRITE_COUNT, gifo);
}

SpriteSheet::~SpriteSheet() { }

bool SpriteSheet::load() {
    Base::Texture texture;
    if (!texture.load("image/sprite")) {
        return false;
    }
    glBindTexture(GL_TEXTURE_2D, texture.tex);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glBindTexture(GL_TEXTURE_2D, 0);

    Base::Data data;
    data.read("image/sprite.sgsprite", 1u << 20);
    Base::ChunkReader chunks;
    if (!chunks.read(data) ||
        std::memcmp(chunks.magic(), SPRITE_MAGIC, sizeof(SPRITE_MAGIC)) ||
        chunks.version().first != 1) {
        return false;
    }

    auto chunk_gnam = chunks.get("GNAM");
    auto chunk_gifo = chunks.get("GIFO");
    auto chunk_sprt = chunks.get("SPRT");
    std::size_t gcount = chunk_gnam.second / 16;
    if (chunk_gifo.second != gcount * 6) {
        return false;
    }
    std::size_t scount = chunk_sprt.second / 12;
    const char (*data_gnam)[16] =
        reinterpret_cast<const char (*)[16]>(chunk_gnam.first);
    const FileGroupInfo *data_gifo =
        reinterpret_cast<const FileGroupInfo *>(chunk_gifo.first);
    const sg_sprite *data_sprt =
        reinterpret_cast<const sg_sprite *>(chunk_sprt.first);

    std::vector<GroupInfo> ginfo;
    ginfo.reserve(SPRITE_COUNT);
    for (int i = 0; i < SPRITE_COUNT; i++) {
        GroupInfo gr { 0, 0, nullptr };
        std::size_t j;
        for (j = 0; j < gcount; j++) {
            if (std::strcmp(SPRITE_NAMES[i], data_gnam[j]))
                continue;
            const auto &g = data_gifo[j];
            if (g.w == 0 || g.h == 0) {
                break;
            }
            std::size_t count = g.w * g.h;
            if (g.offset > scount || count > scount - g.offset) {
                return false;
            }
            gr.w = g.w;
            gr.h = g.h;
            gr.sprites = data_sprt + g.offset;
            break;
        }
        ginfo.push_back(gr);
    }

    m_data = std::move(data);
    m_group = std::move(ginfo);
    m_texture = std::move(texture);
    return true;
}

const struct sg_sprite &SpriteSheet::get(
    Game::Sprite sprite, int nx, int ny) const {
    int idx = static_cast<int>(sprite);
    if (idx < 0 || idx >= SPRITE_COUNT)
        Log::abort("Invalid sprite.");
    const auto &ifo = m_group[idx];
    if (nx < 0 || nx >= ifo.w || ny < 0 || ny >= ifo.h)
        return ZERO_SPRITE;
    return ifo.sprites[ny * ifo.w + nx];
}

SpriteArray::SpriteArray()
{ }

SpriteArray::SpriteArray(SpriteArray &&other)
    : m_array(std::move(other.m_array))
{ }

SpriteArray::~SpriteArray()
{ }

SpriteArray &SpriteArray::operator=(SpriteArray &&other) {
    m_array = std::move(other.m_array);
    return *this;
}

void SpriteArray::clear() {
    m_array.clear();
}

void SpriteArray::add(const sg_sprite &sp, float x, float y,
                      Base::Orientation orient) {
    using Base::Orientation;
    if (sp.w == 0) {
        return;
    }

    Vertex *data = m_array.insert(6);

    short tx0 = sp.x, tx1 = sp.x + sp.w;
    short ty1 = sp.y, ty0 = sp.y + sp.h;

    data[0].tx = tx0; data[0].ty = ty0;
    data[1].tx = tx1; data[1].ty = ty0;
    data[2].tx = tx0; data[2].ty = ty1;
    data[3].tx = tx0; data[3].ty = ty1;
    data[4].tx = tx1; data[4].ty = ty0;
    data[5].tx = tx1; data[5].ty = ty1;

    float rx0 = (float) -sp.cx, rx1 = (float) (sp.w - sp.cx);
    float ry0 = (float) -sp.cy, ry1 = (float) (sp.h - sp.cy);
    float vx[4], vy[4];
    switch (orient) {
    case Orientation::NORMAL:
        vx[0] = vx[2] = x + rx0;
        vx[1] = vx[3] = x + rx1;
        vy[0] = vy[1] = y + ry0;
        vy[2] = vy[3] = y + ry1;
        break;

    case Orientation::ROTATE_90:
        vx[2] = vx[3] = x + ry0;
        vx[0] = vx[1] = x + ry1;
        vy[2] = vy[0] = y + rx0;
        vy[3] = vy[1] = y + rx1;
        break;

    case Orientation::ROTATE_180:
        vx[3] = vx[1] = x + rx0;
        vx[2] = vx[0] = x + rx1;
        vy[3] = vy[2] = y + ry0;
        vy[1] = vy[0] = y + ry1;
        break;

    case Orientation::ROTATE_270:
        vx[1] = vx[0] = x + ry0;
        vx[3] = vx[2] = x + ry1;
        vy[1] = vy[3] = y + rx0;
        vy[0] = vy[2] = y + rx1;
        break;

    case Orientation::FLIP_VERTICAL:
        vx[0] = vx[2] = x + rx0;
        vx[1] = vx[3] = x + rx1;
        vy[0] = vy[1] = y + ry1;
        vy[2] = vy[3] = y + ry0;
        break;

    case Orientation::TRANSPOSE_2:
        vx[2] = vx[3] = x + ry0;
        vx[0] = vx[1] = x + ry1;
        vy[2] = vy[0] = y + rx1;
        vy[3] = vy[1] = y + rx0;
        break;

    case Orientation::FLIP_HORIZONTAL:
        vx[3] = vx[1] = x + rx0;
        vx[2] = vx[0] = x + rx1;
        vy[3] = vy[2] = y + ry1;
        vy[1] = vy[0] = y + ry0;
        break;

    case Orientation::TRANSPOSE:
        vx[1] = vx[0] = x + ry0;
        vx[3] = vx[2] = x + ry1;
        vy[1] = vy[3] = y + rx1;
        vy[0] = vy[2] = y + rx0;
        break;

    default:
#ifdef __GCC__
        __builtin_unreachable();
#endif
        return;
    }

    data[0].px = vx[0]; data[0].py = vy[0];
    data[1].px = vx[1]; data[1].py = vy[1];
    data[2].px = vx[2]; data[2].py = vy[2];
    data[3].px = vx[2]; data[3].py = vy[2];
    data[4].px = vx[1]; data[4].py = vy[1];
    data[5].px = vx[3]; data[5].py = vy[3];
}

void SpriteArray::upload(GLuint usage) {
    m_array.upload(usage);
}

}
<commit_msg>Fix vertical offset of sprites<commit_after>/* Copyright 2014 Dietrich Epp.
   This file is part of Legend of Feleria.  Legend of Feleria is
   licensed under the terms of the 2-clause BSD license.  For more
   information, see LICENSE.txt. */
#include "defs.hpp"
#include "sprite.hpp"
#include "sg/sprite.h"
#include "base/chunk.hpp"
#include <cstring>
namespace Graphics {
using Game::SPRITE_COUNT;

namespace {

const char SPRITE_MAGIC[16] = "Feleria Sprites";

#include "data/sprite.array.hpp"

struct FileGroupInfo {
    unsigned short w, h, offset;
};

const sg_sprite ZERO_SPRITE = { 0, 0, 0, 0, 0, 0 };

}

struct SpriteSheet::GroupInfo {
    int w, h;
    const sg_sprite *sprites;
};

SpriteSheet::SpriteSheet() {
    GroupInfo gifo { 0, 0, nullptr };
    m_group.resize(SPRITE_COUNT, gifo);
}

SpriteSheet::~SpriteSheet() { }

bool SpriteSheet::load() {
    Base::Texture texture;
    if (!texture.load("image/sprite")) {
        return false;
    }
    glBindTexture(GL_TEXTURE_2D, texture.tex);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glBindTexture(GL_TEXTURE_2D, 0);

    Base::Data data;
    data.read("image/sprite.sgsprite", 1u << 20);
    Base::ChunkReader chunks;
    if (!chunks.read(data) ||
        std::memcmp(chunks.magic(), SPRITE_MAGIC, sizeof(SPRITE_MAGIC)) ||
        chunks.version().first != 1) {
        return false;
    }

    auto chunk_gnam = chunks.get("GNAM");
    auto chunk_gifo = chunks.get("GIFO");
    auto chunk_sprt = chunks.get("SPRT");
    std::size_t gcount = chunk_gnam.second / 16;
    if (chunk_gifo.second != gcount * 6) {
        return false;
    }
    std::size_t scount = chunk_sprt.second / 12;
    const char (*data_gnam)[16] =
        reinterpret_cast<const char (*)[16]>(chunk_gnam.first);
    const FileGroupInfo *data_gifo =
        reinterpret_cast<const FileGroupInfo *>(chunk_gifo.first);
    const sg_sprite *data_sprt =
        reinterpret_cast<const sg_sprite *>(chunk_sprt.first);

    std::vector<GroupInfo> ginfo;
    ginfo.reserve(SPRITE_COUNT);
    for (int i = 0; i < SPRITE_COUNT; i++) {
        GroupInfo gr { 0, 0, nullptr };
        std::size_t j;
        for (j = 0; j < gcount; j++) {
            if (std::strcmp(SPRITE_NAMES[i], data_gnam[j]))
                continue;
            const auto &g = data_gifo[j];
            if (g.w == 0 || g.h == 0) {
                break;
            }
            std::size_t count = g.w * g.h;
            if (g.offset > scount || count > scount - g.offset) {
                return false;
            }
            gr.w = g.w;
            gr.h = g.h;
            gr.sprites = data_sprt + g.offset;
            break;
        }
        ginfo.push_back(gr);
    }

    m_data = std::move(data);
    m_group = std::move(ginfo);
    m_texture = std::move(texture);
    return true;
}

const struct sg_sprite &SpriteSheet::get(
    Game::Sprite sprite, int nx, int ny) const {
    int idx = static_cast<int>(sprite);
    if (idx < 0 || idx >= SPRITE_COUNT)
        Log::abort("Invalid sprite.");
    const auto &ifo = m_group[idx];
    if (nx < 0 || nx >= ifo.w || ny < 0 || ny >= ifo.h)
        return ZERO_SPRITE;
    return ifo.sprites[ny * ifo.w + nx];
}

SpriteArray::SpriteArray()
{ }

SpriteArray::SpriteArray(SpriteArray &&other)
    : m_array(std::move(other.m_array))
{ }

SpriteArray::~SpriteArray()
{ }

SpriteArray &SpriteArray::operator=(SpriteArray &&other) {
    m_array = std::move(other.m_array);
    return *this;
}

void SpriteArray::clear() {
    m_array.clear();
}

void SpriteArray::add(const sg_sprite &sp, float x, float y,
                      Base::Orientation orient) {
    using Base::Orientation;
    if (sp.w == 0) {
        return;
    }

    Vertex *data = m_array.insert(6);

    short tx0 = sp.x, tx1 = sp.x + sp.w;
    short ty1 = sp.y, ty0 = sp.y + sp.h;

    data[0].tx = tx0; data[0].ty = ty0;
    data[1].tx = tx1; data[1].ty = ty0;
    data[2].tx = tx0; data[2].ty = ty1;
    data[3].tx = tx0; data[3].ty = ty1;
    data[4].tx = tx1; data[4].ty = ty0;
    data[5].tx = tx1; data[5].ty = ty1;

    float rx0 = (float) -sp.cx, rx1 = (float) (sp.w - sp.cx);
    float ry0 = (float) (sp.cy - sp.h), ry1 = (float) +sp.cy;
    float vx[4], vy[4];
    switch (orient) {
    case Orientation::NORMAL:
        vx[0] = vx[2] = x + rx0;
        vx[1] = vx[3] = x + rx1;
        vy[0] = vy[1] = y + ry0;
        vy[2] = vy[3] = y + ry1;
        break;

    case Orientation::ROTATE_90:
        vx[2] = vx[3] = x + ry0;
        vx[0] = vx[1] = x + ry1;
        vy[2] = vy[0] = y + rx0;
        vy[3] = vy[1] = y + rx1;
        break;

    case Orientation::ROTATE_180:
        vx[3] = vx[1] = x + rx0;
        vx[2] = vx[0] = x + rx1;
        vy[3] = vy[2] = y + ry0;
        vy[1] = vy[0] = y + ry1;
        break;

    case Orientation::ROTATE_270:
        vx[1] = vx[0] = x + ry0;
        vx[3] = vx[2] = x + ry1;
        vy[1] = vy[3] = y + rx0;
        vy[0] = vy[2] = y + rx1;
        break;

    case Orientation::FLIP_VERTICAL:
        vx[0] = vx[2] = x + rx0;
        vx[1] = vx[3] = x + rx1;
        vy[0] = vy[1] = y + ry1;
        vy[2] = vy[3] = y + ry0;
        break;

    case Orientation::TRANSPOSE_2:
        vx[2] = vx[3] = x + ry0;
        vx[0] = vx[1] = x + ry1;
        vy[2] = vy[0] = y + rx1;
        vy[3] = vy[1] = y + rx0;
        break;

    case Orientation::FLIP_HORIZONTAL:
        vx[3] = vx[1] = x + rx0;
        vx[2] = vx[0] = x + rx1;
        vy[3] = vy[2] = y + ry1;
        vy[1] = vy[0] = y + ry0;
        break;

    case Orientation::TRANSPOSE:
        vx[1] = vx[0] = x + ry0;
        vx[3] = vx[2] = x + ry1;
        vy[1] = vy[3] = y + rx1;
        vy[0] = vy[2] = y + rx0;
        break;

    default:
#ifdef __GCC__
        __builtin_unreachable();
#endif
        return;
    }

    data[0].px = vx[0]; data[0].py = vy[0];
    data[1].px = vx[1]; data[1].py = vy[1];
    data[2].px = vx[2]; data[2].py = vy[2];
    data[3].px = vx[2]; data[3].py = vy[2];
    data[4].px = vx[1]; data[4].py = vy[1];
    data[5].px = vx[3]; data[5].py = vy[3];
}

void SpriteArray::upload(GLuint usage) {
    m_array.upload(usage);
}

}
<|endoftext|>


<commit_before>#pragma once

namespace gcl::mp::meta
{
    template <typename ... Ts>
    requires(sizeof...(Ts) not_eq 0)
    class join {
        template <typename...>
        struct impl;
        template <typename first_type, typename second_type, typename... types>
        struct impl<first_type, second_type, types...> {
            using type = typename join<typename join<first_type, second_type>::type, types...>::type;
        };
        template <typename T>
        struct impl<T> {
            using type = T;
        };
        template <template <typename...> typename Type, typename... Us, typename... Vs>
        struct impl<Type<Us...>, Type<Vs...>> {
            using type = Type<Us..., Vs...>;
        };

      public:
          using type = typename impl<Ts...>::type;
    };
    template <typename... Ts>
    using join_t = typename join<Ts...>::type;

    template <typename T, typename... to_remove>
    class remove;
    template <template <typename ...> typename Type, typename ... Ts, typename ... to_remove>
    class remove<Type<Ts...>, to_remove...> {
        template <typename T>
        using element_type = std::conditional_t<((std::is_same_v<T, to_remove> || ...)), Type<>, Type<T>>;

      public:
        using type = join_t<Type<>, element_type<Ts>...>;
    };
    template <template <typename...> typename Type, typename... Ts, typename... to_remove>
    class remove<Type<Ts...>, Type<to_remove...>> {
        template <typename T>
        using element_type = std::conditional_t<((std::is_same_v<T, to_remove> || ...)), Type<>, Type<T>>;

      public:
        using type = join_t<Type<>, element_type<Ts>...>;
    };
    template <typename T, typename ... to_remove>
    using remove_t = typename remove<T, to_remove...>::type;

    template <typename... Ts>
    class type_sequence {

        constexpr type_sequence() = default;

        template <typename T>
        struct flatten {
            using type = type_sequence<T>;
        };
        template <typename... argument_types>
        struct flatten<type_sequence<argument_types...>> {
            using type = type_sequence<argument_types...>;
        };
        template <typename T>
        using flatten_t = typename flatten<T>::type;

        // todo : remove_if<type_trait_as_predicate> => filter
        // todo : `- remove_duplicates => previous position
        // todo : conjunction, disjunction

      public:
        template <typename... arguments_t>
        using add = join_t<type_sequence<Ts...>, flatten_t<arguments_t>...>;
        template <typename... to_remove>
        using remove = remove_t<type_sequence<Ts...>, to_remove...>;
    };

}

namespace gcl::mp::tests::meta
{
    template <typename ... Ts>
    struct type_seq {};

    using namespace gcl::mp::meta;

    namespace join
    {
        static_assert(std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int>, type_seq<char, double>>>);
        static_assert(std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int, char, double>>>);
        static_assert(
            std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int>, type_seq<char>, type_seq<double>>>);
        static_assert(std::is_same_v<
                      type_seq<int, char, double, float>,
                      join_t<type_seq<int>, type_seq<char>, type_seq<double>, type_seq<float>>>);
    }
    namespace remove
    {
        static_assert(std::is_same_v<type_seq<>, remove_t<type_seq<>>>);
        static_assert(std::is_same_v<type_seq<int>, remove_t<type_seq<int, char>, char>>);
        static_assert(std::is_same_v<type_seq<int>, remove_t<type_seq<int, char>, char, char>>);
    }
    namespace type_sequence_t::add
    {
        static_assert(std::is_same_v<type_sequence<int, char>, type_sequence<int>::add<char>>);
        static_assert(std::is_same_v<type_sequence<int, char>, type_sequence<int>::add<type_sequence<char>>>);
        static_assert(std::is_same_v<type_sequence<int, char>, type_sequence<int, char>::add<type_sequence<>>>);
        static_assert(std::is_same_v<
                      type_sequence<int, char, double, bool>,
                      type_sequence<int>::add<type_sequence<>>::add<type_sequence<char>>::add<
                          type_sequence<double>>::add<bool>>);
        static_assert(
            std::is_same_v<type_sequence<int, char, double>, type_sequence<int>::add<type_sequence<char>, double>>);
        static_assert(std::is_same_v<
                      type_sequence<int, char, double, float, bool>,
                      type_sequence<int>::add<type_sequence<>>::add<
                          type_sequence<char>>::add<type_sequence<double>, float>::add<bool>>);
    }
    namespace type_sequence_t::remove
    {
        static_assert(std::is_same_v<type_sequence<int>, type_sequence<int, char>::remove<char>>);
        static_assert(std::is_same_v<type_sequence<>, type_sequence<>::remove<char>>);
        static_assert(std::is_same_v<type_sequence<int>, type_sequence<int, char>::remove<type_sequence<char>>>);
    }
}<commit_msg>[mp::meta] : filter<commit_after>#pragma once

#include <type_traits>
#include <utility>

namespace gcl::mp::meta
{
    template <template <typename...> class T, typename... Ts>
    class pack_as {

        template <typename... types>
        struct impl {
            using type = T<types...>;
        };
        template <template <typename...> class pack_t, typename... types>
        struct impl<pack_t<types...>> {
            using type = T<types...>;
        };

      public:
        using type = typename impl<Ts...>::type;
    };
    template <template <typename...> class T, typename... Ts>
    using pack_as_t = typename pack_as<T, Ts...>::type;

    template <typename ... Ts>
    requires(sizeof...(Ts) not_eq 0)
    class join {
        template <typename...>
        struct impl;
        template <typename first_type, typename second_type, typename... types>
        struct impl<first_type, second_type, types...> {
            using type = typename join<typename join<first_type, second_type>::type, types...>::type;
        };
        template <typename T>
        struct impl<T> {
            using type = T;
        };
        template <template <typename...> typename Type, typename... Us, typename... Vs>
        struct impl<Type<Us...>, Type<Vs...>> {
            using type = Type<Us..., Vs...>;
        };

      public:
          using type = typename impl<Ts...>::type;
    };
    template <typename... Ts>
    using join_t = typename join<Ts...>::type;

    template <typename T, template <typename> typename predicate>
    class filter;
    template <template <typename...> typename Type, typename... Ts, template<typename> typename predicate>
    class filter<Type<Ts...>, predicate> {

        template <typename T>
        using element_type = std::conditional_t<predicate<T>::value, Type<>, Type<T>>;

      public:
        using type = join_t<Type<>, element_type<Ts>...>;
    };
    template <typename T, template <typename> typename predicate>
    using filter_t = typename filter<T, predicate>::type;

    template <typename T, typename... to_remove>
    class remove
    {
        template <typename candidate>
        struct listed_as_to_remove {
            constexpr static auto value = ((std::is_same_v<candidate, to_remove> or ...));
        };

    public:
        using type = filter_t<T, listed_as_to_remove>;
    };
    template <typename T, typename... to_remove>
    using remove_t = typename remove<T, to_remove...>::type;

    template <typename... Ts>
    class type_sequence {

        constexpr static auto size = sizeof...(Ts);
        constexpr static auto empty = (size == 0);
        // todo : at / get <index>

        constexpr type_sequence() = default;

        // todo : remove_if<type_trait_as_predicate> => filter
        // todo : `- remove_duplicates => previous position
        // todo : conjunction, disjunction
        // todo : split

      public:
        template <typename... arguments_t>
        using add = join_t<type_sequence<Ts...>, pack_as_t<type_sequence, arguments_t>...>;
        template <typename... to_remove>
        using remove = remove_t<type_sequence<Ts...>, to_remove...>; // todo : flatten / repack
    };

    //template <typename ... Ts, typename ...Us>
    //constexpr auto operator+(type_sequence<Ts...>, type_sequence<Us...>)
    //{
    //    return type_sequence<Ts...>::template add<Us...>;
    //}
    //template <typename... Ts, typename... Us>
    //constexpr auto operator-(type_sequence<Ts...>, type_sequence<Us...>)
    //{
    //    return type_sequence<Ts...>::template remove<Us...>;
    //}
}

namespace gcl::mp::tests::meta
{
    template <typename ... Ts>
    struct type_seq {};

    using namespace gcl::mp::meta;

    namespace pack_as
    {
        static_assert(std::is_same_v<type_seq<int, char>, pack_as_t<type_seq, int, char>>);
        static_assert(std::is_same_v<type_seq<int, char>, pack_as_t<type_seq, type_seq<int, char>>>);
    }

    namespace join
    {
        static_assert(std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int>, type_seq<char, double>>>);
        static_assert(std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int, char, double>>>);
        static_assert(
            std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int>, type_seq<char>, type_seq<double>>>);
        static_assert(std::is_same_v<
                      type_seq<int, char, double, float>,
                      join_t<type_seq<int>, type_seq<char>, type_seq<double>, type_seq<float>>>);
    }
    namespace filters
    {
        template <typename T>
        using is_int = std::is_same<T, int>;
        static_assert(std::is_same_v<type_seq<char>, filter<type_seq<int, char>, is_int>::type>);
    }
    namespace remove
    {
        static_assert(std::is_same_v<type_seq<>, remove_t<type_seq<>>>);
        static_assert(std::is_same_v<type_seq<int>, remove_t<type_seq<int, char>, char>>);
        static_assert(std::is_same_v<type_seq<int>, remove_t<type_seq<int, char>, char, char>>);
    }
    namespace type_sequence_t::add
    {
        static_assert(std::is_same_v<type_sequence<int, char>, type_sequence<int>::add<char>>);
        static_assert(std::is_same_v<type_sequence<int, char>, type_sequence<int>::add<type_sequence<char>>>);
        static_assert(std::is_same_v<type_sequence<int, char>, type_sequence<int, char>::add<type_sequence<>>>);
        static_assert(std::is_same_v<
                      type_sequence<int, char, double, bool>,
                      type_sequence<int>::add<type_sequence<>>::add<type_sequence<char>>::add<
                          type_sequence<double>>::add<bool>>);
        static_assert(
            std::is_same_v<type_sequence<int, char, double>, type_sequence<int>::add<type_sequence<char>, double>>);
        static_assert(std::is_same_v<
                      type_sequence<int, char, double, float, bool>,
                      type_sequence<int>::add<type_sequence<>>::add<
                          type_sequence<char>>::add<type_sequence<double>, float>::add<bool>>);
    }
    namespace type_sequence_t::remove
    {
        static_assert(std::is_same_v<type_sequence<int>, type_sequence<int, char>::remove<char>>);
        static_assert(std::is_same_v<type_sequence<>, type_sequence<>::remove<char>>);
        // static_assert(std::is_same_v<type_sequence<int>, type_sequence<int, char>::remove<type_sequence<char>>>);
    }
}<|endoftext|>


<commit_before>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 27/06/08.

    This file is part of MRtrix.

    MRtrix is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MRtrix 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 MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gui/dialog/file.h"
#include "image/format/list.h"

namespace MR
{
  namespace GUI
  {
    namespace Dialog
    {
      namespace File
      {

        const std::string image_filter_string = "Medical Images (*" + join (MR::Image::Format::known_extensions, " *") + ")";

        std::string get_folder ( QWidget* parent, const std::string& caption, const std::string& folder)
        {
          QString qstring = QFileDialog::getExistingDirectory (parent, caption.c_str(), folder.size() ? QString(folder.c_str()) : QString());
          if (qstring.size()) {
            std::string folder = qstring.toUtf8().data();
            QDir::setCurrent (Path::dirname (folder).c_str());
            return folder;
          }
          return std::string();
        }

        std::string get_file (QWidget* parent, const std::string& caption, const std::string& filter, const std::string& folder)
        {
          QString qstring = QFileDialog::getOpenFileName (parent, caption.c_str(), folder.size() ? QString(folder.c_str()) : QString(), filter.c_str());
          if (qstring.size()) {
            std::string name = qstring.toUtf8().data();
            QDir::setCurrent (Path::dirname (name).c_str());
            return name;
          }
          return std::string();
        }

        std::vector<std::string> get_files (QWidget* parent, const std::string& caption, const std::string& filter, const std::string& folder)
        {
          QStringList qlist = QFileDialog::getOpenFileNames (parent, caption.c_str(), folder.size() ? QString(folder.c_str()) : QString(), filter.c_str());
          std::vector<std::string> list;
          if (qlist.size()) {
            for (int n = 0; n < qlist.size(); ++n)
              list.push_back (qlist[n].toUtf8().data());
            QDir::setCurrent (Path::dirname (list[0]).c_str());
          }
          return list;
        }

        std::string get_save_name (QWidget* parent, const std::string& caption, const std::string& filter, const std::string& folder)
        {
          QString qstring = QFileDialog::getSaveFileName (parent, caption.c_str(), folder.size() ? QString(folder.c_str()) : QString(), filter.c_str());
          std::string name;
          if (qstring.size()) {
            name = qstring.toUtf8().data();
            QDir::setCurrent (Path::dirname (name).c_str());
          }
          return name;
        }

      }
    }
  }
}

<commit_msg>GUI: prevent use of native file dialog on MacOSX<commit_after>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 27/06/08.

    This file is part of MRtrix.

    MRtrix is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MRtrix 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 MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gui/dialog/file.h"
#include "image/format/list.h"

#ifndef MRTRIX_MACOSX
# define FILE_DIALOG_OPTIONS QFileDialog::DontUseNativeDialog
#else
# define FILE_DIALOG_OPTIONS static_cast<QFileDialog::Options> (0)
#endif

namespace MR
{
  namespace GUI
  {
    namespace Dialog
    {
      namespace File
      {

        const std::string image_filter_string = "Medical Images (*" + join (MR::Image::Format::known_extensions, " *") + ")";

        std::string get_folder ( QWidget* parent, const std::string& caption, const std::string& folder)
        {
          QString qstring = QFileDialog::getExistingDirectory (parent, caption.c_str(), folder.size() ? QString(folder.c_str()) : QString(), QFileDialog::ShowDirsOnly | FILE_DIALOG_OPTIONS);
          if (qstring.size()) {
            std::string folder = qstring.toUtf8().data();
            QDir::setCurrent (Path::dirname (folder).c_str());
            return folder;
          }
          return std::string();
        }

        std::string get_file (QWidget* parent, const std::string& caption, const std::string& filter, const std::string& folder)
        {
          QString qstring = QFileDialog::getOpenFileName (parent, caption.c_str(), folder.size() ? QString(folder.c_str()) : QString(), filter.c_str(), 0, FILE_DIALOG_OPTIONS);
          if (qstring.size()) {
            std::string name = qstring.toUtf8().data();
            QDir::setCurrent (Path::dirname (name).c_str());
            return name;
          }
          return std::string();
        }

        std::vector<std::string> get_files (QWidget* parent, const std::string& caption, const std::string& filter, const std::string& folder)
        {
          QStringList qlist = QFileDialog::getOpenFileNames (parent, caption.c_str(), folder.size() ? QString(folder.c_str()) : QString(), filter.c_str(), 0, FILE_DIALOG_OPTIONS);
          std::vector<std::string> list;
          if (qlist.size()) {
            for (int n = 0; n < qlist.size(); ++n)
              list.push_back (qlist[n].toUtf8().data());
            QDir::setCurrent (Path::dirname (list[0]).c_str());
          }
          return list;
        }

        std::string get_save_name (QWidget* parent, const std::string& caption, const std::string& filter, const std::string& folder)
        {
          QString qstring = QFileDialog::getSaveFileName (parent, caption.c_str(), folder.size() ? QString(folder.c_str()) : QString(), filter.c_str(), 0, FILE_DIALOG_OPTIONS);
          std::string name;
          if (qstring.size()) {
            name = qstring.toUtf8().data();
            QDir::setCurrent (Path::dirname (name).c_str());
          }
          return name;
        }

      }
    }
  }
}

<|endoftext|>


<commit_before>#include "adapters/net.hpp"

#include <linux/nl80211.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>

#include "utils/file.hpp"

POLYBAR_NS

namespace net {
  // class : wireless_network {{{

  /**
   * Query the wireless device for information
   * about the current connection
   */
  bool wireless_network::query(bool accumulate) {
    if (!network::query(accumulate)) {
      return false;
    }

    struct nl_sock* sk = nl_socket_alloc();
    if (sk == nullptr) {
      return false;
    }

    if (genl_connect(sk) < 0) {
      return false;
    }

    int driver_id = genl_ctrl_resolve(sk, "nl80211");
    if (driver_id < 0) {
      nl_socket_free(sk);
      return false;
    }

    if (nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, scan_cb, this) != 0) {
      nl_socket_free(sk);
      return false;
    }

    struct nl_msg* msg = nlmsg_alloc();
    if (msg == nullptr) {
      nl_socket_free(sk);
      return false;
    }

    if ((genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0) == nullptr) ||
        nla_put_u32(msg, NL80211_ATTR_IFINDEX, m_ifid) < 0) {
      nlmsg_free(msg);
      nl_socket_free(sk);
      return false;
    }

    // nl_send_sync always frees msg
    if (nl_send_sync(sk, msg) < 0) {
      nl_socket_free(sk);
      return false;
    }

    nl_socket_free(sk);

    return true;
  }

  /**
   * Check current connection state
   */
  bool wireless_network::connected() const {
    if (!network::test_interface()) {
      return false;
    }
    return !m_essid.empty();
  }

  /**
   * ESSID reported by last query
   */
  string wireless_network::essid() const {
    return m_essid;
  }

  /**
   * Signal strength percentage reported by last query
   */
  int wireless_network::signal() const {
    return m_signalstrength.percentage();
  }

  /**
   * Link quality percentage reported by last query
   */
  int wireless_network::quality() const {
    return m_linkquality.percentage();
  }

  /**
   * Callback to parse scan results
   */
  int wireless_network::scan_cb(struct nl_msg* msg, void* instance) {
    auto wn = static_cast<wireless_network*>(instance);
    auto gnlh = static_cast<genlmsghdr*>(nlmsg_data(nlmsg_hdr(msg)));
    struct nlattr* tb[NL80211_ATTR_MAX + 1];
    struct nlattr* bss[NL80211_BSS_MAX + 1];

    struct nla_policy bss_policy[NL80211_BSS_MAX + 1]{};
    bss_policy[NL80211_BSS_TSF].type = NLA_U64;
    bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32;
    bss_policy[NL80211_BSS_BSSID].type = NLA_UNSPEC;
    bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
    bss_policy[NL80211_BSS_CAPABILITY].type = NLA_U16;
    bss_policy[NL80211_BSS_INFORMATION_ELEMENTS].type = NLA_UNSPEC;
    bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
    bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
    bss_policy[NL80211_BSS_STATUS].type = NLA_U32;

    if (nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), nullptr) < 0) {
      return NL_SKIP;
    }

    if (tb[NL80211_ATTR_BSS] == nullptr) {
      return NL_SKIP;
    }

    if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy) != 0) {
      return NL_SKIP;
    }

    if (!wn->associated_or_joined(bss)) {
      return NL_SKIP;
    }

    wn->parse_essid(bss);
    wn->parse_frequency(bss);
    wn->parse_signal(bss);
    wn->parse_quality(bss);

    return NL_SKIP;
  }

  /**
   * Check for a connection to a AP
   */
  bool wireless_network::associated_or_joined(struct nlattr** bss) {
    if (bss[NL80211_BSS_STATUS] == nullptr) {
      return false;
    }

    auto status = nla_get_u32(bss[NL80211_BSS_STATUS]);

    switch (status) {
      case NL80211_BSS_STATUS_ASSOCIATED:
      case NL80211_BSS_STATUS_IBSS_JOINED:
      case NL80211_BSS_STATUS_AUTHENTICATED:
        return true;
      default:
        return false;
    }
  }

  /**
   * Set the ESSID
   */
  void wireless_network::parse_essid(struct nlattr** bss) {
    m_essid.clear();

    if (bss[NL80211_BSS_INFORMATION_ELEMENTS] != nullptr) {
      // Information Element ID from ieee80211.h
      #define WLAN_EID_SSID 0

      auto ies = static_cast<char*>(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
      auto ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
      const auto hdr_len = 2;

      while (ies_len > hdr_len && ies[0] != WLAN_EID_SSID) {
        ies_len -= ies[1] + hdr_len;
        ies += ies[1] + hdr_len;
      }

      if (ies_len > hdr_len && ies_len > ies[1] + hdr_len) {
        auto essid_begin = ies + hdr_len;
        auto essid_end = essid_begin + ies[1];

        // Only use printable characters of the current locale
        std::copy_if(essid_begin, essid_end, std::back_inserter(m_essid),
            [](char c) { return isprint(static_cast<unsigned char>(c)); });
      }
    }
  }

  /**
   * Set frequency
   */
  void wireless_network::parse_frequency(struct nlattr** bss) {
    if (bss[NL80211_BSS_FREQUENCY] != nullptr) {
      // in MHz
      m_frequency = static_cast<int>(nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
    }
  }

  /**
   * Set device driver quality values
   */
  void wireless_network::parse_quality(struct nlattr** bss) {
    if (bss[NL80211_BSS_SIGNAL_UNSPEC] != nullptr) {
      // Signal strength in unspecified units, scaled to 0..100 (u8)
      m_linkquality.val = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
      m_linkquality.max = 100;
    }
  }

  /**
   * Set the signalstrength
   */
  void wireless_network::parse_signal(struct nlattr** bss) {
    if (bss[NL80211_BSS_SIGNAL_MBM] != nullptr) {
      // signalstrength in dBm
      int signalstrength = static_cast<int>(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM])) / 100;

      // WiFi-hardware usually operates in the range -90 to -20dBm.
      const int hardware_max = -20;
      const int hardware_min = -90;
      signalstrength = std::max(hardware_min, std::min(signalstrength, hardware_max));

      // Shift for positive values
      m_signalstrength.val = signalstrength - hardware_min;
      m_signalstrength.max = hardware_max - hardware_min;
    }
  }
}  // namespace net

POLYBAR_NS_END
<commit_msg>fix(net): Allow all characters for the SSID<commit_after>#include "adapters/net.hpp"

#include <linux/nl80211.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>

#include "utils/file.hpp"

POLYBAR_NS

namespace net {
  // class : wireless_network {{{

  /**
   * Query the wireless device for information
   * about the current connection
   */
  bool wireless_network::query(bool accumulate) {
    if (!network::query(accumulate)) {
      return false;
    }

    struct nl_sock* sk = nl_socket_alloc();
    if (sk == nullptr) {
      return false;
    }

    if (genl_connect(sk) < 0) {
      return false;
    }

    int driver_id = genl_ctrl_resolve(sk, "nl80211");
    if (driver_id < 0) {
      nl_socket_free(sk);
      return false;
    }

    if (nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, scan_cb, this) != 0) {
      nl_socket_free(sk);
      return false;
    }

    struct nl_msg* msg = nlmsg_alloc();
    if (msg == nullptr) {
      nl_socket_free(sk);
      return false;
    }

    if ((genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0) == nullptr) ||
        nla_put_u32(msg, NL80211_ATTR_IFINDEX, m_ifid) < 0) {
      nlmsg_free(msg);
      nl_socket_free(sk);
      return false;
    }

    // nl_send_sync always frees msg
    if (nl_send_sync(sk, msg) < 0) {
      nl_socket_free(sk);
      return false;
    }

    nl_socket_free(sk);

    return true;
  }

  /**
   * Check current connection state
   */
  bool wireless_network::connected() const {
    if (!network::test_interface()) {
      return false;
    }
    return !m_essid.empty();
  }

  /**
   * ESSID reported by last query
   */
  string wireless_network::essid() const {
    return m_essid;
  }

  /**
   * Signal strength percentage reported by last query
   */
  int wireless_network::signal() const {
    return m_signalstrength.percentage();
  }

  /**
   * Link quality percentage reported by last query
   */
  int wireless_network::quality() const {
    return m_linkquality.percentage();
  }

  /**
   * Callback to parse scan results
   */
  int wireless_network::scan_cb(struct nl_msg* msg, void* instance) {
    auto wn = static_cast<wireless_network*>(instance);
    auto gnlh = static_cast<genlmsghdr*>(nlmsg_data(nlmsg_hdr(msg)));
    struct nlattr* tb[NL80211_ATTR_MAX + 1];
    struct nlattr* bss[NL80211_BSS_MAX + 1];

    struct nla_policy bss_policy[NL80211_BSS_MAX + 1]{};
    bss_policy[NL80211_BSS_TSF].type = NLA_U64;
    bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32;
    bss_policy[NL80211_BSS_BSSID].type = NLA_UNSPEC;
    bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
    bss_policy[NL80211_BSS_CAPABILITY].type = NLA_U16;
    bss_policy[NL80211_BSS_INFORMATION_ELEMENTS].type = NLA_UNSPEC;
    bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
    bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
    bss_policy[NL80211_BSS_STATUS].type = NLA_U32;

    if (nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), nullptr) < 0) {
      return NL_SKIP;
    }

    if (tb[NL80211_ATTR_BSS] == nullptr) {
      return NL_SKIP;
    }

    if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy) != 0) {
      return NL_SKIP;
    }

    if (!wn->associated_or_joined(bss)) {
      return NL_SKIP;
    }

    wn->parse_essid(bss);
    wn->parse_frequency(bss);
    wn->parse_signal(bss);
    wn->parse_quality(bss);

    return NL_SKIP;
  }

  /**
   * Check for a connection to a AP
   */
  bool wireless_network::associated_or_joined(struct nlattr** bss) {
    if (bss[NL80211_BSS_STATUS] == nullptr) {
      return false;
    }

    auto status = nla_get_u32(bss[NL80211_BSS_STATUS]);

    switch (status) {
      case NL80211_BSS_STATUS_ASSOCIATED:
      case NL80211_BSS_STATUS_IBSS_JOINED:
      case NL80211_BSS_STATUS_AUTHENTICATED:
        return true;
      default:
        return false;
    }
  }

  /**
   * Set the ESSID
   */
  void wireless_network::parse_essid(struct nlattr** bss) {
    m_essid.clear();

    if (bss[NL80211_BSS_INFORMATION_ELEMENTS] != nullptr) {
      // Information Element ID from ieee80211.h
      #define WLAN_EID_SSID 0

      auto ies = static_cast<char*>(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
      auto ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
      const auto hdr_len = 2;

      while (ies_len > hdr_len && ies[0] != WLAN_EID_SSID) {
        ies_len -= ies[1] + hdr_len;
        ies += ies[1] + hdr_len;
      }

      if (ies_len > hdr_len && ies_len > ies[1] + hdr_len) {
        auto essid_begin = ies + hdr_len;
        auto essid_end = essid_begin + ies[1];

        std::copy(essid_begin, essid_end, std::back_inserter(m_essid));
      }
    }
  }

  /**
   * Set frequency
   */
  void wireless_network::parse_frequency(struct nlattr** bss) {
    if (bss[NL80211_BSS_FREQUENCY] != nullptr) {
      // in MHz
      m_frequency = static_cast<int>(nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
    }
  }

  /**
   * Set device driver quality values
   */
  void wireless_network::parse_quality(struct nlattr** bss) {
    if (bss[NL80211_BSS_SIGNAL_UNSPEC] != nullptr) {
      // Signal strength in unspecified units, scaled to 0..100 (u8)
      m_linkquality.val = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
      m_linkquality.max = 100;
    }
  }

  /**
   * Set the signalstrength
   */
  void wireless_network::parse_signal(struct nlattr** bss) {
    if (bss[NL80211_BSS_SIGNAL_MBM] != nullptr) {
      // signalstrength in dBm
      int signalstrength = static_cast<int>(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM])) / 100;

      // WiFi-hardware usually operates in the range -90 to -20dBm.
      const int hardware_max = -20;
      const int hardware_min = -90;
      signalstrength = std::max(hardware_min, std::min(signalstrength, hardware_max));

      // Shift for positive values
      m_signalstrength.val = signalstrength - hardware_min;
      m_signalstrength.max = hardware_max - hardware_min;
    }
  }
}  // namespace net

POLYBAR_NS_END
<|endoftext|>


<commit_before>// ********************************************************************
// Copyright 2010, Institute of Computer and Network Engineering,
//                 TU-Braunschweig
// All rights reserved
// Any reproduction, use, distribution or disclosure of this program,
// without the express, prior written consent of the authors is
// strictly prohibited.
//
// University of Technology Braunschweig
// Institute of Computer and Network Engineering
// Hans-Sommer-Str. 66
// 38118 Braunschweig, Germany
//
// ESA SPECIAL LICENSE
//
// This program may be freely used, copied, modified, and redistributed
// by the European Space Agency for the Agency's own requirements.
//
// The program is provided "as is", there is no warranty that
// the program is correct or suitable for any purpose,
// neither implicit nor explicit. The program and the information in it
// contained do not necessarily reflect the policy of the
// European Space Agency or of TU-Braunschweig.
// ********************************************************************
// Title:      timingmonitor.h
//
// ScssId:
//
// Origin:     HW-SW SystemC Co-Simulation SoC Validation Platform
//
// Purpose:    The timing monitor can be used to track
//             progress, performance and simulation time
//             of testbenches.
//
//
// Modified on $Date$
//          at $Revision$
//          by $Author$
//
// Principal:  European Space Agency
// Author:     VLSI working group @ IDA @ TUBS
// Maintainer: Thomas Schuster
// Reviewed:
// ********************************************************************

#include "timingmonitor.h"

// Initialize timing map (static - must be done outside class def)
TimingMonitor::t_timing_map TimingMonitor::timing_map;

// Create a new timing record and set starting time
void TimingMonitor::phase_start_timing(const unsigned int id, const char * name) {

  t_timing_rec tmp;

  tmp.name = (char *)name;
  tmp.st_start = sc_core::sc_time_stamp();
  tmp.rt_start = std::clock();
  tmp.st_end = sc_core::SC_ZERO_TIME;
  tmp.rt_end = std::clock();

  timing_map[id] = tmp;

}

// Enter phase finishing time
void TimingMonitor::phase_end_timing(const unsigned int id) {

  t_timing_rec tmp;
  t_timing_it it;

  it = timing_map.find(id);

  // Forbidden to set end timing before creating phase (calling phase_start_timing)
  if (it == timing_map.end()) {

    v::error << "TimingMonitor" << "No such phase: " << id << v::endl;

  }

  tmp=it->second;

  tmp.st_end = sc_core::sc_time_stamp();
  tmp.rt_end = std::clock();

  timing_map[id] = tmp;

}

// Return simulation time of phase id
sc_core::sc_time TimingMonitor::phase_systime(const unsigned int id) {

  t_timing_it it;

  it = timing_map.find(id);

  // Phase/key must exist in timing_map
  if (it == timing_map.end()) {

    v::error << "TimingMonitor" << "No such phase: " << id << v::endl;

    return(sc_core::sc_time(0,SC_NS));

  }

  return((it->second).st_end - (it->second).st_start);
}

// Return real time for processing phase id
double TimingMonitor::phase_realtime(const unsigned int id) {

  t_timing_it it;

  clock_t start_clock;
  clock_t end_clock;
  double  diff_sec;

  it = timing_map.find(id);

  // Phase/key must exist in timing_map
  if (it == timing_map.end()) {

    v::error << "TimingMonitor" << "No such phase: " << id << v::endl;

    return(0);

  }

  start_clock = (it->second).rt_start;
  end_clock   = (it->second).rt_end;

  diff_sec = (end_clock - start_clock)/(double)CLOCKS_PER_SEC;

  return(diff_sec);
}

// Return name of phase id
const char * TimingMonitor::phase_get_name(const unsigned int id) {

  t_timing_it it;

  it = timing_map.find(id);

  // Phase/key must exist in timing_map
  if (it == timing_map.end()) {

    v::error << "TimingMonitor" << "No such phase: " << id << v::endl;

    return("Unknown Phase");

  }

  return((it->second).name);

}

// Generate timing report for all phases at 'info' level.
void TimingMonitor::report_timing() {

  unsigned int id;
  t_timing_rec tmp;
  t_timing_it it;

  it = timing_map.begin();

  v::report << "TimingMonitor" << "******************************************************************" << v::endl;
  v::report << "TimingMonitor" << "* TIMING SUMMARY " << v::endl;
  v::report << "TimingMonitor" << "* -------------- " << v::endl;

  // Walk through timing map
  while(it != timing_map.end()) {

    id  = it->first;
    tmp = it->second;

    v::report << "TimingMonitor" << "* Phase: " << id << v::endl;
    v::report << "TimingMonitor" << "* Name: " << ((it->second).name) << v::endl;
    v::report << "TimingMonitor" << "* SystemC Time: " << TimingMonitor::phase_systime(id) \
	    << " (Start: " << tmp.st_start << " End: " << tmp.st_end << ")" << v::endl;
    v::report << "TimingMonitor" << "* Real Time: " << TimingMonitor::phase_realtime(id) << " sec " << v::endl;
    v::report << "TimingMonitor" << "* --------------------------------------------------------------" << v::endl;

    it++;
  }

  v::report << "TimingMonitor" << "******************************************************************" << v::endl;

}
<commit_msg>The timeing monitor is printing tables now<commit_after>// ********************************************************************
// Copyright 2010, Institute of Computer and Network Engineering,
//                 TU-Braunschweig
// All rights reserved
// Any reproduction, use, distribution or disclosure of this program,
// without the express, prior written consent of the authors is
// strictly prohibited.
//
// University of Technology Braunschweig
// Institute of Computer and Network Engineering
// Hans-Sommer-Str. 66
// 38118 Braunschweig, Germany
//
// ESA SPECIAL LICENSE
//
// This program may be freely used, copied, modified, and redistributed
// by the European Space Agency for the Agency's own requirements.
//
// The program is provided "as is", there is no warranty that
// the program is correct or suitable for any purpose,
// neither implicit nor explicit. The program and the information in it
// contained do not necessarily reflect the policy of the
// European Space Agency or of TU-Braunschweig.
// ********************************************************************
// Title:      timingmonitor.h
//
// ScssId:
//
// Origin:     HW-SW SystemC Co-Simulation SoC Validation Platform
//
// Purpose:    The timing monitor can be used to track
//             progress, performance and simulation time
//             of testbenches.
//
//
// Modified on $Date$
//          at $Revision$
//          by $Author$
//
// Principal:  European Space Agency
// Author:     VLSI working group @ IDA @ TUBS
// Maintainer: Thomas Schuster
// Reviewed:
// ********************************************************************

#include "timingmonitor.h"

// Initialize timing map (static - must be done outside class def)
TimingMonitor::t_timing_map TimingMonitor::timing_map;

// Create a new timing record and set starting time
void TimingMonitor::phase_start_timing(const unsigned int id, const char * name) {

  t_timing_rec tmp;

  tmp.name = (char *)name;
  tmp.st_start = sc_core::sc_time_stamp();
  tmp.rt_start = std::clock();
  tmp.st_end = sc_core::SC_ZERO_TIME;
  tmp.rt_end = std::clock();

  timing_map[id] = tmp;

}

// Enter phase finishing time
void TimingMonitor::phase_end_timing(const unsigned int id) {

  t_timing_rec tmp;
  t_timing_it it;

  it = timing_map.find(id);

  // Forbidden to set end timing before creating phase (calling phase_start_timing)
  if (it == timing_map.end()) {

    v::error << "TimingMonitor" << "No such phase: " << id << v::endl;

  }

  tmp=it->second;

  tmp.st_end = sc_core::sc_time_stamp();
  tmp.rt_end = std::clock();

  timing_map[id] = tmp;

}

// Return simulation time of phase id
sc_core::sc_time TimingMonitor::phase_systime(const unsigned int id) {

  t_timing_it it;

  it = timing_map.find(id);

  // Phase/key must exist in timing_map
  if (it == timing_map.end()) {

    v::error << "TimingMonitor" << "No such phase: " << id << v::endl;

    return(sc_core::sc_time(0,SC_NS));

  }

  return((it->second).st_end - (it->second).st_start);
}

// Return real time for processing phase id
double TimingMonitor::phase_realtime(const unsigned int id) {

  t_timing_it it;

  clock_t start_clock;
  clock_t end_clock;
  double  diff_sec;

  it = timing_map.find(id);

  // Phase/key must exist in timing_map
  if (it == timing_map.end()) {

    v::error << "TimingMonitor" << "No such phase: " << id << v::endl;

    return(0);

  }

  start_clock = (it->second).rt_start;
  end_clock   = (it->second).rt_end;

  diff_sec = (end_clock - start_clock)/(double)CLOCKS_PER_SEC;

  return(diff_sec);
}

// Return name of phase id
const char * TimingMonitor::phase_get_name(const unsigned int id) {

  t_timing_it it;

  it = timing_map.find(id);

  // Phase/key must exist in timing_map
  if (it == timing_map.end()) {

    v::error << "TimingMonitor" << "No such phase: " << id << v::endl;

    return("Unknown Phase");

  }

  return((it->second).name);

}

// Generate timing report for all phases at 'info' level.
void TimingMonitor::report_timing() {

  unsigned int id;
  t_timing_rec tmp;
  t_timing_it it;

  it = timing_map.begin();

  v::report << "TimingMonitor" << "******************************************************************" << v::endl;
  v::report << "TimingMonitor" << "* TIMING SUMMARY " << v::endl;
  v::report << "TimingMonitor" << "* -------------- " << v::endl;
  v::report << "TimingMonitor" << " Phase, Name, SystemC Time, SystemC Start, SystemC End, Real Time (sec)" << v::endl;

  // Walk through timing map
  while(it != timing_map.end()) {

    id  = it->first;
    tmp = it->second;

    v::report << "TimingMonitor" << id << ", " << ((it->second).name) << ", " << TimingMonitor::phase_systime(id) << ", " << tmp.st_start << ", " << tmp.st_end << ", " << TimingMonitor::phase_realtime(id) << v::endl;
    //v::report << "TimingMonitor" << "* Phase: " << id << v::endl;
    //v::report << "TimingMonitor" << "* Name: " << ((it->second).name) << v::endl;
    //v::report << "TimingMonitor" << "* SystemC Time: " << TimingMonitor::phase_systime(id) \
	    << " (Start: " << tmp.st_start << " End: " << tmp.st_end << ")" << v::endl;
    //v::report << "TimingMonitor" << "* Real Time: " << TimingMonitor::phase_realtime(id) << " sec " << v::endl;
    //v::report << "TimingMonitor" << "* --------------------------------------------------------------" << v::endl;

    it++;
  }

  v::report << "TimingMonitor" << "******************************************************************" << v::endl;

}
<|endoftext|>