return a wxAnyStrPtr covnertible to either narrow or wide char pointer from wxDateTime::ParseXXX() methods to improve compatibility with wx 2.8 and also simplify the code (closes #9560)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59822 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
136
include/wx/anystr.h
Normal file
136
include/wx/anystr.h
Normal file
@@ -0,0 +1,136 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/anystr.h
|
||||
// Purpose: wxAnyStrPtr class declaration
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2009-03-23
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_ANYSTR_H_
|
||||
#define _WX_ANYSTR_H_
|
||||
|
||||
#include "wx/string.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxAnyStrPtr
|
||||
//
|
||||
// Notice that this is an internal and intentionally not documented class. It
|
||||
// is only used by wxWidgets itself to ensure compatibility with previous
|
||||
// versions and shouldn't be used by user code. When you see a function
|
||||
// returning it you should just know that you can treat it as a string pointer.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This is a helper class convertible to either narrow or wide string pointer.
|
||||
// It is similar to wxCStrData but, unlike it, can be NULL which is required to
|
||||
// represent the return value of wxDateTime::ParseXXX() methods for example.
|
||||
//
|
||||
// NB: this class is fully inline and so doesn't need to be DLL-exported
|
||||
class wxAnyStrPtr
|
||||
{
|
||||
public:
|
||||
// ctors: this class must be created from the associated string or using
|
||||
// its default ctor for an invalid NULL-like object; notice that it is
|
||||
// immutable after creation.
|
||||
|
||||
// ctor for invalid pointer
|
||||
wxAnyStrPtr()
|
||||
: m_str(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// ctor for valid pointer into the given string (whose lifetime must be
|
||||
// greater than ours and which should remain constant while we're used)
|
||||
wxAnyStrPtr(const wxString& str, const wxString::const_iterator& iter)
|
||||
: m_str(&str),
|
||||
m_iter(iter)
|
||||
{
|
||||
}
|
||||
|
||||
// default copy ctor is ok and so is default dtor, in particular we do not
|
||||
// free the string
|
||||
|
||||
|
||||
// various operators meant to make this class look like a superposition of
|
||||
// char* and wchar_t*
|
||||
|
||||
// this one is needed to allow boolean expressions involving these objects,
|
||||
// e.g. "if ( FuncReturningAnyStrPtr() && ... )" (unfortunately using
|
||||
// unspecified_bool_type here wouldn't help with ambiguity between all the
|
||||
// different conversions to pointers)
|
||||
operator bool() const { return m_str != NULL; }
|
||||
|
||||
|
||||
// and these are the conversions operator which allow to assign the result
|
||||
// of FuncReturningAnyStrPtr() to either char* or wxChar* (i.e. wchar_t*)
|
||||
operator const char *() const
|
||||
{
|
||||
if ( !m_str )
|
||||
return NULL;
|
||||
|
||||
// check if the string is convertible to char at all
|
||||
//
|
||||
// notice that this pointer points into wxString internal buffer
|
||||
// containing its char* representation and so it can be kept for as
|
||||
// long as wxString is not modified -- which is long enough for our
|
||||
// needs
|
||||
const char *p = m_str->c_str().AsChar();
|
||||
if ( *p )
|
||||
{
|
||||
// find the offset of the character corresponding to this iterator
|
||||
// position in bytes: we don't have any direct way to do it so we
|
||||
// need to redo the conversion again for the part of the string
|
||||
// before the iterator to find its length in bytes in current
|
||||
// locale
|
||||
//
|
||||
// NB: conversion won't fail as it succeeded for the entire string
|
||||
p += strlen(wxString(m_str->begin(), m_iter).mb_str());
|
||||
}
|
||||
//else: conversion failed, return "" as we can't do anything else
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
operator const wchar_t *() const
|
||||
{
|
||||
if ( !m_str )
|
||||
return NULL;
|
||||
|
||||
// no complications with wide strings (as long as we discount
|
||||
// surrogates as we do for now)
|
||||
//
|
||||
// just remember that this works as long as wxString keeps an internal
|
||||
// buffer with its wide wide char representation, just as with AsChar()
|
||||
// above
|
||||
return m_str->c_str().AsWChar() + (m_iter - m_str->begin());
|
||||
}
|
||||
|
||||
// Because the objects of this class are only used as return type for
|
||||
// functions which can return NULL we can skip providing dereferencing
|
||||
// operators: the code using this class must test it for NULL first and if
|
||||
// it does anything else with it it has to assign it to either char* or
|
||||
// wchar_t* itself, before dereferencing.
|
||||
//
|
||||
// IOW this
|
||||
//
|
||||
// if ( *FuncReturningAnyStrPtr() )
|
||||
//
|
||||
// is invalid because it could crash. And this
|
||||
//
|
||||
// const char *p = FuncReturningAnyStrPtr();
|
||||
// if ( p && *p )
|
||||
//
|
||||
// already works fine.
|
||||
|
||||
private:
|
||||
// the original string and the offset in it we correspond to, if the string
|
||||
// is NULL this object is NULL pointer-like
|
||||
const wxString * const m_str;
|
||||
const wxString::const_iterator m_iter;
|
||||
|
||||
wxDECLARE_NO_ASSIGN_CLASS(wxAnyStrPtr);
|
||||
};
|
||||
|
||||
#endif // _WX_ANYSTR_H_
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include <limits.h> // for INT_MIN
|
||||
|
||||
#include "wx/longlong.h"
|
||||
#include "wx/anystr.h"
|
||||
|
||||
class WXDLLIMPEXP_FWD_BASE wxDateTime;
|
||||
class WXDLLIMPEXP_FWD_BASE wxTimeSpan;
|
||||
@@ -1098,103 +1099,36 @@ public:
|
||||
inline wxTimeSpan Subtract(const wxDateTime& dt) const;
|
||||
inline wxTimeSpan operator-(const wxDateTime& dt2) const;
|
||||
|
||||
// conversion to/from text: all conversions from text return the pointer to
|
||||
// the next character following the date specification (i.e. the one where
|
||||
// the scan had to stop) or NULL on failure; for the versions taking
|
||||
// wxString or wxCStrData, we don't know if the user code needs char* or
|
||||
// wchar_t* pointer and so we return char* one for compatibility with the
|
||||
// existing ANSI code and also return iterator in another output parameter
|
||||
// (it will be equal to end if the entire string was parsed)
|
||||
// conversion to/from text: all conversions from text return an object
|
||||
// representing the next character following the date specification (i.e.
|
||||
// the one where the scan had to stop) or a special NULL-like object
|
||||
// on failure -- this object is necessary to preserve compatibility with
|
||||
// the existing code assigning the return value of these functions to
|
||||
// either char* or wxChar* (new code should treat the return value as bool
|
||||
// and use end parameter to retrieve the end of the scan)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// parse a string in RFC 822 format (found e.g. in mail headers and
|
||||
// having the form "Wed, 10 Feb 1999 19:07:07 +0100")
|
||||
const char *ParseRfc822Date(const wxString& date,
|
||||
wxAnyStrPtr ParseRfc822Date(const wxString& date,
|
||||
wxString::const_iterator *end = NULL);
|
||||
const char *ParseRfc822Date(const wxCStrData& date,
|
||||
wxString::const_iterator *end = NULL)
|
||||
{
|
||||
return ParseRfc822Date(date.AsString(), end);
|
||||
}
|
||||
|
||||
const wchar_t *ParseRfc822Date(const wchar_t* date)
|
||||
{
|
||||
return ReturnEndAsWidePtr(&wxDateTime::ParseRfc822Date, date);
|
||||
}
|
||||
|
||||
const char *ParseRfc822Date(const char* date)
|
||||
{
|
||||
return ParseRfc822Date(wxString(date));
|
||||
}
|
||||
|
||||
// parse a date/time in the given format (see strptime(3)), fill in
|
||||
// the missing (in the string) fields with the values of dateDef (by
|
||||
// default, they will not change if they had valid values or will
|
||||
// default to Today() otherwise)
|
||||
|
||||
// notice that we unfortunately need all those overloads because we use
|
||||
// the type of the date string to select the return value of the
|
||||
// function: it's wchar_t if a wide string is passed for compatibility
|
||||
// with the code doing "const wxChar *p = dt.ParseFormat(_T("..."))",
|
||||
// but char* in all other cases for compatibility with ANSI build which
|
||||
// allowed code like "const char *p = dt.ParseFormat("...")"
|
||||
//
|
||||
// so we need wchar_t overload and now passing s.c_str() as first
|
||||
// argument is ambiguous because it's convertible to both wxString and
|
||||
// wchar_t* and now it's passing char* which becomes ambiguous as it is
|
||||
// convertible to both wxString and wxCStrData hence we need char*
|
||||
// overload too
|
||||
//
|
||||
// and to make our life more miserable we also pay for having the
|
||||
// optional dateDef parameter: as it's almost never used, we want to
|
||||
// allow people to omit it when specifying the end iterator output
|
||||
// parameter but we still have to allow specifying dateDef too, so we
|
||||
// need another overload for this
|
||||
//
|
||||
// FIXME: all this mess could be avoided by using some class similar to
|
||||
// wxFormatString, i.e. remembering string [pointer] of any type
|
||||
// and convertible to either char* or wchar_t* as wxCStrData and
|
||||
// having only 1 (or 2, because of the last paragraph above)
|
||||
// overload taking it, see #9560
|
||||
const char *ParseFormat(const wxString& date,
|
||||
wxAnyStrPtr ParseFormat(const wxString& date,
|
||||
const wxString& format = wxDefaultDateTimeFormat,
|
||||
const wxDateTime& dateDef = wxDefaultDateTime,
|
||||
wxString::const_iterator *end = NULL);
|
||||
|
||||
const char *ParseFormat(const wxString& date,
|
||||
wxAnyStrPtr ParseFormat(const wxString& date,
|
||||
const wxString& format,
|
||||
wxString::const_iterator *end)
|
||||
{
|
||||
return ParseFormat(date, format, wxDefaultDateTime, end);
|
||||
}
|
||||
|
||||
const char *ParseFormat(const wxCStrData& date,
|
||||
const wxString& format = wxDefaultDateTimeFormat,
|
||||
const wxDateTime& dateDef = wxDefaultDateTime,
|
||||
wxString::const_iterator *end = NULL)
|
||||
{
|
||||
return ParseFormat(date.AsString(), format, dateDef, end);
|
||||
}
|
||||
|
||||
const wchar_t *ParseFormat(const wchar_t *date,
|
||||
const wxString& format = wxDefaultDateTimeFormat,
|
||||
const wxDateTime& dateDef = wxDefaultDateTime)
|
||||
{
|
||||
const wxString datestr(date);
|
||||
wxString::const_iterator end;
|
||||
if ( !ParseFormat(datestr, format, dateDef, &end) )
|
||||
return NULL;
|
||||
|
||||
return date + (end - datestr.begin());
|
||||
}
|
||||
|
||||
const char *ParseFormat(const char *date,
|
||||
const wxString& format = "%c",
|
||||
const wxDateTime& dateDef = wxDefaultDateTime)
|
||||
{
|
||||
return ParseFormat(wxString(date), format, dateDef);
|
||||
}
|
||||
|
||||
|
||||
// parse a string containing date, time or both in ISO 8601 format
|
||||
//
|
||||
@@ -1221,65 +1155,18 @@ public:
|
||||
|
||||
// parse a string containing the date/time in "free" format, this
|
||||
// function will try to make an educated guess at the string contents
|
||||
const char *ParseDateTime(const wxString& datetime,
|
||||
wxAnyStrPtr ParseDateTime(const wxString& datetime,
|
||||
wxString::const_iterator *end = NULL);
|
||||
|
||||
const char *ParseDateTime(const wxCStrData& datetime,
|
||||
wxString::const_iterator *end = NULL)
|
||||
{
|
||||
return ParseDateTime(datetime.AsString(), end);
|
||||
}
|
||||
|
||||
const wchar_t *ParseDateTime(const wchar_t *datetime)
|
||||
{
|
||||
return ReturnEndAsWidePtr(&wxDateTime::ParseDateTime, datetime);
|
||||
}
|
||||
|
||||
const char *ParseDateTime(const char *datetime)
|
||||
{
|
||||
return ParseDateTime(wxString(datetime));
|
||||
}
|
||||
|
||||
// parse a string containing the date only in "free" format (less
|
||||
// flexible than ParseDateTime)
|
||||
const char *ParseDate(const wxString& date,
|
||||
wxAnyStrPtr ParseDate(const wxString& date,
|
||||
wxString::const_iterator *end = NULL);
|
||||
|
||||
const char *ParseDate(const wxCStrData& date,
|
||||
wxString::const_iterator *end = NULL)
|
||||
{
|
||||
return ParseDate(date.AsString(), end);
|
||||
}
|
||||
|
||||
const wchar_t *ParseDate(const wchar_t *date)
|
||||
{
|
||||
return ReturnEndAsWidePtr(&wxDateTime::ParseDate, date);
|
||||
}
|
||||
|
||||
const char *ParseDate(const char *date)
|
||||
{
|
||||
return ParseDate(wxString(date));
|
||||
}
|
||||
|
||||
// parse a string containing the time only in "free" format
|
||||
const char *ParseTime(const wxString& time,
|
||||
wxAnyStrPtr ParseTime(const wxString& time,
|
||||
wxString::const_iterator *end = NULL);
|
||||
|
||||
const char *ParseTime(const wxCStrData& time,
|
||||
wxString::const_iterator *end = NULL)
|
||||
{
|
||||
return ParseTime(time.AsString(), end);
|
||||
}
|
||||
|
||||
const wchar_t *ParseTime(const wchar_t *time)
|
||||
{
|
||||
return ReturnEndAsWidePtr(&wxDateTime::ParseTime, time);
|
||||
}
|
||||
|
||||
const char *ParseTime(const char *time)
|
||||
{
|
||||
return ParseTime(wxString(time));
|
||||
}
|
||||
|
||||
// this function accepts strftime()-like format string (default
|
||||
// argument corresponds to the preferred date and time representation
|
||||
@@ -1326,23 +1213,6 @@ public:
|
||||
static struct tm *GetTmNow(struct tm *tmstruct);
|
||||
|
||||
private:
|
||||
// helper function for defining backward-compatible wrappers for code
|
||||
// using wchar_t* pointer instead of wxString iterators
|
||||
typedef
|
||||
const char *(wxDateTime::*StringMethod)(const wxString& s,
|
||||
wxString::const_iterator *end);
|
||||
|
||||
const wchar_t *ReturnEndAsWidePtr(StringMethod func, const wchar_t *p)
|
||||
{
|
||||
const wxString s(p);
|
||||
wxString::const_iterator end;
|
||||
if ( !(this->*func)(s, &end) )
|
||||
return NULL;
|
||||
|
||||
return p + (end - s.begin());
|
||||
}
|
||||
|
||||
|
||||
// the current country - as it's the same for all program objects (unless
|
||||
// it runs on a _really_ big cluster system :-), this is a static member:
|
||||
// see SetCountry() and GetCountry()
|
||||
|
Reference in New Issue
Block a user