]>
Commit | Line | Data |
---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | |
2 | // Name: wx/anystr.h | |
3 | // Purpose: wxAnyStrPtr class declaration | |
4 | // Author: Vadim Zeitlin | |
5 | // Created: 2009-03-23 | |
6 | // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org> | |
7 | // Licence: wxWindows licence | |
8 | /////////////////////////////////////////////////////////////////////////////// | |
9 | ||
10 | #ifndef _WX_ANYSTR_H_ | |
11 | #define _WX_ANYSTR_H_ | |
12 | ||
13 | #include "wx/string.h" | |
14 | ||
15 | // ---------------------------------------------------------------------------- | |
16 | // wxAnyStrPtr | |
17 | // | |
18 | // Notice that this is an internal and intentionally not documented class. It | |
19 | // is only used by wxWidgets itself to ensure compatibility with previous | |
20 | // versions and shouldn't be used by user code. When you see a function | |
21 | // returning it you should just know that you can treat it as a string pointer. | |
22 | // ---------------------------------------------------------------------------- | |
23 | ||
24 | // This is a helper class convertible to either narrow or wide string pointer. | |
25 | // It is similar to wxCStrData but, unlike it, can be NULL which is required to | |
26 | // represent the return value of wxDateTime::ParseXXX() methods for example. | |
27 | // | |
28 | // NB: this class is fully inline and so doesn't need to be DLL-exported | |
29 | class wxAnyStrPtr | |
30 | { | |
31 | public: | |
32 | // ctors: this class must be created from the associated string or using | |
33 | // its default ctor for an invalid NULL-like object; notice that it is | |
34 | // immutable after creation. | |
35 | ||
36 | // ctor for invalid pointer | |
37 | wxAnyStrPtr() | |
38 | : m_str(NULL) | |
39 | { | |
40 | } | |
41 | ||
42 | // ctor for valid pointer into the given string (whose lifetime must be | |
43 | // greater than ours and which should remain constant while we're used) | |
44 | wxAnyStrPtr(const wxString& str, const wxString::const_iterator& iter) | |
45 | : m_str(&str), | |
46 | m_iter(iter) | |
47 | { | |
48 | } | |
49 | ||
50 | // default copy ctor is ok and so is default dtor, in particular we do not | |
51 | // free the string | |
52 | ||
53 | ||
54 | // various operators meant to make this class look like a superposition of | |
55 | // char* and wchar_t* | |
56 | ||
57 | // this one is needed to allow boolean expressions involving these objects, | |
58 | // e.g. "if ( FuncReturningAnyStrPtr() && ... )" (unfortunately using | |
59 | // unspecified_bool_type here wouldn't help with ambiguity between all the | |
60 | // different conversions to pointers) | |
61 | operator bool() const { return m_str != NULL; } | |
62 | ||
63 | // at least VC6 and VC7 also need this one or they complain about ambiguity | |
64 | // for !anystr expressions | |
65 | bool operator!() const { return !((bool)*this); } | |
66 | ||
67 | ||
68 | // and these are the conversions operator which allow to assign the result | |
69 | // of FuncReturningAnyStrPtr() to either char* or wxChar* (i.e. wchar_t*) | |
70 | operator const char *() const | |
71 | { | |
72 | if ( !m_str ) | |
73 | return NULL; | |
74 | ||
75 | // check if the string is convertible to char at all | |
76 | // | |
77 | // notice that this pointer points into wxString internal buffer | |
78 | // containing its char* representation and so it can be kept for as | |
79 | // long as wxString is not modified -- which is long enough for our | |
80 | // needs | |
81 | const char *p = m_str->c_str().AsChar(); | |
82 | if ( *p ) | |
83 | { | |
84 | // find the offset of the character corresponding to this iterator | |
85 | // position in bytes: we don't have any direct way to do it so we | |
86 | // need to redo the conversion again for the part of the string | |
87 | // before the iterator to find its length in bytes in current | |
88 | // locale | |
89 | // | |
90 | // NB: conversion won't fail as it succeeded for the entire string | |
91 | p += strlen(wxString(m_str->begin(), m_iter).mb_str()); | |
92 | } | |
93 | //else: conversion failed, return "" as we can't do anything else | |
94 | ||
95 | return p; | |
96 | } | |
97 | ||
98 | operator const wchar_t *() const | |
99 | { | |
100 | if ( !m_str ) | |
101 | return NULL; | |
102 | ||
103 | // no complications with wide strings (as long as we discount | |
104 | // surrogates as we do for now) | |
105 | // | |
106 | // just remember that this works as long as wxString keeps an internal | |
107 | // buffer with its wide wide char representation, just as with AsChar() | |
108 | // above | |
109 | return m_str->c_str().AsWChar() + (m_iter - m_str->begin()); | |
110 | } | |
111 | ||
112 | // Because the objects of this class are only used as return type for | |
113 | // functions which can return NULL we can skip providing dereferencing | |
114 | // operators: the code using this class must test it for NULL first and if | |
115 | // it does anything else with it it has to assign it to either char* or | |
116 | // wchar_t* itself, before dereferencing. | |
117 | // | |
118 | // IOW this | |
119 | // | |
120 | // if ( *FuncReturningAnyStrPtr() ) | |
121 | // | |
122 | // is invalid because it could crash. And this | |
123 | // | |
124 | // const char *p = FuncReturningAnyStrPtr(); | |
125 | // if ( p && *p ) | |
126 | // | |
127 | // already works fine. | |
128 | ||
129 | private: | |
130 | // the original string and the position in it we correspond to, if the | |
131 | // string is NULL this object is NULL pointer-like | |
132 | const wxString * const m_str; | |
133 | const wxString::const_iterator m_iter; | |
134 | ||
135 | wxDECLARE_NO_ASSIGN_CLASS(wxAnyStrPtr); | |
136 | }; | |
137 | ||
138 | #endif // _WX_ANYSTR_H_ | |
139 |