WxExtLib - WxMessageFormat.h
00001: // -*- c++ -*-
00002: /*
00003: -------------------------------------------------------------------------
00004: This file is part of WxWidgetsExtensions library.
00005: -------------------------------------------------------------------------
00006:
00007: WxExtLib (WxWidgetsExtensions) library
00008: -----------------------------
00009:
00010: COPYRIGHT NOTICE:
00011:
00012: WxExtLib library Copyright (c) 2003-2007 Daniel Käps
00013:
00014: The WxWidgetsExtensions library and associated documentation files (the
00015: "Software") is provided "AS IS". The author(s) disclaim all
00016: warranties, expressed or implied, including, without limitation, the
00017: warranties of merchantability and of fitness for any purpose. The
00018: author(s) assume no liability for direct, indirect, incidental,
00019: special, exemplary, or consequential damages, which may result from
00020: the use of or other dealings in the Software, even if advised of the
00021: possibility of such damage.
00022:
00023: Permission is hereby granted, free of charge, to any person obtaining
00024: a copy of this Software, to deal in the Software without restriction,
00025: including without limitation the rights to use, copy, modify, merge,
00026: publish, distribute, sublicense, and/or sell copies of the Software,
00027: and to permit persons to whom the Software is furnished to do so,
00028: subject to the following conditions:
00029:
00030: 1. The origin of this source code must not be misrepresented.
00031: 2. Altered versions must be plainly marked as such and must not be
00032: misrepresented as being the original source.
00033: 3. This Copyright notice may not be removed or altered from any
00034: source or altered source distribution.
00035:
00036: End of WxExtLib library Copyright Notice
00037:
00038: -------------------------------------------------------------------------
00039: */
00040:
00041: //-------------------------------------------------------------------------
00042: //
00043: // NOTE
00044: //
00045: // - WxMessageFormat.h,.cpp files are superseeded by StxFormatMessage.h,.cpp.
00046: // Development and changes shall be made to StxFormatMessage.h,.cpp
00047: // (not yet published).
00048: //
00049: //
00050: //-------------------------------------------------------------------------
00051: //
00052: // Interoperability with std::string instead of wxString:
00053: // ------------------------------------------------------
00054: //
00055: // if M_MessageFormat_StdString is defined, the wxMessageFormatter/wxFormat/
00056: // wxFormatMessage classes and functions will be made up to be usable with
00057: // std::string instead of wxString. This involves following transparent
00058: // renames (only in this header and in implemenation file):
00059: // wxMessageFormatter -> stMessageFormatter
00060: // wxFormat -> stFormat
00061: // wxFormatMessage -> stFormatMessage
00062: // wxString -> std::string
00063: //
00064: // Example: wxFormatMessage()/stFormatMessage() the following function call
00065: // can be used:
00066: // - if M_MessageFormat_StdString was defined:
00067: // std::string FormattedStdString = stFormatMessage ("file %1 has length of %2 bytes",
00068: // FilenameStdString, "4096")
00069: // - if M_MessageFormat_StdString was not defined:
00070: // wxString FormattedWxString = wxFormatMessage ("file %1 has length of %2 bytes",
00071: // FilenameWxString, "4096")
00072: //
00073: // NOTE to use both variants in a single compilation unit,
00074: // #undef _INCLUDED_WxMessageFormat_h may be required to get the header
00075: // included a second time (untested)
00076: //
00077: //-------------------------------------------------------------------------
00078:
00079: // no guards here, use guards around specific class declarations/implementations
00080: // #ifndef _INCLUDED_WxMessageFormat_h
00081: // #define _INCLUDED_WxMessageFormat_h
00082:
00083: //=========================================================================
00084:
00085: #ifdef M_MessageFormat_IsUseStxFormatMessage
00086:
00087: # include <StxConfig.h> // for stxInt64
00088: # include <StxFormatMessage.h>
00089:
00090: //=========================================================================
00091:
00092: #else
00093:
00094: //-------------------------------------------------------------------------
00095:
00096: // ?
00097: // #if ((!defined M_MessageFormat_IsReIncludeHeader) && (!defined M_MessageFormat_IsReIncludeSource))
00098: // # include "WxExtLibConfig.h"
00099: // #endif
00100:
00101: //=========================================================================
00102:
00103: #if (!defined M_MessageFormat_IsEmitDeclarations)
00104:
00105: //-------------------------------------------------------------------------
00106:
00107: #if ((!defined M_MessageFormat_WxString) && (!defined M_MessageFormat_StdString))
00108: # error "please define at least one of M_MessageFormat_StdString, M_MessageFormat_WxString"
00109: #endif
00110:
00111: //-------------------------------------------------------------------------
00112:
00113: // wxString interface: wxMessageFormatter, wxFormat, etc.
00114: // using wxString
00115:
00116: #if (defined M_MessageFormat_WxString)
00117:
00118: #ifndef _DECLARED_MessageFormat_WxString
00119: #define _DECLARED_MessageFormat_WxString
00120:
00121: #include <wx/defs.h>
00122:
00123: #ifndef WX_PRECOMP
00124: # include <wx/string.h>
00125: # include <wx/dynarray.h>
00126: #endif
00127:
00128: #ifndef WX_DEFINE_ARRAY_PTR
00129: // under wxWindows 2.5.2, WX_DEFINE_ARRAY_PTR should be used, but it
00130: // doesn't seem to be available under wxWindows 2.4.1
00131: # define WX_DEFINE_ARRAY_PTR WX_DEFINE_ARRAY
00132: #endif
00133:
00134: #define M_MessageFormat_IsEmitDeclarations
00135: #define M_MessageFormat_IsUseWxString 1
00136: #define M_MessageFormatter wxMessageFormatter
00137: #define M_Format wxFormat
00138: #define M_FormatMessage wxFormatMessage
00139: #define M_String wxString
00140: #define M_FormatArray wxFormatArray
00141: #define M_makeMessageFormatter MessageFormatter
00142: #include "WxMessageFormat.h"
00143: #undef M_MessageFormat_IsEmitDeclarations
00144: #undef M_MessageFormat_IsUseWxString
00145: #undef M_MessageFormatter
00146: #undef M_Format
00147: #undef M_FormatMessage
00148: #undef M_String
00149: #undef M_FormatArray
00150: #undef M_makeMessageFormatter
00151:
00152: #endif
00153:
00154: #endif
00155:
00156: //-------------------------------------------------------------------------
00157:
00158: // std::string interface: stMessageFormatter, stFormat, etc.
00159: // using std::string
00160:
00161: #if (defined M_MessageFormat_StdString)
00162:
00163: #ifndef _DECLARED_MessageFormat_StdString
00164: #define _DECLARED_MessageFormat_StdString
00165:
00166:
00167: #include <string>
00168: #include <vector>
00169:
00170: #define M_MessageFormat_IsEmitDeclarations
00171: #define M_MessageFormat_IsUseStdString 1
00172: #define M_MessageFormatter stMessageFormatter
00173: #define M_Format stFormat
00174: #define M_FormatMessage stFormatMessage
00175: #define M_String std::string
00176: #define M_FormatArray stFormatArray
00177: #define M_makeMessageFormatter makeStdStringMessageFormatter
00178: #include "WxMessageFormat.h"
00179: #undef M_MessageFormat_IsEmitDeclarations
00180: #undef M_MessageFormat_IsUseStdString
00181: #undef M_MessageFormatter
00182: #undef M_Format
00183: #undef M_FormatMessage
00184: #undef M_String
00185: #undef M_FormatArray
00186: #undef M_makeMessageFormatter
00187:
00188: #endif
00189:
00190: #endif
00191:
00192: //-------------------------------------------------------------------------
00193:
00194: #endif
00195:
00196: //=========================================================================
00197:
00198: #if (defined M_MessageFormat_IsEmitDeclarations)
00199:
00200: //-------------------------------------------------------------------------
00201:
00202: // WARN it is not clear how the multiple variations of this file
00203: // interact with "#pragma interface"
00204: // #if defined(__GNUG__) && (!defined(__APPLE__)) && (!defined(M_NoPragmaInterface))
00205: // # pragma interface "WxMessageFormat.h"
00206: // #endif
00207:
00208: //-------------------------------------------------------------------------
00209:
00210: #ifdef M_MessageFormat_IsTraceUsedInterface
00211: # if (M_MessageFormat_IsUseWxString == 1)
00212: # pragma message ("-- wxFormatMessage() etc. / wxString interface")
00213: # endif
00214: # if (M_MessageFormat_IsUseStdString == 1)
00215: # pragma message ("-- stFormatMessage() etc. / std::string interface")
00216: # endif
00217: #endif
00218:
00219: //-------------------------------------------------------------------------
00220:
00221: // wxMessageFormatter/wxFormat/wxFormatMessage:
00222: // provide type-safe string formatting similar to printf
00223: // - parameters are added with the "%" operator
00224: // - format string refers to parameters with %N or %{N} (with N
00225: // being the N-th parameter added)
00226: // - "%+" may be used to refer to "next" parameter
00227: // Notes:
00228: // - Currently, type-safety may be breached by specifying wrong
00229: // printf-format strings to wxFormat objects, but this string
00230: // is usually changed by the programmer only (not internationalized)
00231: // (to do: add type-compatibility checks).
00232: // - This approach allows reordering of parameters in the output
00233: // which might be useful or even required when translating
00234: // messages into other languages.
00235: // - Unlike with the usual with C++-stream operators "<<",
00236: // the message string must not be split up into several sub-strings
00237: // which makes it all possibly better readable.
00238: // - wxFormat may be used to set up output precision as usual,
00239: // but for safety reasons currently this cannot be done in the
00240: // message format string (which might be edited by translators
00241: // externally)
00242: // - For the %N syntax, N must be a single digit. This means that
00243: // %23 prints parameter two, followed by the digit 'three'.
00244: // (%23 is identical to %{2}3). However, %{23} can be used to
00245: // refer parameter '23'.
00246: // It was opted to use this syntax because parameter numbers >= 10
00247: // are probably rarely used, so normally the %N syntax is sufficient.
00248: // - The idea of using the percent (%) operator has been borrowed
00249: // from boost::format which also provides printf-like formatting
00250: // in a type-safe manner, but heavily depends on C++-templates
00251: // - The "%+" syntax can also be used to ease conversion of printf
00252: // format strings: just replace all occurences of "%d", "%s" etc.
00253: // with "%+".
00254: // Possible improvements:
00255: // - avoid allocations of wxStrings by pre-calculating the resulting
00256: // string size and by using static buffers for intermediate
00257: // number output buffers
00258: // TODO
00259: // - test with older compilers if overloads work as expected, also test
00260: // with latest compilers
00261: // TESTED
00262: // - (wxExtLib 0.7.1:) GCC 2.95.2, MSVC 6, DMC 8.40, BCC 5.5.1
00263:
00264: // possible (thinkable) shorthands for wxFormat: "wxF", "_F", "F"
00265: // typedef wxFormat wxF;
00266:
00267: class M_Format
00268: {
00269: public:
00270: M_Format (int Integer);
00271: M_Format (const char * PrintfFormatString, int Integer);
00272: M_Format (unsigned int UInt);
00273: M_Format (const char * PrintfFormatString, unsigned int UInt);
00274: M_Format (long Long);
00275: M_Format (const char * PrintfFormatString, long Long);
00276: M_Format (unsigned long ULong);
00277: M_Format (const char * PrintfFormatString, unsigned long ULong);
00278: M_Format (const float & Float);
00279: M_Format (const char * PrintfFormatString, const float & Float);
00280: M_Format (const double & Double);
00281: M_Format (const char * PrintfFormatString, const double & Double);
00282: M_Format (const char * CharPtr);
00283: M_Format (const char * PrintfFormatString, const char * CharPtr);
00284: M_Format (const M_String & String);
00285: M_Format (const char * PrintfFormatString, const M_String & String);
00286: M_Format (char Char);
00287: M_Format (const char * PrintfFormatString, char Char);
00288: M_Format (unsigned char UChar);
00289: M_Format (const char * PrintfFormatString, unsigned char UChar);
00290: // TODO: add signed/unsigned overloads char-types,
00291: // wxDateTime (for current locale)
00292:
00293: virtual ~M_Format ();
00294:
00295: void init (const char * PrintfFormatString, int Integer);
00296: void init (const char * PrintfFormatString, unsigned int UInt);
00297: void init (const char * PrintfFormatString, long Long);
00298: void init (const char * PrintfFormatString, unsigned long ULong);
00299: void init (const char * PrintfFormatString, const double & Double);
00300: void init (const char * PrintfFormatString, const char * CharPtr);
00301: void init (const char * PrintfFormatString, const M_String & String);
00302: void init (const char * PrintfFormatString, char Char);
00303: void init (const char * PrintfFormatString, unsigned char UChar);
00304:
00305: // interface draft which might be used for optimization purposes:
00306: // virtual int getPrintCharCount () const;
00307: // virtual void printInto (wxString & String, int FirstPos, int Count) const;
00308: virtual void appendTo (M_String & String) const;
00309: // virtual M_String print ();
00310:
00311: private:
00312: M_String m_FormattedValueString;
00313: };
00314:
00315: class M_MessageFormatter;
00316:
00317: //-------------------------------------------------------------------------
00318:
00319: // helper functions to ease transition to use wxMessageFormatter
00320: // - Example:
00321: // use
00322: // wxFormatMessage ("TEXT %1 TEXT %2", Int, Double)
00323: // instead of
00324: // wxString::Format ("TEXT %d TEXT %f", Int, Double)
00325: //
00326: M_String M_FormatMessage (const char * FormatString);
00327: M_String M_FormatMessage (const char * FormatString, const M_Format & Param1Format);
00328: M_String M_FormatMessage (const char * FormatString,
00329: const M_Format & Param1Format,
00330: const M_Format & Param2Format);
00331: M_String M_FormatMessage (const char * FormatString,
00332: const M_Format & Param1Format,
00333: const M_Format & Param2Format,
00334: const M_Format & Param3Format);
00335: M_String M_FormatMessage (const char * FormatString,
00336: const M_Format & Param1Format,
00337: const M_Format & Param2Format,
00338: const M_Format & Param3Format,
00339: const M_Format & Param4Format);
00340: M_String M_FormatMessage (const char * FormatString,
00341: const M_Format & Param1Format,
00342: const M_Format & Param2Format,
00343: const M_Format & Param3Format,
00344: const M_Format & Param4Format,
00345: const M_Format & Param5Format);
00346: M_String M_FormatMessage (const char * FormatString,
00347: const M_Format & Param1Format,
00348: const M_Format & Param2Format,
00349: const M_Format & Param3Format,
00350: const M_Format & Param4Format,
00351: const M_Format & Param5Format,
00352: const M_Format & Param6Format);
00353: M_String M_FormatMessage (const char * FormatString,
00354: const M_Format & Param1Format,
00355: const M_Format & Param2Format,
00356: const M_Format & Param3Format,
00357: const M_Format & Param4Format,
00358: const M_Format & Param5Format,
00359: const M_Format & Param6Format,
00360: const M_Format & Param7Format);
00361: M_String M_FormatMessage (const char * FormatString,
00362: const M_Format & Param1Format,
00363: const M_Format & Param2Format,
00364: const M_Format & Param3Format,
00365: const M_Format & Param4Format,
00366: const M_Format & Param5Format,
00367: const M_Format & Param6Format,
00368: const M_Format & Param7Format,
00369: const M_Format & Param8Format);
00370: M_String M_FormatMessage (const char * FormatString,
00371: const M_Format & Param1Format,
00372: const M_Format & Param2Format,
00373: const M_Format & Param3Format,
00374: const M_Format & Param4Format,
00375: const M_Format & Param5Format,
00376: const M_Format & Param6Format,
00377: const M_Format & Param7Format,
00378: const M_Format & Param8Format,
00379: const M_Format & Param9Format);
00380: M_String M_FormatMessage (const char * FormatString,
00381: const M_Format & Param1Format,
00382: const M_Format & Param2Format,
00383: const M_Format & Param3Format,
00384: const M_Format & Param4Format,
00385: const M_Format & Param5Format,
00386: const M_Format & Param6Format,
00387: const M_Format & Param7Format,
00388: const M_Format & Param8Format,
00389: const M_Format & Param9Format,
00390: const M_Format & Param10Format);
00391: // add overloads with more parameters if required... (C++ language
00392: // syntactically doesn't support real variable-number arguments with
00393: // type-checks)
00394:
00395: //-------------------------------------------------------------------------
00396:
00397: #if (M_MessageFormat_IsUseWxString == 1)
00398: WX_DEFINE_ARRAY_PTR(M_Format *, M_FormatArray);
00399: #elif (defined M_MessageFormat_StdString)
00400: typedef std::vector<M_Format *> M_FormatArray;
00401: #else
00402: #error "unhandled/missing typedef for M_FormatArray"
00403: #endif
00404:
00405: //-------------------------------------------------------------------------
00406:
00407: // MessageFormatter will return a wxMessageFormatter object
00408: M_MessageFormatter M_makeMessageFormatter (const char * FormatString);
00409:
00410: // helper function
00411: M_String & operator+= (M_String & String, M_MessageFormatter & MessageFormatter);
00412:
00413: class M_MessageFormatter
00414: {
00415: public:
00416: M_MessageFormatter (const char * FormatString);
00417: ~M_MessageFormatter ();
00418:
00419: // TODO: add signed/unsigned overloads, overload for char-types,
00420: // wxDateTime
00421: #if 0
00422: // TEST these functions should not be required since
00423: // we have operator%(wxFormat & Format)
00424: M_MessageFormatter & operator% (int Integer);
00425: M_MessageFormatter & operator% (long Long);
00426: M_MessageFormatter & operator% (const double & Double);
00427: M_MessageFormatter & operator% (const char * CharPtr);
00428: M_MessageFormatter & operator% (const M_String & String);
00429: #endif
00430: // NOTE: maybe, the above overloads are not required since
00431: // wxFormat class constructor has also the required overloads - maybe
00432: // these functions even cause problems together with the overloads
00433: // in the wxFormat constructor on some compilers
00434: M_MessageFormatter & operator% (const M_Format & Format);
00435:
00436: // DEF the operator% and addFormat() taking a pointer to a
00437: // wxFormat object assume this object was allocated via 'new'
00438: // - this is intended to make it possible to use user defined
00439: // formatter classes (NOTE: wxFormatMessage() function
00440: // cannot simply use user-defined format objects)
00441: // - therefore, to output user-defined types, it may be better
00442: // to write a function that converts the user-defined-type
00443: // to string and returns an appropriate wxFormat object
00444: // (which then can be used as argument to both, wxFormatMessage()
00445: // and wxMessageFormatter::operator%())
00446: M_MessageFormatter & operator% (M_Format * FormatPtr);
00447: M_MessageFormatter & addFormat (M_Format * FormatPtr);
00448:
00449: // format() does the formatting work
00450: void format ();
00451:
00452: // format string and return reference to it:
00453: const M_String & getRef ();
00454: operator const M_String & ();
00455: operator const char *();
00456:
00457: // format string and return result or append result to other string
00458: void appendTo (M_String & String);
00459: void assignTo (M_String & String);
00460:
00461: protected:
00462: M_String m_FormatString;
00463: M_FormatArray m_FormatArray;
00464:
00465: M_String m_OutputString;
00466: };
00467:
00468: //-------------------------------------------------------------------------
00469:
00470: #endif // if(defined M_MessageFormat_IsEmitDeclarations)
00471:
00472: //=========================================================================
00473:
00474: #endif /* M_MessageFormat_IsUseStxFormatMessage */
00475:
00476: //=========================================================================
00477:
00478: