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:
Vadim Zeitlin
2009-03-24 23:21:29 +00:00
parent 3a6a00822d
commit 254696bb8f
13 changed files with 442 additions and 466 deletions

View File

@@ -309,6 +309,7 @@ WXSCINTILLA_OBJECTS = \
PLUGINS_INST_DIR = $(libdir)/wx/$(PLUGIN_VERSION0) PLUGINS_INST_DIR = $(libdir)/wx/$(PLUGIN_VERSION0)
ALL_BASE_HEADERS = \ ALL_BASE_HEADERS = \
wx/afterstd.h \ wx/afterstd.h \
wx/anystr.h \
wx/app.h \ wx/app.h \
wx/apptrait.h \ wx/apptrait.h \
wx/archive.h \ wx/archive.h \
@@ -467,6 +468,7 @@ ALL_HEADERS = \
$(ALL_GUI_HEADERS) $(ALL_GUI_HEADERS)
ALL_PORTS_BASE_HEADERS = \ ALL_PORTS_BASE_HEADERS = \
wx/afterstd.h \ wx/afterstd.h \
wx/anystr.h \
wx/app.h \ wx/app.h \
wx/apptrait.h \ wx/apptrait.h \
wx/archive.h \ wx/archive.h \

View File

@@ -390,6 +390,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
</set> </set>
<set var="BASE_CMN_HDR" hints="files"> <set var="BASE_CMN_HDR" hints="files">
wx/afterstd.h wx/afterstd.h
wx/anystr.h
wx/app.h wx/app.h
wx/apptrait.h wx/apptrait.h
wx/archive.h wx/archive.h

View File

@@ -1035,6 +1035,10 @@ SOURCE=..\..\include\wx\afterstd.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\include\wx\anystr.h
# End Source File
# Begin Source File
SOURCE=..\..\include\wx\app.h SOURCE=..\..\include\wx\app.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -1194,6 +1194,9 @@
<File <File
RelativePath="..\..\include\wx\afterstd.h"> RelativePath="..\..\include\wx\afterstd.h">
</File> </File>
<File
RelativePath="..\..\include\wx\anystr.h">
</File>
<File <File
RelativePath="..\..\include\wx\app.h"> RelativePath="..\..\include\wx\app.h">
</File> </File>

View File

@@ -1615,6 +1615,10 @@
RelativePath="..\..\include\wx\afterstd.h" RelativePath="..\..\include\wx\afterstd.h"
> >
</File> </File>
<File
RelativePath="..\..\include\wx\anystr.h"
>
</File>
<File <File
RelativePath="..\..\include\wx\app.h" RelativePath="..\..\include\wx\app.h"
> >

View File

@@ -1611,6 +1611,10 @@
RelativePath="..\..\include\wx\afterstd.h" RelativePath="..\..\include\wx\afterstd.h"
> >
</File> </File>
<File
RelativePath="..\..\include\wx\anystr.h"
>
</File>
<File <File
RelativePath="..\..\include\wx\app.h" RelativePath="..\..\include\wx\app.h"
> >

136
include/wx/anystr.h Normal file
View 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_

View File

@@ -26,6 +26,7 @@
#include <limits.h> // for INT_MIN #include <limits.h> // for INT_MIN
#include "wx/longlong.h" #include "wx/longlong.h"
#include "wx/anystr.h"
class WXDLLIMPEXP_FWD_BASE wxDateTime; class WXDLLIMPEXP_FWD_BASE wxDateTime;
class WXDLLIMPEXP_FWD_BASE wxTimeSpan; class WXDLLIMPEXP_FWD_BASE wxTimeSpan;
@@ -1098,103 +1099,36 @@ public:
inline wxTimeSpan Subtract(const wxDateTime& dt) const; inline wxTimeSpan Subtract(const wxDateTime& dt) const;
inline wxTimeSpan operator-(const wxDateTime& dt2) const; inline wxTimeSpan operator-(const wxDateTime& dt2) const;
// conversion to/from text: all conversions from text return the pointer to // conversion to/from text: all conversions from text return an object
// the next character following the date specification (i.e. the one where // representing the next character following the date specification (i.e.
// the scan had to stop) or NULL on failure; for the versions taking // the one where the scan had to stop) or a special NULL-like object
// wxString or wxCStrData, we don't know if the user code needs char* or // on failure -- this object is necessary to preserve compatibility with
// wchar_t* pointer and so we return char* one for compatibility with the // the existing code assigning the return value of these functions to
// existing ANSI code and also return iterator in another output parameter // either char* or wxChar* (new code should treat the return value as bool
// (it will be equal to end if the entire string was parsed) // 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 // 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") // 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); 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 // 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 // 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, they will not change if they had valid values or will
// default to Today() otherwise) // default to Today() otherwise)
wxAnyStrPtr ParseFormat(const wxString& date,
// 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,
const wxString& format = wxDefaultDateTimeFormat, const wxString& format = wxDefaultDateTimeFormat,
const wxDateTime& dateDef = wxDefaultDateTime, const wxDateTime& dateDef = wxDefaultDateTime,
wxString::const_iterator *end = NULL); wxString::const_iterator *end = NULL);
const char *ParseFormat(const wxString& date, wxAnyStrPtr ParseFormat(const wxString& date,
const wxString& format, const wxString& format,
wxString::const_iterator *end) wxString::const_iterator *end)
{ {
return ParseFormat(date, format, wxDefaultDateTime, 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 // 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 // parse a string containing the date/time in "free" format, this
// function will try to make an educated guess at the string contents // 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); 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 // parse a string containing the date only in "free" format (less
// flexible than ParseDateTime) // flexible than ParseDateTime)
const char *ParseDate(const wxString& date, wxAnyStrPtr ParseDate(const wxString& date,
wxString::const_iterator *end = NULL); 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 // 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); 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 // this function accepts strftime()-like format string (default
// argument corresponds to the preferred date and time representation // argument corresponds to the preferred date and time representation
@@ -1326,23 +1213,6 @@ public:
static struct tm *GetTmNow(struct tm *tmstruct); static struct tm *GetTmNow(struct tm *tmstruct);
private: 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 // 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: // it runs on a _really_ big cluster system :-), this is a static member:
// see SetCountry() and GetCountry() // see SetCountry() and GetCountry()

View File

@@ -802,50 +802,34 @@ public:
/** /**
This function is like ParseDateTime(), but it only allows the date to This function is like ParseDateTime(), but it only allows the date to
be specified. It is thus less flexible then ParseDateTime(), but also be specified.
has less chances to misinterpret the user input.
@return @NULL if the conversion failed, otherwise return the pointer It is thus less flexible then ParseDateTime(), but also has less
to the character which stopped the scan. chances to misinterpret the user input.
See ParseFormat() for the description of function parameters and return
value.
@see Format() @see Format()
*/ */
const char* ParseDate(const wxString& date, const char* ParseDate(const wxString& date,
wxString::const_iterator* end = NULL); wxString::const_iterator* end = NULL);
/**
@overload
*/
const char* ParseDate(const char* date);
/**
@overload
*/
const wchar_t* ParseDate(const wchar_t* date);
/** /**
Parses the string @a datetime containing the date and time in free Parses the string @a datetime containing the date and time in free
format. This function tries as hard as it can to interpret the given format.
string as date and time. Unlike ParseRfc822Date(), it will accept
anything that may be accepted and will only reject strings which can
not be parsed in any way at all.
@return @NULL if the conversion failed, otherwise return the pointer This function tries as hard as it can to interpret the given string as
to the character which stopped the scan. date and time. Unlike ParseRfc822Date(), it will accept anything that
may be accepted and will only reject strings which can not be parsed in
any way at all.
See ParseFormat() for the description of function parameters and return
value.
*/ */
const char* ParseDateTime(const wxString& datetime, const char* ParseDateTime(const wxString& datetime,
wxString::const_iterator* end = NULL); wxString::const_iterator* end = NULL);
/**
@overload
*/
const char* ParseDateTime(const char* datetime);
/**
@overload
*/
const wchar_t* ParseDateTime(const wchar_t* datetime);
/** /**
This function parses the string @a date according to the given This function parses the string @a date according to the given
@e format. The system @c strptime(3) function is used whenever @e format. The system @c strptime(3) function is used whenever
@@ -865,8 +849,38 @@ public:
@a dateDef. If it is not specified, Today() is used as the default @a dateDef. If it is not specified, Today() is used as the default
date. date.
@return @NULL if the conversion failed, otherwise return the pointer Notice that the return value of this method is not actually a pointer
to the character which stopped the scan. but rather an object of a special proxy class which is convertible to
either @c char* or @c wchar_t* pointer. This is needed for
compatibility with the existing code but the new code should use @a end
parameter instead and just test whether the return value is @NULL or
not, e.g.:
@code
wxDateTime dt;
wxString str = "...";
wxString::const_iterator end;
if ( !dt.ParseFormat(str, "%Y-%m-%d", &end) )
... parsing failed ...
else if ( end == str.end() )
... entire string parsed ...
else
... wxString(end, str.end()) left over ...
@endcode
@param date
The string to be parsed.
@param format
strptime()-like format string.
@param dateDef
Used to fill in the date components not specified in the @a date
string.
@param end
If non-@NULL, will be filled with the iterator pointing to the
location where the parsing stopped. If the entire string was
consumed, it is set to @c date.end().
@return
Pointer-like object indicating the location where the scan stopped
if parsing was successful or @NULL-like otherwise.
@see Format() @see Format()
*/ */
@@ -878,16 +892,9 @@ public:
/** /**
@overload @overload
*/ */
const char* ParseFormat(const char* date, const char* ParseFormat(const wxString& date,
const wxString& format = wxDefaultDateTimeFormat, const wxString& format = wxDefaultDateTimeFormat,
const wxDateTime& dateDef = wxDefaultDateTime); wxString::const_iterator* end = NULL);
/**
@overload
*/
const wchar_t* ParseFormat(const wchar_t* date,
const wxString& format = wxDefaultDateTimeFormat,
const wxDateTime& dateDef = wxDefaultDateTime);
/** /**
This function parses the string containing the date and time in ISO This function parses the string containing the date and time in ISO
@@ -933,39 +940,22 @@ public:
string which is not RFC 822 compliant. If you need to parse date string which is not RFC 822 compliant. If you need to parse date
formatted in more free ways, you should use ParseDateTime() or formatted in more free ways, you should use ParseDateTime() or
ParseDate() instead. ParseDate() instead.
See ParseFormat() for the description of function parameters and return
value.
*/ */
const char* ParseRfc822Date(const wxString& date, const char* ParseRfc822Date(const wxString& date,
wxString::const_iterator* end = NULL); wxString::const_iterator* end = NULL);
/**
@overload
*/
const char* ParseRfc822Date(const char* date);
/**
@overload
*/
const wchar_t* ParseRfc822Date(const wchar_t* date);
/** /**
This functions is like ParseDateTime(), but only allows the time to be This functions is like ParseDateTime(), but only allows the time to be
specified in the input string. specified in the input string.
@return @NULL if the conversion failed, otherwise return the pointer See ParseFormat() for the description of function parameters and return
to the character which stopped the scan. value.
*/ */
const char* ParseTime(const wxString& time, const char* ParseTime(const wxString& time,
wxString::const_iterator* end = NULL); wxString::const_iterator* end = NULL);
/**
@overload
*/
const char* ParseTime(const char* time);
/**
@overload
*/
const wchar_t* ParseTime(const wchar_t* time);
//@} //@}

View File

@@ -128,8 +128,20 @@ CallStrptime(const wxString& str,
#endif // HAVE_STRPTIME #endif // HAVE_STRPTIME
enum
{
DateLang_English = 1,
DateLang_Local = 2
};
// return the month if the string is a month name or Inv_Month otherwise // return the month if the string is a month name or Inv_Month otherwise
wxDateTime::Month GetMonthFromName(const wxString& name, int flags) //
// flags can contain wxDateTime::Name_Abbr/Name_Full or both of them and lang
// can be either DateLang_Local (default) to interpret string as a localized
// month name or DateLang_English to parse it as a standard English name or
// their combination to interpret it in any way
wxDateTime::Month
GetMonthFromName(const wxString& name, int flags, int lang)
{ {
wxDateTime::Month mon; wxDateTime::Month mon;
for ( mon = wxDateTime::Jan; mon < wxDateTime::Inv_Month; wxNextMonth(mon) ) for ( mon = wxDateTime::Jan; mon < wxDateTime::Inv_Month; wxNextMonth(mon) )
@@ -138,19 +150,35 @@ wxDateTime::Month GetMonthFromName(const wxString& name, int flags)
// and not versions // and not versions
if ( flags & wxDateTime::Name_Full ) if ( flags & wxDateTime::Name_Full )
{ {
if ( name.CmpNoCase(wxDateTime:: if ( lang & DateLang_English )
GetMonthName(mon, wxDateTime::Name_Full)) == 0 )
{ {
break; if ( name.CmpNoCase(wxDateTime::GetEnglishMonthName(mon,
wxDateTime::Name_Full)) == 0 )
break;
}
if ( lang & DateLang_Local )
{
if ( name.CmpNoCase(wxDateTime::GetMonthName(mon,
wxDateTime::Name_Full)) == 0 )
break;
} }
} }
if ( flags & wxDateTime::Name_Abbr ) if ( flags & wxDateTime::Name_Abbr )
{ {
if ( name.CmpNoCase(wxDateTime:: if ( lang & DateLang_English )
GetMonthName(mon, wxDateTime::Name_Abbr)) == 0 )
{ {
break; if ( name.CmpNoCase(wxDateTime::GetEnglishMonthName(mon,
wxDateTime::Name_Abbr)) == 0 )
break;
}
if ( lang & DateLang_Local )
{
if ( name.CmpNoCase(wxDateTime::GetMonthName(mon,
wxDateTime::Name_Abbr)) == 0 )
break;
} }
} }
} }
@@ -159,28 +187,46 @@ wxDateTime::Month GetMonthFromName(const wxString& name, int flags)
} }
// return the weekday if the string is a weekday name or Inv_WeekDay otherwise // return the weekday if the string is a weekday name or Inv_WeekDay otherwise
wxDateTime::WeekDay GetWeekDayFromName(const wxString& name, int flags) //
// flags and lang parameters have the same meaning as for GetMonthFromName()
// above
wxDateTime::WeekDay
GetWeekDayFromName(const wxString& name, int flags, int lang)
{ {
wxDateTime::WeekDay wd; wxDateTime::WeekDay wd;
for ( wd = wxDateTime::Sun; wd < wxDateTime::Inv_WeekDay; wxNextWDay(wd) ) for ( wd = wxDateTime::Sun; wd < wxDateTime::Inv_WeekDay; wxNextWDay(wd) )
{ {
// case-insensitive comparison either one of or with both abbreviated
// and not versions
if ( flags & wxDateTime::Name_Full ) if ( flags & wxDateTime::Name_Full )
{ {
if ( name.CmpNoCase(wxDateTime:: if ( lang & DateLang_English )
GetWeekDayName(wd, wxDateTime::Name_Full)) == 0 )
{ {
break; if ( name.CmpNoCase(wxDateTime::GetEnglishWeekDayName(wd,
wxDateTime::Name_Full)) == 0 )
break;
}
if ( lang & DateLang_Local )
{
if ( name.CmpNoCase(wxDateTime::GetWeekDayName(wd,
wxDateTime::Name_Full)) == 0 )
break;
} }
} }
if ( flags & wxDateTime::Name_Abbr ) if ( flags & wxDateTime::Name_Abbr )
{ {
if ( name.CmpNoCase(wxDateTime:: if ( lang & DateLang_English )
GetWeekDayName(wd, wxDateTime::Name_Abbr)) == 0 )
{ {
break; if ( name.CmpNoCase(wxDateTime::GetEnglishWeekDayName(wd,
wxDateTime::Name_Abbr)) == 0 )
break;
}
if ( lang & DateLang_Local )
{
if ( name.CmpNoCase(wxDateTime::GetWeekDayName(wd,
wxDateTime::Name_Abbr)) == 0 )
break;
} }
} }
} }
@@ -636,226 +682,156 @@ wxString wxDateTime::Format(const wxString& format, const TimeZone& tz) const
// //
// this function is "strict" by design - it must reject anything except true // this function is "strict" by design - it must reject anything except true
// RFC822 time specs. // RFC822 time specs.
// wxAnyStrPtr
// TODO a great candidate for using reg exps
const char *
wxDateTime::ParseRfc822Date(const wxString& date, wxString::const_iterator *end) wxDateTime::ParseRfc822Date(const wxString& date, wxString::const_iterator *end)
{ {
// TODO: rewrite using iterators instead of wxChar pointers wxString::const_iterator p = date.begin();
const wxStringCharType *p = date.wx_str();
const wxStringCharType *comma = wxStrchr(p, wxS(','));
if ( comma )
{
// the part before comma is the weekday
// skip it for now - we don't use but might check that it really // 1. week day
// corresponds to the specfied date static const int WDAY_LEN = 3;
p = comma + 1; const wxString::const_iterator endWday = p + WDAY_LEN;
const wxString wday(p, endWday);
if ( GetWeekDayFromName(wday, Name_Abbr, DateLang_English) == Inv_WeekDay )
return wxAnyStrPtr();
//else: ignore week day for now, we could also check that it really
// corresponds to the specified date
if ( *p != _T(' ') ) p = endWday;
{
wxLogDebug(_T("no space after weekday in RFC822 time spec"));
return NULL; // 2. separating comma
} if ( *p++ != ',' || *p++ != ' ' )
return wxAnyStrPtr();
p++; // skip space // 3. day number
}
// the following 1 or 2 digits are the day number
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ return wxAnyStrPtr();
wxLogDebug(_T("day number expected in RFC822 time spec, none found"));
return NULL; wxDateTime_t day = (wxDateTime_t)(*p++ - '0');
}
wxDateTime_t day = (wxDateTime_t)(*p++ - _T('0'));
if ( wxIsdigit(*p) ) if ( wxIsdigit(*p) )
{ {
day *= 10; day *= 10;
day = (wxDateTime_t)(day + (*p++ - _T('0'))); day = (wxDateTime_t)(day + (*p++ - '0'));
} }
if ( *p++ != _T(' ') ) if ( *p++ != ' ' )
{ return wxAnyStrPtr();
return NULL;
}
// the following 3 letters specify the month // 4. month name
wxString monName(p, 3); static const int MONTH_LEN = 3;
Month mon; const wxString::const_iterator endMonth = p + MONTH_LEN;
if ( monName == _T("Jan") ) const wxString monName(p, endMonth);
mon = Jan; Month mon = GetMonthFromName(monName, Name_Abbr, DateLang_English);
else if ( monName == _T("Feb") ) if ( mon == Inv_Month )
mon = Feb; return wxAnyStrPtr();
else if ( monName == _T("Mar") )
mon = Mar;
else if ( monName == _T("Apr") )
mon = Apr;
else if ( monName == _T("May") )
mon = May;
else if ( monName == _T("Jun") )
mon = Jun;
else if ( monName == _T("Jul") )
mon = Jul;
else if ( monName == _T("Aug") )
mon = Aug;
else if ( monName == _T("Sep") )
mon = Sep;
else if ( monName == _T("Oct") )
mon = Oct;
else if ( monName == _T("Nov") )
mon = Nov;
else if ( monName == _T("Dec") )
mon = Dec;
else
{
wxLogDebug(_T("Invalid RFC 822 month name '%s'"), monName.c_str());
return NULL; p = endMonth;
}
p += 3; if ( *p++ != ' ' )
return wxAnyStrPtr();
if ( *p++ != _T(' ') ) // 5. year
{
return NULL;
}
// next is the year
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ return wxAnyStrPtr();
// no year?
return NULL;
}
int year = *p++ - _T('0'); int year = *p++ - '0';
if ( !wxIsdigit(*p) ) // should have at least 2 digits in the year
if ( !wxIsdigit(*p) ) return wxAnyStrPtr();
{
// should have at least 2 digits in the year
return NULL;
}
year *= 10; year *= 10;
year += *p++ - _T('0'); year += *p++ - '0';
// is it a 2 digit year (as per original RFC 822) or a 4 digit one? // is it a 2 digit year (as per original RFC 822) or a 4 digit one?
if ( wxIsdigit(*p) ) if ( wxIsdigit(*p) )
{ {
year *= 10; year *= 10;
year += *p++ - _T('0'); year += *p++ - '0';
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ {
// no 3 digit years please // no 3 digit years please
return NULL; return wxAnyStrPtr();
} }
year *= 10; year *= 10;
year += *p++ - _T('0'); year += *p++ - '0';
} }
if ( *p++ != _T(' ') ) if ( *p++ != ' ' )
{ return wxAnyStrPtr();
return NULL;
}
// time is in the format hh:mm:ss and seconds are optional // 6. time in hh:mm:ss format with seconds being optional
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ return wxAnyStrPtr();
return NULL;
}
wxDateTime_t hour = (wxDateTime_t)(*p++ - _T('0')); wxDateTime_t hour = (wxDateTime_t)(*p++ - '0');
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ return wxAnyStrPtr();
return NULL;
}
hour *= 10; hour *= 10;
hour = (wxDateTime_t)(hour + (*p++ - _T('0'))); hour = (wxDateTime_t)(hour + (*p++ - '0'));
if ( *p++ != _T(':') ) if ( *p++ != ':' )
{ return wxAnyStrPtr();
return NULL;
}
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ return wxAnyStrPtr();
return NULL;
}
wxDateTime_t min = (wxDateTime_t)(*p++ - _T('0')); wxDateTime_t min = (wxDateTime_t)(*p++ - '0');
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ return wxAnyStrPtr();
return NULL;
}
min *= 10; min *= 10;
min = (wxDateTime_t)(min + *p++ - _T('0')); min += (wxDateTime_t)(*p++ - '0');
wxDateTime_t sec = 0; wxDateTime_t sec = 0;
if ( *p == _T(':') ) if ( *p == ':' )
{ {
p++; p++;
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ return wxAnyStrPtr();
return NULL;
}
sec = (wxDateTime_t)(*p++ - _T('0')); sec = (wxDateTime_t)(*p++ - '0');
if ( !wxIsdigit(*p) ) if ( !wxIsdigit(*p) )
{ return wxAnyStrPtr();
return NULL;
}
sec *= 10; sec *= 10;
sec = (wxDateTime_t)(sec + *p++ - _T('0')); sec += (wxDateTime_t)(*p++ - '0');
} }
if ( *p++ != _T(' ') ) if ( *p++ != ' ' )
{ return wxAnyStrPtr();
return NULL;
}
// and now the interesting part: the timezone // 7. now the interesting part: the timezone
int offset wxDUMMY_INITIALIZE(0); int offset wxDUMMY_INITIALIZE(0);
if ( *p == _T('-') || *p == _T('+') ) if ( *p == '-' || *p == '+' )
{ {
// the explicit offset given: it has the form of hhmm // the explicit offset given: it has the form of hhmm
bool plus = *p++ == _T('+'); bool plus = *p++ == '+';
if ( !wxIsdigit(*p) || !wxIsdigit(*(p + 1)) ) if ( !wxIsdigit(*p) || !wxIsdigit(*(p + 1)) )
{ return wxAnyStrPtr();
return NULL;
}
// hours // hours
offset = MIN_PER_HOUR*(10*(*p - _T('0')) + (*(p + 1) - _T('0'))); offset = MIN_PER_HOUR*(10*(*p - '0') + (*(p + 1) - '0'));
p += 2; p += 2;
if ( !wxIsdigit(*p) || !wxIsdigit(*(p + 1)) ) if ( !wxIsdigit(*p) || !wxIsdigit(*(p + 1)) )
{ return wxAnyStrPtr();
return NULL;
}
// minutes // minutes
offset += 10*(*p - _T('0')) + (*(p + 1) - _T('0')); offset += 10*(*p - '0') + (*(p + 1) - '0');
if ( !plus ) if ( !plus )
{
offset = -offset; offset = -offset;
}
p += 2; p += 2;
} }
else else // not numeric
{ {
// the symbolic timezone given: may be either military timezone or one // the symbolic timezone given: may be either military timezone or one
// of standard abbreviations // of standard abbreviations
@@ -871,18 +847,14 @@ wxDateTime::ParseRfc822Date(const wxString& date, wxString::const_iterator *end)
}; };
if ( *p < _T('A') || *p > _T('Z') || *p == _T('J') ) if ( *p < _T('A') || *p > _T('Z') || *p == _T('J') )
{ return wxAnyStrPtr();
wxLogDebug(_T("Invalid militaty timezone '%c'"), *p);
return NULL; offset = offsets[*p++ - 'A'];
}
offset = offsets[*p++ - _T('A')];
} }
else else
{ {
// abbreviation // abbreviation
wxString tz = p; const wxString tz(p, date.end());
if ( tz == _T("UT") || tz == _T("UTC") || tz == _T("GMT") ) if ( tz == _T("UT") || tz == _T("UTC") || tz == _T("GMT") )
offset = 0; offset = 0;
else if ( tz == _T("AST") ) else if ( tz == _T("AST") )
@@ -906,11 +878,7 @@ wxDateTime::ParseRfc822Date(const wxString& date, wxString::const_iterator *end)
else if ( tz == _T("PDT") ) else if ( tz == _T("PDT") )
offset = PDT - GMT0; offset = PDT - GMT0;
else else
{ return wxAnyStrPtr();
wxLogDebug(_T("Unknown RFC 822 timezone '%s'"), p);
return NULL;
}
p += tz.length(); p += tz.length();
} }
@@ -919,15 +887,15 @@ wxDateTime::ParseRfc822Date(const wxString& date, wxString::const_iterator *end)
offset *= MIN_PER_HOUR; offset *= MIN_PER_HOUR;
} }
// the spec was correct, construct the date from the values we found // the spec was correct, construct the date from the values we found
Set(day, mon, year, hour, min, sec); Set(day, mon, year, hour, min, sec);
MakeFromTimezone(TimeZone::Make(offset*SEC_PER_MIN)); MakeFromTimezone(TimeZone::Make(offset*SEC_PER_MIN));
const size_t endpos = p - date.wx_str();
if ( end ) if ( end )
*end = date.begin() + endpos; *end = p;
return date.c_str() + endpos; return wxAnyStrPtr(date, p);
} }
#ifdef __WINDOWS__ #ifdef __WINDOWS__
@@ -1090,13 +1058,13 @@ static wxString GetLocaleDateFormat()
#endif // __WINDOWS__ #endif // __WINDOWS__
const char * wxAnyStrPtr
wxDateTime::ParseFormat(const wxString& date, wxDateTime::ParseFormat(const wxString& date,
const wxString& format, const wxString& format,
const wxDateTime& dateDef, const wxDateTime& dateDef,
wxString::const_iterator *end) wxString::const_iterator *end)
{ {
wxCHECK_MSG( !format.empty(), NULL, "format can't be empty" ); wxCHECK_MSG( !format.empty(), wxAnyStrPtr(), "format can't be empty" );
wxString str; wxString str;
unsigned long num; unsigned long num;
@@ -1147,7 +1115,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( *input++ != *fmt ) if ( *input++ != *fmt )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
} }
@@ -1162,7 +1130,7 @@ wxDateTime::ParseFormat(const wxString& date,
while ( wxIsdigit(*++fmt) ) while ( wxIsdigit(*++fmt) )
{ {
width *= 10; width *= 10;
width += *fmt - _T('0'); width += *fmt - '0';
} }
// the default widths for the various fields // the default widths for the various fields
@@ -1195,12 +1163,16 @@ wxDateTime::ParseFormat(const wxString& date,
case _T('a'): // a weekday name case _T('a'): // a weekday name
case _T('A'): case _T('A'):
{ {
int flag = *fmt == _T('a') ? Name_Abbr : Name_Full; wday = GetWeekDayFromName
wday = GetWeekDayFromName(GetAlphaToken(input), flag); (
GetAlphaToken(input),
*fmt == 'a' ? Name_Abbr : Name_Full,
DateLang_Local
);
if ( wday == Inv_WeekDay ) if ( wday == Inv_WeekDay )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
} }
haveWDay = true; haveWDay = true;
@@ -1209,12 +1181,16 @@ wxDateTime::ParseFormat(const wxString& date,
case _T('b'): // a month name case _T('b'): // a month name
case _T('B'): case _T('B'):
{ {
int flag = *fmt == _T('b') ? Name_Abbr : Name_Full; mon = GetMonthFromName
mon = GetMonthFromName(GetAlphaToken(input), flag); (
GetAlphaToken(input),
*fmt == 'b' ? Name_Abbr : Name_Full,
DateLang_Local
);
if ( mon == Inv_Month ) if ( mon == Inv_Month )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
} }
haveMon = true; haveMon = true;
@@ -1253,7 +1229,7 @@ wxDateTime::ParseFormat(const wxString& date,
wxS("%X %x") wxS("%X %x")
); );
if ( !dt.IsValid() ) if ( !dt.IsValid() )
return NULL; return wxAnyStrPtr();
Tm tm = dt.GetTm(); Tm tm = dt.GetTm();
@@ -1276,7 +1252,7 @@ wxDateTime::ParseFormat(const wxString& date,
(num > 31) || (num < 1) ) (num > 31) || (num < 1) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
// we can't check whether the day range is correct yet, will // we can't check whether the day range is correct yet, will
@@ -1289,7 +1265,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) || (num > 23) ) if ( !GetNumericToken(width, input, &num) || (num > 23) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveHour = true; haveHour = true;
@@ -1300,7 +1276,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) || !num || (num > 12) ) if ( !GetNumericToken(width, input, &num) || !num || (num > 12) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveHour = true; haveHour = true;
@@ -1312,7 +1288,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) || !num || (num > 366) ) if ( !GetNumericToken(width, input, &num) || !num || (num > 366) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveYDay = true; haveYDay = true;
@@ -1321,7 +1297,7 @@ wxDateTime::ParseFormat(const wxString& date,
case _T('l'): // milliseconds (0-999) case _T('l'): // milliseconds (0-999)
if ( !GetNumericToken(width, input, &num) ) if ( !GetNumericToken(width, input, &num) )
return NULL; return wxAnyStrPtr();
haveMsec = true; haveMsec = true;
msec = (wxDateTime_t)num; msec = (wxDateTime_t)num;
@@ -1331,7 +1307,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) || !num || (num > 12) ) if ( !GetNumericToken(width, input, &num) || !num || (num > 12) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveMon = true; haveMon = true;
@@ -1342,7 +1318,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) || (num > 59) ) if ( !GetNumericToken(width, input, &num) || (num > 59) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveMin = true; haveMin = true;
@@ -1362,7 +1338,7 @@ wxDateTime::ParseFormat(const wxString& date,
GetAmPmStrings(&am, &pm); GetAmPmStrings(&am, &pm);
if (am.empty() && pm.empty()) if (am.empty() && pm.empty())
return NULL; // no am/pm strings defined return wxAnyStrPtr(); // no am/pm strings defined
if ( token.CmpNoCase(pm) == 0 ) if ( token.CmpNoCase(pm) == 0 )
{ {
isPM = true; isPM = true;
@@ -1370,7 +1346,7 @@ wxDateTime::ParseFormat(const wxString& date,
else if ( token.CmpNoCase(am) != 0 ) else if ( token.CmpNoCase(am) != 0 )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
} }
break; break;
@@ -1380,7 +1356,7 @@ wxDateTime::ParseFormat(const wxString& date,
wxDateTime dt; wxDateTime dt;
if ( !dt.ParseFormat(wxString(input, date.end()), if ( !dt.ParseFormat(wxString(input, date.end()),
wxS("%I:%M:%S %p"), &input) ) wxS("%I:%M:%S %p"), &input) )
return NULL; return wxAnyStrPtr();
haveHour = haveMin = haveSec = true; haveHour = haveMin = haveSec = true;
@@ -1396,7 +1372,7 @@ wxDateTime::ParseFormat(const wxString& date,
const wxDateTime const wxDateTime
dt = ParseFormatAt(input, date.end(), wxS("%H:%M")); dt = ParseFormatAt(input, date.end(), wxS("%H:%M"));
if ( !dt.IsValid() ) if ( !dt.IsValid() )
return NULL; return wxAnyStrPtr();
haveHour = haveHour =
haveMin = true; haveMin = true;
@@ -1411,7 +1387,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) || (num > 61) ) if ( !GetNumericToken(width, input, &num) || (num > 61) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveSec = true; haveSec = true;
@@ -1423,7 +1399,7 @@ wxDateTime::ParseFormat(const wxString& date,
const wxDateTime const wxDateTime
dt = ParseFormatAt(input, date.end(), wxS("%H:%M:%S")); dt = ParseFormatAt(input, date.end(), wxS("%H:%M:%S"));
if ( !dt.IsValid() ) if ( !dt.IsValid() )
return NULL; return wxAnyStrPtr();
haveHour = haveHour =
haveMin = haveMin =
@@ -1440,7 +1416,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) || (wday > 6) ) if ( !GetNumericToken(width, input, &num) || (wday > 6) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveWDay = true; haveWDay = true;
@@ -1496,7 +1472,7 @@ wxDateTime::ParseFormat(const wxString& date,
dt = ParseFormatAt(input, date.end(), dt = ParseFormatAt(input, date.end(),
fmtDate, fmtDateAlt); fmtDate, fmtDateAlt);
if ( !dt.IsValid() ) if ( !dt.IsValid() )
return NULL; return wxAnyStrPtr();
Tm tm = dt.GetTm(); Tm tm = dt.GetTm();
@@ -1517,7 +1493,7 @@ wxDateTime::ParseFormat(const wxString& date,
// use strptime() to do it for us (FIXME !Unicode friendly) // use strptime() to do it for us (FIXME !Unicode friendly)
struct tm tm; struct tm tm;
if ( !CallStrptime(date, input, "%X", &tm) ) if ( !CallStrptime(date, input, "%X", &tm) )
return NULL; return wxAnyStrPtr();
haveHour = haveMin = haveSec = true; haveHour = haveMin = haveSec = true;
@@ -1536,7 +1512,7 @@ wxDateTime::ParseFormat(const wxString& date,
const wxDateTime const wxDateTime
dt = ParseFormatAt(input, date.end(), "%T", "%r"); dt = ParseFormatAt(input, date.end(), "%T", "%r");
if ( !dt.IsValid() ) if ( !dt.IsValid() )
return NULL; return wxAnyStrPtr();
haveHour = haveHour =
haveMin = haveMin =
@@ -1554,7 +1530,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) || (num > 99) ) if ( !GetNumericToken(width, input, &num) || (num > 99) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveYear = true; haveYear = true;
@@ -1568,7 +1544,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( !GetNumericToken(width, input, &num) ) if ( !GetNumericToken(width, input, &num) )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
haveYear = true; haveYear = true;
@@ -1583,7 +1559,7 @@ wxDateTime::ParseFormat(const wxString& date,
if ( *input++ != _T('%') ) if ( *input++ != _T('%') )
{ {
// no match // no match
return NULL; return wxAnyStrPtr();
} }
break; break;
@@ -1593,7 +1569,7 @@ wxDateTime::ParseFormat(const wxString& date,
// fall through // fall through
default: // not a known format spec default: // not a known format spec
return NULL; return wxAnyStrPtr();
} }
} }
@@ -1634,22 +1610,14 @@ wxDateTime::ParseFormat(const wxString& date,
if ( haveDay ) if ( haveDay )
{ {
if ( mday > GetNumberOfDays(tm.mon, tm.year) ) if ( mday > GetNumberOfDays(tm.mon, tm.year) )
{ return wxAnyStrPtr();
wxLogDebug(_T("bad month day in wxDateTime::ParseFormat"));
return NULL;
}
tm.mday = mday; tm.mday = mday;
} }
else if ( haveYDay ) else if ( haveYDay )
{ {
if ( yday > GetNumberOfDays(tm.year) ) if ( yday > GetNumberOfDays(tm.year) )
{ return wxAnyStrPtr();
wxLogDebug(_T("bad year day in wxDateTime::ParseFormat"));
return NULL;
}
Tm tm2 = wxDateTime(1, Jan, tm.year).SetToYearDay(yday).GetTm(); Tm tm2 = wxDateTime(1, Jan, tm.year).SetToYearDay(yday).GetTm();
@@ -1688,19 +1656,15 @@ wxDateTime::ParseFormat(const wxString& date,
// finally check that the week day is consistent -- if we had it // finally check that the week day is consistent -- if we had it
if ( haveWDay && GetWeekDay() != wday ) if ( haveWDay && GetWeekDay() != wday )
{ return wxAnyStrPtr();
wxLogDebug(_T("inconsistsnet week day in wxDateTime::ParseFormat()"));
return NULL;
}
if ( end ) if ( end )
*end = input; *end = input;
return date.c_str() + (input - date.begin()); return wxAnyStrPtr(date, input);
} }
const char * wxAnyStrPtr
wxDateTime::ParseDateTime(const wxString& date, wxString::const_iterator *end) wxDateTime::ParseDateTime(const wxString& date, wxString::const_iterator *end)
{ {
// Set to current day and hour, so strings like '14:00' becomes today at // Set to current day and hour, so strings like '14:00' becomes today at
@@ -1723,7 +1687,7 @@ wxDateTime::ParseDateTime(const wxString& date, wxString::const_iterator *end)
const wxString timestr(endDate, date.end()); const wxString timestr(endDate, date.end());
if ( !dtTime.ParseTime(timestr, &endTime) ) if ( !dtTime.ParseTime(timestr, &endTime) )
return NULL; return wxAnyStrPtr();
endBoth = endDate + (endTime - timestr.begin()); endBoth = endDate + (endTime - timestr.begin());
} }
@@ -1731,14 +1695,14 @@ wxDateTime::ParseDateTime(const wxString& date, wxString::const_iterator *end)
{ {
// check if we have a time followed by a date // check if we have a time followed by a date
if ( !dtTime.ParseTime(date, &endTime) ) if ( !dtTime.ParseTime(date, &endTime) )
return NULL; return wxAnyStrPtr();
while ( endTime != date.end() && wxIsspace(*endTime) ) while ( endTime != date.end() && wxIsspace(*endTime) )
++endTime; ++endTime;
const wxString datestr(endTime, date.end()); const wxString datestr(endTime, date.end());
if ( !dtDate.ParseDate(datestr, &endDate) ) if ( !dtDate.ParseDate(datestr, &endDate) )
return NULL; return wxAnyStrPtr();
endBoth = endTime + (endDate - datestr.begin()); endBoth = endTime + (endDate - datestr.begin());
} }
@@ -1751,10 +1715,10 @@ wxDateTime::ParseDateTime(const wxString& date, wxString::const_iterator *end)
if ( end ) if ( end )
*end = endBoth; *end = endBoth;
return date.c_str() + (endBoth - date.begin()); return wxAnyStrPtr(date, endBoth);
} }
const char * wxAnyStrPtr
wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end) wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
{ {
// this is a simplified version of ParseDateTime() which understands only // this is a simplified version of ParseDateTime() which understands only
@@ -1801,8 +1765,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
if ( end ) if ( end )
*end = pEnd; *end = pEnd;
return wxStringOperations::AddToIter(date.c_str().AsChar(), return wxAnyStrPtr(date, pEnd);
pEnd - pBegin);
} }
} }
@@ -1906,7 +1869,12 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
else // not a number else // not a number
{ {
// be careful not to overwrite the current mon value // be careful not to overwrite the current mon value
Month mon2 = GetMonthFromName(token, Name_Full | Name_Abbr); Month mon2 = GetMonthFromName
(
token,
Name_Full | Name_Abbr,
DateLang_Local | DateLang_English
);
if ( mon2 != Inv_Month ) if ( mon2 != Inv_Month )
{ {
// it's a month // it's a month
@@ -1934,7 +1902,12 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
} }
else // not a valid month name else // not a valid month name
{ {
WeekDay wday2 = GetWeekDayFromName(token, Name_Full | Name_Abbr); WeekDay wday2 = GetWeekDayFromName
(
token,
Name_Full | Name_Abbr,
DateLang_Local | DateLang_English
);
if ( wday2 != Inv_WeekDay ) if ( wday2 != Inv_WeekDay )
{ {
// a week day // a week day
@@ -2013,11 +1986,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
// either no more tokens or the scan was stopped by something we couldn't // either no more tokens or the scan was stopped by something we couldn't
// parse - in any case, see if we can construct a date from what we have // parse - in any case, see if we can construct a date from what we have
if ( !haveDay && !haveWDay ) if ( !haveDay && !haveWDay )
{ return wxAnyStrPtr();
wxLogDebug(_T("ParseDate: no day, no weekday hence no date."));
return NULL;
}
if ( haveWDay && (haveMon || haveYear || haveDay) && if ( haveWDay && (haveMon || haveYear || haveDay) &&
!(haveDay && haveMon && haveYear) ) !(haveDay && haveMon && haveYear) )
@@ -2025,7 +1994,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
// without adjectives (which we don't support here) the week day only // without adjectives (which we don't support here) the week day only
// makes sense completely separately or with the full date // makes sense completely separately or with the full date
// specification (what would "Wed 1999" mean?) // specification (what would "Wed 1999" mean?)
return NULL; return wxAnyStrPtr();
} }
if ( !haveWDay && haveYear && !(haveDay && haveMon) ) if ( !haveWDay && haveYear && !(haveDay && haveMon) )
@@ -2051,12 +2020,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
} }
if ( !haveMon ) if ( !haveMon )
{ return wxAnyStrPtr();
// if we give the year, month and day must be given too
wxLogDebug(_T("ParseDate: day and month should be specified if year is."));
return NULL;
}
} }
if ( !haveMon ) if ( !haveMon )
@@ -2074,7 +2038,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
// normally we check the day above but the check is optimistic in case // normally we check the day above but the check is optimistic in case
// we find the day before its month/year so we have to redo it now // we find the day before its month/year so we have to redo it now
if ( day > GetNumberOfDays(mon, year) ) if ( day > GetNumberOfDays(mon, year) )
return NULL; return wxAnyStrPtr();
Set(day, mon, year); Set(day, mon, year);
@@ -2082,12 +2046,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
{ {
// check that it is really the same // check that it is really the same
if ( GetWeekDay() != wday ) if ( GetWeekDay() != wday )
{ return wxAnyStrPtr();
// inconsistency detected
wxLogDebug(_T("ParseDate: inconsistent day/weekday."));
return NULL;
}
} }
} }
else // haveWDay else // haveWDay
@@ -2109,17 +2068,17 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
if ( end ) if ( end )
*end = p; *end = p;
return wxStringOperations::AddToIter(date.c_str().AsChar(), p - pBegin); return wxAnyStrPtr(date, p);
} }
const char * wxAnyStrPtr
wxDateTime::ParseTime(const wxString& time, wxString::const_iterator *end) wxDateTime::ParseTime(const wxString& time, wxString::const_iterator *end)
{ {
// first try some extra things // first try some extra things
static const struct static const struct
{ {
const char *name; const char *name;
wxDateTime_t hour; wxDateTime_t hour;
} stdTimes[] = } stdTimes[] =
{ {
{ wxTRANSLATE("noon"), 12 }, { wxTRANSLATE("noon"), 12 },
@@ -2129,17 +2088,17 @@ wxDateTime::ParseTime(const wxString& time, wxString::const_iterator *end)
for ( size_t n = 0; n < WXSIZEOF(stdTimes); n++ ) for ( size_t n = 0; n < WXSIZEOF(stdTimes); n++ )
{ {
wxString timeString = wxGetTranslation(stdTimes[n].name); const wxString timeString = wxGetTranslation(stdTimes[n].name);
size_t len = timeString.length(); const wxString::const_iterator p = time.begin() + timeString.length();
if ( timeString.CmpNoCase(wxString(time, len)) == 0 ) if ( timeString.CmpNoCase(wxString(time.begin(), p)) == 0 )
{ {
// casts required by DigitalMars // casts required by DigitalMars
Set(stdTimes[n].hour, wxDateTime_t(0), wxDateTime_t(0)); Set(stdTimes[n].hour, wxDateTime_t(0), wxDateTime_t(0));
if ( end ) if ( end )
*end = time.begin() + len; *end = p;
return time.c_str() + len; return wxAnyStrPtr(time, p);
} }
} }
@@ -2159,12 +2118,12 @@ wxDateTime::ParseTime(const wxString& time, wxString::const_iterator *end)
for ( size_t nFmt = 0; nFmt < WXSIZEOF(timeFormats); nFmt++ ) for ( size_t nFmt = 0; nFmt < WXSIZEOF(timeFormats); nFmt++ )
{ {
const char *result = ParseFormat(time, timeFormats[nFmt], end); const wxAnyStrPtr result = ParseFormat(time, timeFormats[nFmt], end);
if ( result ) if ( result )
return result; return result;
} }
return NULL; return wxAnyStrPtr();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -206,6 +206,7 @@ rm -rf $RPM_BUILD_ROOT
# --- wxBase headers list begins here --- # --- wxBase headers list begins here ---
cat <<EOF >wxbase-headers.files cat <<EOF >wxbase-headers.files
wx/afterstd.h wx/afterstd.h
wx/anystr.h
wx/app.h wx/app.h
wx/apptrait.h wx/apptrait.h
wx/archive.h wx/archive.h

View File

@@ -111,6 +111,7 @@ rm -rf $RPM_BUILD_ROOT
# --- wxBase headers list begins here --- # --- wxBase headers list begins here ---
cat <<EOF >wxbase-headers.files cat <<EOF >wxbase-headers.files
wx/afterstd.h wx/afterstd.h
wx/anystr.h
wx/app.h wx/app.h
wx/apptrait.h wx/apptrait.h
wx/archive.h wx/archive.h

View File

@@ -135,6 +135,7 @@ rm -rf $RPM_BUILD_ROOT
# --- wxBase headers list begins here --- # --- wxBase headers list begins here ---
cat <<EOF >wxbase-headers.files cat <<EOF >wxbase-headers.files
wx/afterstd.h wx/afterstd.h
wx/anystr.h
wx/app.h wx/app.h
wx/apptrait.h wx/apptrait.h
wx/archive.h wx/archive.h