[gparted] Update String::ucompose library to version 1.0.5



commit a739afc9a1d1d94a8c95446db762db93cff15572
Author: Curtis Gedak <gedakc gmail com>
Date:   Mon Sep 26 16:44:04 2011 -0600

    Update String::ucompose library to version 1.0.5

 compose/README         |    9 +-
 compose/README.compose |  342 ++++++++++++++++++++++++++++++++++++++++++++++++
 compose/ucompose.hpp   |   20 ++-
 3 files changed, 359 insertions(+), 12 deletions(-)
---
diff --git a/compose/README b/compose/README
index 509c1ee..98b6668 100644
--- a/compose/README
+++ b/compose/README
@@ -3,18 +3,17 @@ composition of strings with Gtkmm >= 1.3.* (see www.gtkmm.org).
 Uses Glib::ustring instead of std::string which doesn't work with
 Gtkmm due to character encoding troubles with stringstreams.
 
-Version 1.0.4.
+Version 1.0.5.
 
-Copyright (c) 2002, 03, 04 Ole Laursen <olau hardworking dk>.
+Copyright (c) 2002, 03, 04, 07 Ole Laursen <olau hardworking dk>.
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public License
 as published by the Free Software Foundation; either version 2.1 of
 the License, or (at your option) any later version.
 
-       
+
 Basic usage is like:
 String::ucompose("This is a %1x%2 matrix.", rows, cols);
 
-See http://www.cs.auc.dk/~olau/compose for more details.
-		       
+See http://people.iola.dk/olau/compose/ for more details.
diff --git a/compose/README.compose b/compose/README.compose
new file mode 100644
index 0000000..4946352
--- /dev/null
+++ b/compose/README.compose
@@ -0,0 +1,342 @@
+Documentation for the compose library
+-------------------------------------
+
+The file compose.hpp contains the source for a small C++ library for
+composition of strings from arbitrary objects convertible to strings
+(such as integers, floats etc.). This is the documentation for that
+library. The utility of the library is thought to be greatest for
+programmers needing translation of their programs, but in fact it can
+be used for its mere convenience.
+
+The file ucompose.hpp has a front-end that uses Glib::ustrings which
+come from the C++ GUI library Gtkmm (see www.gtkmm.org). Use
+ucompose.hpp and String::ucompose if you are using Gtkmm - else your
+ustrings will end up corrupted someday.
+
+
+The initiating problem - a prelude
+----------------------------------
+
+The basic problem this library solves is that of creating strings such
+as "Fact is that 10 gobbles are worth 100$ of troubles." where the two
+numbers, 10 and 100, are to be determined at runtime and may vary. C++
+doesn't have a good solution for this problem - unless you use
+something like itoa() (which isn't really portable and doesn't work
+for arbitrary objects, say GobbliGobs, that define their own
+conversion routines by overloading "ostream & operator<<(ostream &,
+Object)"), the best option you have is to aggregate an ostringstream:
+
+  std::ostringstream os;
+  os << gobble_no;
+  std::string gobble_no_as_string = os.str();
+
+But even Bjarne Stroustrup thinks this is embarrassing for ordinary
+integer-to-string conversion. The Boost family of libraries (see
+www.boost.org) defines a lexical_cast<T>() which one may use to
+conveniently compose a complex string (in fact it uses a stringstream
+internally):
+
+  #include <boost/lexical_cast.hpp>
+
+  std::string s = "Fact is that " + boost::lexical_cast<std::string>(gobble_no)
+                  + " gobbles are worth "
+                  + boost::lexical_cast<std::string>(gobble_price)
+                  + "$ of troubles.";
+
+However, this is prone to subtle errors when written (one may easily
+forget a '+' or a space on one side of a converted object, both
+annoyingly requiring recompilation and attention), hard to read, and a
+real internationalisation killer. Imagine translating the strings
+
+  "Fact is that "
+
+  " gobbles are worth "
+
+  "$ of troubles."
+
+not quite sure whether the strings actually form an entity and with
+only fragmented clues of what is inserted between them. What is worse,
+most languages do not order the different parts of sentences the same
+way English does. And by chopping up the string, we have more or less
+enforced a particular order (or at least made the changing of it most
+difficult for the translator). Also, one now has to mark up three
+strings in the program to get one string translated - another source
+of errors.
+
+Furthermore, the lexical cast of Boost doesn't allow us to control
+even simple formatting requests, such as increased (or, often more
+importantly, decreased) precision of floating point numbers.
+
+
+Interlude: The Solution that isn't really a Solution
+----------------------------------------------------
+
+So, one might think, isn't this string composition problem already
+solved? Does our inheritage from C not already provide us with the
+solution, the end to all these troubles? Upon thinking this, one
+probably has the dreaded printf, "print formatted", family in mind.
+
+Except from the type insecurity resulting from usage of such
+functions, a problem already partly solved by modern compiler
+warnings, suffice to say that they mix badly with ordinary C++ style
+of programming. For good reason, they don't return proper
+std::string's and usually even require one to worry about memory
+management. Needless worries.
+
+
+Finale: An end to the problem
+-----------------------------
+
+So what we need really need is something like
+
+  std::string s = compose("Fact is that %1 gobbles are worth %2$ of troubles.",
+                          gobble_no, gobble_price);
+
+This is what this library gives.
+
+
+Semantics in details (...and there was much rejoice)
+----------------------------------------------------
+
+Actually, what the library really gives is 15 overloaded template
+functions like
+
+  template <typename T1, typename T2>
+  inline std::string compose(const std::string &fmt,
+			     const T1 &o1, const T2 &o2);
+
+declared in the namespace String - each allowing one extra parameter
+to join the composition - and some implementation details in the
+namespace StringPrivate (notably a class that defines a generic,
+unlimited parameter substitution mechanism).
+
+The first parameter is the format string containing percent
+specifications (%1, %2 etc.) and the following generically typed
+parameters are the objects to be inserted in the string. The 15
+functions allow up to 15 parameters to be inserted. For instance:
+
+  String::compose("%1 times %2 equals %3", 1.5, 2, 3);
+
+  // "1.5 times 2 equals 3"
+  
+A percent specification consists of a percent sign followed by an
+integer. The format string is parsed at first so any possible new
+percent specifications that may be constructed halfway through the
+composition by the inserted strings, aren't interpreted as such:
+
+  String::compose("1st: %1  2nd: %2", "%2", 1234);
+
+  // "1st: %2  2nd: 1234"
+
+Of course, this format allows one to easily swap the specification
+strings:
+
+  String::compose("No. %2 is better than no. %1", 1, 2);
+
+  // "No. 2 is better than no. 1"
+
+One may silently leave out a specification string:
+
+  String::compose("%1, %3", "Hey", "hi", "ho");
+
+  // "Hey, ho"
+
+Or even an object (all percent specifications are always erased):
+
+  String::compose("%1 %2: '%3'", "Twin", "geeks");
+
+  // "Twin geeks: ''"
+
+And specifications may be repeated:
+
+  String::compose("I am feeling so %1, %1, %1!", "happy");
+
+  // "I am feeling so happy, happy, happy!"
+
+This gives potential translators of the strings considerable freedom.
+
+
+Conversion of objects, the art of
+----------------------------------
+
+Internally the template functions use an object that stores a
+stringstream for converting arguments. Thus adding an extra parameter
+to the compose function is very much like appending an extra "<< arg"
+to a stream output statement.
+
+This implies seamless support for manipulators and that user-supplied
+conversions are supported for free. To add output support for one of
+your own classes, simply add the appropriate operator<< overload, just
+as you would for std::cout:
+
+  ostream &operator<<(ostream &, const MyType &my_obj)
+  {
+    // ...
+  }
+
+The manipulator support imply that constructions like the following
+are possible:
+
+  #include <iomanip>
+  // ...
+
+  double r = 1.0 / 6;
+  String::compose("1/6 app. equals %1, %2, and %3", r, 
+                   std::setprecision(10), r, 
+                   std::setprecision(3), r);
+
+  // "1/6 app. equals 0.166667, 0.1666666667, and 0.167"
+
+Note that within the same call of compose the stringstream is not
+cleared, so the same rules governs whether the settings are remembered
+as for ordinary ostreams (look up the rules in your favourite C++
+standard iostream documentation):
+
+  String::compose("1/6 app. equals %1, %2, and %3", r, 
+                   std::setprecision(10), r, r);
+
+  // "1/6 app. equals 0.166667, 0.1666666667, and 0.1666666667"
+
+Each call of compose constructs a new stringstream so settings are not
+preserved across these.
+
+Internally, the manipulator detection works by examining the output
+from the stringstream - if it is empty, then the parameter is not
+considered real output, and the specification number is not
+incremented. This behaviour is needed to give the above semantics, but
+it also implies that if your insert the empty string, "", the compose
+object will not consider it output; as a consequence the following
+example does not work as expected:
+
+  String::compose("I'm a%1 alien at the age of %2.",
+                   happiness > 10 ? " happy" : "", 99800);
+
+  // "I'm a happy alien at the age of 99800."
+  // "I'm a99800 alien at the age of ."
+
+But read below for why you really should not do this anyway, and for
+the simple remedy.
+
+
+Escaping the parse
+------------------
+
+All double percent signs are replaced with a single sign; if the
+double signs appears in front of an integer, the resulting single
+percent sign followed by the integer isn't considered a specification.
+Thus, to get a percent specification:
+
+  String::compose("This is a %1: %%1", "specification");
+
+  // "This is a specification: %1"
+
+Single percent signs are left untouched in case they aren't followed
+by a number:
+
+  String::compose("%1% done", 0.98 * 100);
+
+  // "98% done"
+
+To get two percent signs in a row:
+
+  String::compose("%1 %2 signs: %%%%", 2, '%');
+
+  // "2 % signs: %%"
+
+
+A final advice against cleverness
+---------------------------------
+
+Do not let the techniques this library offers tempt you into trying
+overly clever string compositions, or the translators of your program
+will curse you in eternity! For instance:
+
+  String::compose("A%1 man", man.is_angry() ? "n angry" : " content");
+
+  // "An angry man"
+  // "A happy man"
+
+The inherent problem with this approach is that it hardcodes the way
+the sentence is constructed; obviously this is only guaranteed to work
+for English. It also makes the code harder to read. Instead, fork the
+code on a slightly higher level and repeat the whole string:
+
+  std::string description;
+  
+  if (man.is_angry())
+    description = String::compose("An angry man");
+  else
+    description = String::compose("A content man");
+
+Now the code is also much easier to read. This (slightly contrived,
+but realistic, I have seen it in real code) example is of course quite
+easy to spot, but in generel one needs to be very careful as soon as
+one substitute strings into ordinary text. One more example:
+
+  String::compose("This is a %1", thing->got_wheels() ? "car" : "house");
+
+Innocent looking, but absolutely wrong. Most languages will need to
+change the part "a " of the string too (e.g. in Danish it is "en bil"
+(a car) but "et hus" (a house)).
+
+Completely decoupled words should of course not cause any problems:
+
+  String::compose("The XML error was caused by the element '%1'", 
+                  element.name);
+
+In fact, factoring out the common part of such strings (e.g. putting
+it in a xml_error function) may be much of a convenience for the
+translators.
+
+Often, you would want to use constructions such as the above ones when
+some part of the string sometime needs to be in plural form:
+
+  String::compose("There is a total of %1 %2.", n, n == 1 ? "hen" : "hens");
+
+But do not do this - for some languages, a two-way branch isn't
+enough. Instead the translation system should have some means of
+solving this (for gettext, look up the function 'ngettext').
+
+  
+Practically speaking, the art of improvement
+--------------------------------------------
+
+The latest, super-duper-improved (hah!) version of the library should
+always be available together with a small test example from
+
+  http://www.cs.aau.dk/~olau/compose/
+
+Note that the license of the library is GNU Lesser General Public
+License. For the uninitiated, this basically means that you may use
+the library freely in any way you want, but if you change any of the
+code of it and distribute it in binary form, you _must_ also release
+the source for the modified library under the LGPL. Thus you must
+share your improvements with the rest of the world, just like I shared
+my code with you. No big deal. If you have any comments, suggestions
+for improvements, critics, (good) jokes, portability fixes,
+interesting uses, or perhaps just a word of wisdom, let me know.
+
+Ole Laursen <olau hardworking dk>, 2003.
+
+
+A short historical anecdote - postlude
+--------------------------------------
+
+One might think that the name of the namespace "String::" is pretty
+lame; and, indeed, I agree. However, the library was initially born
+because the Gtkmm family of libraries doesn't help with composition of
+strings and e.g. integers in a way so that the placement of the
+integers is decoupled from the conversion to strings; a procedure that
+is frequently badly needed in a GUI-intensitive program.
+
+So when I got the idea of using a stringstream together with a
+template member function, I promptly implemented the Composition class
+(defined in the StringPrivate namespace). But, alas, the functionality
+isn't conceived to be important enough for Gtkmm users to be put into
+Glibmm (a support library for Gtkmm that contains various helpers), so
+instead I'm placing it here. Unfortunately, this left me without a
+proper namespace (formerly "Glib::") to wrap the functionality in -
+thus the current "String::".
+
+My apologies. Maybe the situation will change one day. Suggestions are
+welcome.
diff --git a/compose/ucompose.hpp b/compose/ucompose.hpp
index fbdc269..e5f1cfc 100644
--- a/compose/ucompose.hpp
+++ b/compose/ucompose.hpp
@@ -3,9 +3,9 @@
  * Uses Glib::ustring instead of std::string which doesn't work with
  * Gtkmm due to character encoding troubles with stringstreams.
  *
- * Version 1.0.4.
+ * Version 1.0.5.
  *
- * Copyright (c) 2002, 03, 04 Ole Laursen <olau hardworking dk>.
+ * Copyright (c) 2002, 03, 04, 07 Ole Laursen <olau hardworking dk>.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -28,7 +28,7 @@
 //
 //   String::ucompose("This is a %1x%2 matrix.", rows, cols);
 //
-// See http://www.cs.aau.dk/~olau/compose/ or the included
+// See http://people.iola.dk/olau/compose/ or the included
 // README.compose for more details.
 //
 
@@ -124,7 +124,7 @@ namespace UStringPrivate
     os << obj;
 
     std::wstring str = os.str();
-   
+    
     return Glib::convert(std::string(reinterpret_cast<const char *>(str.data()),
 				     str.size() * sizeof(wchar_t)),
 			 "UTF-8", "WCHAR_T");
@@ -151,13 +151,20 @@ namespace UStringPrivate
   {
     return obj;
   }
+
+  template <>
+  inline std::string
+  Composition::stringify<char *>(char *obj)
+  {
+    return obj;
+  }
   
   // implementation of class Composition
   template <typename T>
   inline Composition &Composition::arg(const T &obj)
   {
     Glib::ustring rep = stringify(obj);
-  
+    
     if (!rep.empty()) {		// manipulators don't produce output
       for (specification_map::const_iterator i = specs.lower_bound(arg_no),
 	     end = specs.upper_bound(arg_no); i != end; ++i) {
@@ -179,8 +186,7 @@ namespace UStringPrivate
     : arg_no(1)
   {
 #if __GNUC__ >= 3
-	  //see #157871
-	//os.imbue(std::locale("")); // use the user's locale for the stream
+    os.imbue(std::locale("")); // use the user's locale for the stream
 #endif
     std::string::size_type b = 0, i = 0;
   



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]