X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6090d53c8a3eddbb6bda370badfbe8e6f90807f7..a7f62f39092512cda56bc0bb89cdabf156f05385:/include/wx/ustring.h diff --git a/include/wx/ustring.h b/include/wx/ustring.h index 1fdfa105a4..0c00b6f9df 100644 --- a/include/wx/ustring.h +++ b/include/wx/ustring.h @@ -1,84 +1,64 @@ -///////////////////////////////////////////////////////////////////////////// + // Name: wx/ustring.h // Purpose: 32-bit string (UCS-4) // Author: Robert Roebling // Copyright: (c) Robert Roebling -// RCS-ID: $Id: tab.h 37400 2006-02-09 00:28:34Z VZ $ +// RCS-ID: $Id$ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifndef _WX_USTRING_H_BASE_ -#define _WX_USTRING_H_BASE_ +#ifndef _WX_USTRING_H_ +#define _WX_USTRING_H_ #include "wx/defs.h" #include "wx/string.h" #include -WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer ) - #if SIZEOF_WCHAR_T == 2 - typedef wxWCharBuffer wxU16CharBuffer; - +typedef wxScopedWCharBuffer wxScopedU16CharBuffer; #else - -class WXDLLIMPEXP_BASE wxU16CharBuffer : public wxCharTypeBuffer -{ -public: - typedef wxCharTypeBuffer wxCharTypeBufferBase; - - wxU16CharBuffer(const wxCharTypeBufferBase& buf) - : wxCharTypeBufferBase(buf) {} - - wxU16CharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {} - wxU16CharBuffer(size_t len) : wxCharTypeBufferBase(len) {} -}; - +typedef wxCharTypeBuffer wxU16CharBuffer; +typedef wxScopedCharTypeBuffer wxScopedU16CharBuffer; #endif - - -#if SIZEOF_WCHAR_T == 2 - -class WXDLLIMPEXP_BASE wxU32CharBuffer : public wxCharTypeBuffer -{ -public: - typedef wxCharTypeBuffer wxCharTypeBufferBase; - - wxU32CharBuffer(const wxCharTypeBufferBase& buf) - : wxCharTypeBufferBase(buf) {} - - wxU32CharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {} - wxU32CharBuffer(size_t len) : wxCharTypeBufferBase(len) {} -}; - -#else - +#if SIZEOF_WCHAR_T == 4 typedef wxWCharBuffer wxU32CharBuffer; +typedef wxScopedWCharBuffer wxScopedU32CharBuffer; +#else +typedef wxCharTypeBuffer wxU32CharBuffer; +typedef wxScopedCharTypeBuffer wxScopedU32CharBuffer; +#endif +#ifdef __VISUALC__ + // "non dll-interface class 'std::basic_string' used as base + // interface for dll-interface class 'wxString'" -- this is OK in our case + // (and warning is unavoidable anyhow) + #pragma warning(push) + #pragma warning(disable:4275) #endif class WXDLLIMPEXP_BASE wxUString: public std::basic_string { -public: +public: wxUString() { } - + wxUString( const wxChar32 *str ) { assign(str); } wxUString( const wxUString &str ) { assign(str); } - wxUString( const wxU32CharBuffer &buf ) { assign(buf); } - + wxUString( const wxScopedU32CharBuffer &buf ) { assign(buf); } + wxUString( const char *str ) { assign(str); } - wxUString( const wxCharBuffer &buf ) { assign(buf); } + wxUString( const wxScopedCharBuffer &buf ) { assign(buf); } wxUString( const char *str, const wxMBConv &conv ) { assign(str,conv); } - wxUString( const wxCharBuffer &buf, const wxMBConv &conv ) { assign(buf,conv); } + wxUString( const wxScopedCharBuffer &buf, const wxMBConv &conv ) { assign(buf,conv); } wxUString( const wxChar16 *str ) { assign(str); } - wxUString( const wxU16CharBuffer &buf ) { assign(buf); } - + wxUString( const wxScopedU16CharBuffer &buf ) { assign(buf); } + wxUString( const wxCStrData *cstr ) { assign(cstr); } wxUString( const wxString &str ) { assign(str); } - + wxUString( char ch ) { assign(ch); } wxUString( wxChar16 ch ) { assign(ch); } wxUString( wxChar32 ch ) { assign(ch); } @@ -89,53 +69,53 @@ public: wxUString( size_type n, wxChar32 ch ) { assign(n,ch); } wxUString( size_type n, wxUniChar ch ) { assign(n,ch); } wxUString( size_type n, wxUniCharRef ch ) { assign(n,ch); } - + // static construction - + static wxUString FromAscii( const char *str, size_type n ) { wxUString ret; ret.assignFromAscii( str, n ); return ret; } - + static wxUString FromAscii( const char *str ) { wxUString ret; ret.assignFromAscii( str ); return ret; } - + static wxUString FromUTF8( const char *str, size_type n ) { wxUString ret; ret.assignFromUTF8( str, n ); return ret; } - + static wxUString FromUTF8( const char *str ) { wxUString ret; ret.assignFromUTF8( str ); return ret; } - + static wxUString FromUTF16( const wxChar16 *str, size_type n ) { wxUString ret; ret.assignFromUTF16( str, n ); return ret; } - + static wxUString FromUTF16( const wxChar16 *str ) { wxUString ret; ret.assignFromUTF16( str ); return ret; } - + // assign from encoding - + wxUString &assignFromAscii( const char *str ); wxUString &assignFromAscii( const char *str, size_type n ); wxUString &assignFromUTF8( const char *str ); @@ -144,14 +124,14 @@ public: wxUString &assignFromUTF16( const wxChar16* str, size_type n ); wxUString &assignFromCString( const char* str ); wxUString &assignFromCString( const char* str, const wxMBConv &conv ); - + // conversions - - wxCharBuffer utf8_str() const; - wxU16CharBuffer utf16_str() const; - + + wxScopedCharBuffer utf8_str() const; + wxScopedU16CharBuffer utf16_str() const; + #if SIZEOF_WCHAR_T == 2 - wxWCharBuffer wc_str() const + wxScopedWCharBuffer wc_str() const { return utf16_str(); } @@ -176,13 +156,13 @@ public: } #if wxUSE_UNICODE_UTF8 - wxCharBuffer wx_str() + wxScopedCharBuffer wx_str() { return utf8_str(); } #else #if SIZEOF_WCHAR_T == 2 - wxWCharBuffer wx_str() + wxScopedWCharBuffer wx_str() { return utf16_str(); } @@ -195,78 +175,104 @@ public: #endif // assign - - inline wxUString &assign( const wxChar32* str ) + + wxUString &assign( const wxChar32* str ) { std::basic_string *base = this; return (wxUString &) base->assign( str ); } - - inline wxUString &assign( const wxChar32* str, size_type n ) + + wxUString &assign( const wxChar32* str, size_type n ) { std::basic_string *base = this; return (wxUString &) base->assign( str, n ); } - - inline wxUString &assign( const wxUString &str ) + + wxUString &assign( const wxUString &str ) { std::basic_string *base = this; return (wxUString &) base->assign( str ); } - - inline wxUString &assign( const wxUString &str, size_type pos, size_type n ) + + wxUString &assign( const wxUString &str, size_type pos, size_type n ) { std::basic_string *base = this; return (wxUString &) base->assign( str, pos, n ); } - - inline wxUString &assign( wxChar32 ch ) - { - std::basic_string *base = this; - return (wxUString &) base->assign( (size_type) 1, ch ); - } - - inline wxUString &assign( size_type n, wxChar32 ch ) - { - std::basic_string *base = this; - return (wxUString &) base->assign( n, ch ); - } - - wxUString &assign( const wxU32CharBuffer &buf ) + + // FIXME-VC6: VC 6.0 stl does not support all types of assign functions + #ifdef __VISUALC6__ + wxUString &assign( wxChar32 ch ) + { + wxChar32 chh[1]; + chh[0] = ch; + std::basic_string *base = this; + return (wxUString &)base->assign(chh); + } + + wxUString &assign( size_type n, wxChar32 ch ) + { + wxU32CharBuffer buffer(n); + wxChar32 *p = buffer.data(); + size_type i; + for (i = 0; i < n; i++) + { + *p = ch; + p++; + } + + std::basic_string *base = this; + return (wxUString &)base->assign(buffer.data()); + } + #else + wxUString &assign( wxChar32 ch ) + { + std::basic_string *base = this; + return (wxUString &) base->assign( (size_type) 1, ch ); + } + + wxUString &assign( size_type n, wxChar32 ch ) + { + std::basic_string *base = this; + return (wxUString &) base->assign( n, ch ); + } + #endif // __VISUALC6__ + + wxUString &assign( const wxScopedU32CharBuffer &buf ) { return assign( buf.data() ); } - + wxUString &assign( const char *str ) { return assignFromCString( str ); } - - wxUString &assign( const wxCharBuffer &buf ) - { + + wxUString &assign( const wxScopedCharBuffer &buf ) + { return assignFromCString( buf.data() ); } - + wxUString &assign( const char *str, const wxMBConv &conv ) - { + { return assignFromCString( str, conv ); } - - wxUString &assign( const wxCharBuffer &buf, const wxMBConv &conv ) - { + + wxUString &assign( const wxScopedCharBuffer &buf, const wxMBConv &conv ) + { return assignFromCString( buf.data(), conv ); } - + wxUString &assign( const wxChar16 *str ) { return assignFromUTF16( str ); } - - wxUString &assign( const wxU16CharBuffer &buf ) + + wxUString &assign( const wxScopedU16CharBuffer &buf ) { return assignFromUTF16( buf.data() ); } - + wxUString &assign( const wxCStrData *cstr ) { #if SIZEOF_WCHAR_T == 2 @@ -275,7 +281,7 @@ public: return assign( cstr->AsWChar() ); #endif } - + wxUString &assign( const wxString &str ) { #if wxUSE_UNICODE_UTF8 @@ -284,11 +290,11 @@ public: #if SIZEOF_WCHAR_T == 2 return assignFromUTF16( str.wc_str() ); #else - return assign( wc_str() ); + return assign( str.wc_str() ); #endif #endif } - + wxUString &assign( char ch ) { char buf[2]; @@ -296,9 +302,9 @@ public: buf[1] = 0; return assignFromCString( buf ); } - + wxUString &assign( size_type n, char ch ) - { + { wxCharBuffer buffer(n); char *p = buffer.data(); size_type i; @@ -309,7 +315,7 @@ public: } return assignFromCString( buffer.data() ); } - + wxUString &assign( wxChar16 ch ) { wxChar16 buf[2]; @@ -317,7 +323,7 @@ public: buf[1] = 0; return assignFromUTF16( buf ); } - + wxUString &assign( size_type n, wxChar16 ch ) { wxU16CharBuffer buffer(n); @@ -330,60 +336,78 @@ public: } return assignFromUTF16( buffer.data() ); } - + wxUString &assign( wxUniChar ch ) { - return assign( (const wxChar32) ch.GetValue() ); + return assign( (wxChar32) ch.GetValue() ); } - + wxUString &assign( size_type n, wxUniChar ch ) { - return assign( n, (const wxChar32) ch.GetValue() ); + return assign( n, (wxChar32) ch.GetValue() ); } - + wxUString &assign( wxUniCharRef ch ) { - return assign( (const wxChar32) ch.GetValue() ); + return assign( (wxChar32) ch.GetValue() ); } - + wxUString &assign( size_type n, wxUniCharRef ch ) { - return assign( n, (const wxChar32) ch.GetValue() ); + return assign( n, (wxChar32) ch.GetValue() ); } - + // append [STL overload] - - inline wxUString &append( const wxUString &s ) + + wxUString &append( const wxUString &s ) { std::basic_string *base = this; return (wxUString &) base->append( s ); } - - inline wxUString &append( const wxUString &s, size_type pos, size_type n ) + + wxUString &append( const wxUString &s, size_type pos, size_type n ) { std::basic_string *base = this; return (wxUString &) base->append( s, pos, n ); } - - inline wxUString &append( const wxChar32* s ) + + wxUString &append( const wxChar32* s ) { std::basic_string *base = this; return (wxUString &) base->append( s ); } - inline wxUString &append( const wxChar32* s, size_type n ) + wxUString &append( const wxChar32* s, size_type n ) { std::basic_string *base = this; return (wxUString &) base->append( s, n ); } - inline wxUString &append( size_type n, wxChar32 c ) - { - std::basic_string *base = this; - return (wxUString &) base->append( n, c ); - } + // FIXME-VC6: VC 6.0 stl does not support all types of append functions + #ifdef __VISUALC6__ + wxUString &append( size_type n, wxChar32 c ) + { + wxU32CharBuffer buffer(n); + wxChar32 *p = buffer.data(); + size_type i; + for (i = 0; i < n; i++) + { + *p = c; + p++; + } + + std::basic_string *base = this; + return (wxUString &) base->append(buffer.data()); + } + #else + wxUString &append( size_type n, wxChar32 c ) + { + std::basic_string *base = this; + return (wxUString &) base->append( n, c ); + } + #endif // __VISUALC6__ - inline wxUString &append( wxChar32 c ) + wxUString &append( wxChar32 c ) { std::basic_string *base = this; return (wxUString &) base->append( 1, c ); @@ -391,12 +415,12 @@ public: // append [wx overload] - wxUString &append( const wxU16CharBuffer &buf ) + wxUString &append( const wxScopedU16CharBuffer &buf ) { return append( buf.data() ); } - wxUString &append( const wxU32CharBuffer &buf ) + wxUString &append( const wxScopedU32CharBuffer &buf ) { return append( buf.data() ); } @@ -406,7 +430,7 @@ public: return append( wxUString( str ) ); } - wxUString &append( const wxCharBuffer &buf ) + wxUString &append( const wxScopedCharBuffer &buf ) { return append( wxUString( buf ) ); } @@ -415,17 +439,17 @@ public: { return append( wxUString( str ) ); } - + wxUString &append( const wxString &str ) { return append( wxUString( str ) ); } - + wxUString &append( const wxCStrData *cstr ) { return append( wxUString( cstr ) ); } - + wxUString &append( char ch ) { char buf[2]; @@ -433,7 +457,7 @@ public: buf[1] = 0; return append( buf ); } - + wxUString &append( wxChar16 ch ) { wxChar16 buf[2]; @@ -441,7 +465,7 @@ public: buf[1] = 0; return append( buf ); } - + wxUString &append( wxUniChar ch ) { return append( (size_type) 1, (wxChar32) ch.GetValue() ); @@ -452,34 +476,34 @@ public: return append( (size_type) 1, (wxChar32) ch.GetValue() ); } - + // insert [STL overloads] - - inline wxUString &insert( size_type pos, const wxUString &s ) + + wxUString &insert( size_type pos, const wxUString &s ) { std::basic_string *base = this; return (wxUString &) base->insert( pos, s ); } - inline wxUString &insert( size_type pos, const wxUString &s, size_type pos1, size_type n ) + wxUString &insert( size_type pos, const wxUString &s, size_type pos1, size_type n ) { std::basic_string *base = this; return (wxUString &) base->insert( pos, s, pos1, n ); } - inline wxUString &insert( size_type pos, const wxChar32 *s ) + wxUString &insert( size_type pos, const wxChar32 *s ) { std::basic_string *base = this; return (wxUString &) base->insert( pos, s ); } - inline wxUString &insert( size_type pos, const wxChar32 *s, size_type n ) + wxUString &insert( size_type pos, const wxChar32 *s, size_type n ) { std::basic_string *base = this; return (wxUString &) base->insert( pos, s, n ); } - inline wxUString &insert( size_type pos, size_type n, wxChar32 c ) + wxUString &insert( size_type pos, size_type n, wxChar32 c ) { std::basic_string *base = this; return (wxUString &) base->insert( pos, n, c ); @@ -498,17 +522,17 @@ public: return insert( n, wxUString( s ) ); } - wxUString &insert( size_type n, const wxCharBuffer &buf ) + wxUString &insert( size_type n, const wxScopedCharBuffer &buf ) { return insert( n, wxUString( buf ) ); } - wxUString &insert( size_type n, const wxU16CharBuffer &buf ) + wxUString &insert( size_type n, const wxScopedU16CharBuffer &buf ) { return insert( n, wxUString( buf ) ); } - wxUString &insert( size_type n, const wxU32CharBuffer &buf ) + wxUString &insert( size_type n, const wxScopedU32CharBuffer &buf ) { return insert( n, buf.data() ); } @@ -517,12 +541,12 @@ public: { return insert( n, wxUString( s ) ); } - + wxUString &insert( size_type n, const wxCStrData *cstr ) { return insert( n, wxUString( cstr ) ); } - + wxUString &insert( size_type n, char ch ) { char buf[2]; @@ -530,7 +554,7 @@ public: buf[1] = 0; return insert( n, buf ); } - + wxUString &insert( size_type n, wchar_t ch ) { wchar_t buf[2]; @@ -538,15 +562,15 @@ public: buf[1] = 0; return insert( n, buf ); } - + // insert iterator - + iterator insert( iterator it, wxChar32 ch ) { std::basic_string *base = this; return base->insert( it, ch ); } - + void insert(iterator it, const_iterator first, const_iterator last) { std::basic_string *base = this; @@ -555,67 +579,71 @@ public: // operator = - inline wxUString& operator=(const wxUString& s) + wxUString& operator=(const wxUString& s) { return assign( s ); } - inline wxUString& operator=(const wxString& s) + wxUString& operator=(const wxString& s) { return assign( s ); } - inline wxUString& operator=(const wxCStrData* s) + wxUString& operator=(const wxCStrData* s) { return assign( s ); } - inline wxUString& operator=(const char *s) + wxUString& operator=(const char *s) { return assign( s ); } - inline wxUString& operator=(const wxChar16 *s) + wxUString& operator=(const wxChar16 *s) { return assign( s ); } - inline wxUString& operator=(const wxChar32 *s) + wxUString& operator=(const wxChar32 *s) { return assign( s ); } - inline wxUString& operator=(const wxCharBuffer &s) + wxUString& operator=(const wxScopedCharBuffer &s) { return assign( s ); } - inline wxUString& operator=(const wxU16CharBuffer &s) + wxUString& operator=(const wxScopedU16CharBuffer &s) { return assign( s ); } - inline wxUString& operator=(const wxU32CharBuffer &s) + wxUString& operator=(const wxScopedU32CharBuffer &s) { return assign( s ); } - inline wxUString& operator=(const char ch) + wxUString& operator=(const char ch) { return assign( ch ); } - inline wxUString& operator=(const wxChar16 ch) + wxUString& operator=(const wxChar16 ch) { return assign( ch ); } - inline wxUString& operator=(const wxChar32 ch) + wxUString& operator=(const wxChar32 ch) { return assign( ch ); } - inline wxUString& operator=(const wxUniChar ch) + wxUString& operator=(const wxUniChar ch) { return assign( ch ); } - inline wxUString& operator=(const wxUniCharRef ch) + wxUString& operator=(const wxUniCharRef ch) { return assign( ch ); } - + // operator += - inline wxUString& operator+=(const wxUString& s) + wxUString& operator+=(const wxUString& s) { return append( s ); } - inline wxUString& operator+=(const wxString& s) + wxUString& operator+=(const wxString& s) { return append( s ); } - inline wxUString& operator+=(const wxCStrData* s) + wxUString& operator+=(const wxCStrData* s) { return append( s ); } - inline wxUString& operator+=(const char *s) + wxUString& operator+=(const char *s) { return append( s ); } - inline wxUString& operator+=(const wxChar16 *s) + wxUString& operator+=(const wxChar16 *s) { return append( s ); } - inline wxUString& operator+=(const wxChar32 *s) + wxUString& operator+=(const wxChar32 *s) { return append( s ); } - inline wxUString& operator+=(const wxCharBuffer &s) + wxUString& operator+=(const wxScopedCharBuffer &s) { return append( s ); } - inline wxUString& operator+=(const wxU16CharBuffer &s) + wxUString& operator+=(const wxScopedU16CharBuffer &s) { return append( s ); } - inline wxUString& operator+=(const wxU32CharBuffer &s) + wxUString& operator+=(const wxScopedU32CharBuffer &s) { return append( s ); } - inline wxUString& operator+=(const char ch) + wxUString& operator+=(const char ch) { return append( ch ); } - inline wxUString& operator+=(const wxChar16 ch) + wxUString& operator+=(const wxChar16 ch) { return append( ch ); } - inline wxUString& operator+=(const wxChar32 ch) + wxUString& operator+=(const wxChar32 ch) { return append( ch ); } - inline wxUString& operator+=(const wxUniChar ch) + wxUString& operator+=(const wxUniChar ch) { return append( ch ); } - inline wxUString& operator+=(const wxUniCharRef ch) + wxUString& operator+=(const wxUniCharRef ch) { return append( ch ); } - + }; +#ifdef __VISUALC__ + #pragma warning(pop) +#endif + inline wxUString operator+(const wxUString &s1, const wxUString &s2) { wxUString ret( s1 ); ret.append( s2 ); return ret; } inline wxUString operator+(const wxUString &s1, const char *s2) @@ -628,11 +656,11 @@ inline wxUString operator+(const wxUString &s1, const wxChar16* s2) { return s1 + wxUString(s2); } inline wxUString operator+(const wxUString &s1, const wxChar32 *s2) { return s1 + wxUString(s2); } -inline wxUString operator+(const wxUString &s1, const wxCharBuffer &s2) +inline wxUString operator+(const wxUString &s1, const wxScopedCharBuffer &s2) { return s1 + wxUString(s2); } -inline wxUString operator+(const wxUString &s1, const wxU16CharBuffer &s2) +inline wxUString operator+(const wxUString &s1, const wxScopedU16CharBuffer &s2) { return s1 + wxUString(s2); } -inline wxUString operator+(const wxUString &s1, const wxU32CharBuffer &s2) +inline wxUString operator+(const wxUString &s1, const wxScopedU32CharBuffer &s2) { return s1 + wxUString(s2); } inline wxUString operator+(const wxUString &s1, char s2) { return s1 + wxUString(s2); } @@ -655,11 +683,11 @@ inline wxUString operator+(const wxChar16* s1, const wxUString &s2) { return wxUString(s1) + s2; } inline wxUString operator+(const wxChar32 *s1, const wxUString &s2) { return wxUString(s1) + s2; } -inline wxUString operator+(const wxCharBuffer &s1, const wxUString &s2) +inline wxUString operator+(const wxScopedCharBuffer &s1, const wxUString &s2) { return wxUString(s1) + s2; } -inline wxUString operator+(const wxU16CharBuffer &s1, const wxUString &s2) +inline wxUString operator+(const wxScopedU16CharBuffer &s1, const wxUString &s2) { return wxUString(s1) + s2; } -inline wxUString operator+(const wxU32CharBuffer &s1, const wxUString &s2) +inline wxUString operator+(const wxScopedU32CharBuffer &s1, const wxUString &s2) { return wxUString(s1) + s2; } inline wxUString operator+(char s1, const wxUString &s2) { return wxUString(s1) + s2; } @@ -678,7 +706,7 @@ inline bool operator==(const wxUString& s1, const wxUString& s2) inline bool operator!=(const wxUString& s1, const wxUString& s2) { return s1.compare( s2 ) != 0; } inline bool operator< (const wxUString& s1, const wxUString& s2) - { wxPrintf( "test\n"); return s1.compare( s2 ) < 0; } + { return s1.compare( s2 ) < 0; } inline bool operator> (const wxUString& s1, const wxUString& s2) { return s1.compare( s2 ) > 0; } inline bool operator<=(const wxUString& s1, const wxUString& s2) @@ -717,10 +745,9 @@ wxUSTRING_COMP_OPERATORS( const wxString & ) wxUSTRING_COMP_OPERATORS( const char * ) wxUSTRING_COMP_OPERATORS( const wxChar16 * ) wxUSTRING_COMP_OPERATORS( const wxChar32 * ) -wxUSTRING_COMP_OPERATORS( const wxCharBuffer & ) -wxUSTRING_COMP_OPERATORS( const wxU16CharBuffer & ) -wxUSTRING_COMP_OPERATORS( const wxU32CharBuffer & ) +wxUSTRING_COMP_OPERATORS( const wxScopedCharBuffer & ) +wxUSTRING_COMP_OPERATORS( const wxScopedU16CharBuffer & ) +wxUSTRING_COMP_OPERATORS( const wxScopedU32CharBuffer & ) wxUSTRING_COMP_OPERATORS( const wxCStrData * ) -#endif - // _WX_USTRING_H_BASE_ +#endif // _WX_USTRING_H_