library of assembled shared sources

http://lass.cocamware.com

extended_io.inl

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 #include <cctype>
00044 #include "extended_string.h"
00045 
00046 // --- implemenation details -----------------------------------------------------------------------
00047 
00048 namespace lass
00049 {
00050 namespace stde
00051 {
00052 namespace impl
00053 {
00054 
00055 /** @ingroup extended_io
00056  *  @internal
00057  */
00058 template <typename Char, typename Traits>
00059 void eat_whitespace(std::basic_istream<Char, Traits>& stream)
00060 {
00061     Char c = 0;
00062     while (stream.get(c))
00063     {
00064         if (!std::isspace(c))
00065         {
00066             stream.putback(c);
00067             break;
00068         }
00069     }
00070 }
00071 
00072 /** @ingroup extended_io
00073  *  @internal
00074  */
00075 struct sequence_traits
00076 {
00077     template <typename Container, typename T>
00078     static void push(Container& container, const T& value)
00079     {
00080         container.push_back(value);
00081     }
00082     template <typename Container>
00083     static void temp_to_output(Container& temp, Container& output)
00084     {
00085         temp.swap(output);
00086     }
00087 };
00088 
00089 /** @ingroup extended_io
00090  *  @internal
00091  */
00092 struct set_traits
00093 {
00094     template <typename Container, typename T>
00095     static void push(Container& container, const T& value)
00096     {
00097         container.insert(value);
00098     }
00099     template <typename Container>
00100     static void temp_to_output(Container& temp, Container& output)
00101     {
00102         temp.swap(output);
00103     }
00104 };
00105 
00106 /** @ingroup extended_io
00107  *  @internal
00108  *  @note may change value on failure, but that's ok since it's a temp of the caller.
00109  */
00110 struct value_traits
00111 {
00112     template <typename Char, typename Traits, typename T>
00113     static bool read(
00114             std::basic_istream<Char, Traits>& stream, T& value,
00115             Char inter_seperator, Char /*intra_seperator*/, Char closer)
00116     {
00117         eat_whitespace(stream);
00118 
00119         // read till next seperator
00120         //
00121         std::basic_string<Char, Traits> buffer;
00122         Char c = 0;
00123         while (stream.get(c))
00124         {
00125             if (c == inter_seperator || c == closer)
00126             {
00127                 stream.putback(c);
00128                 break;
00129             }
00130             buffer += c;
00131         }
00132 
00133         // convert
00134         //
00135         return cast(buffer, value);
00136 
00137     }
00138 private:
00139     static bool cast(const std::string& buffer, std::string& value)
00140     {
00141         value = rstrip(buffer);
00142         return true;
00143     }
00144     template <typename T>
00145     static bool cast(const std::string& buffer, T& value)
00146     {
00147         std::stringstream buffer_stream(buffer);
00148         if (std::numeric_limits<T>::is_specialized)
00149         {
00150             buffer_stream.precision(std::numeric_limits<T>::digits10 + 1);
00151         }
00152         return buffer_stream >> value && (buffer_stream >> std::ws).eof();
00153     }
00154 };
00155 
00156 /** @ingroup extended_io
00157  *  @internal
00158  *  @note may change value on failure, but that's ok since it's a temp of the caller.
00159  */
00160 struct pair_traits
00161 {
00162     template <typename Char, typename Traits, typename T, typename U>
00163     static bool read(
00164             std::basic_istream<Char, Traits>& stream, std::pair<T, U>& value,
00165             Char inter_seperator, Char intra_seperator, Char closer)
00166     {
00167         if (!value_traits::read<Char>(stream, value.first, intra_seperator, 0, intra_seperator))
00168         {
00169             return false;
00170         }
00171         stream.ignore();
00172         if (!value_traits::read<Char>(stream, value.second, inter_seperator, 0, closer))
00173         {
00174             return false;
00175         }
00176         return true;
00177     }
00178 };
00179 
00180 /** @ingroup extended_io
00181  *  @internal
00182  */
00183 template <typename Iterator, typename Char, typename Traits>
00184 std::basic_ostream<Char, Traits>& print_sequence(
00185         std::basic_ostream<Char, Traits>& stream, Iterator begin, Iterator end,
00186         const Char* opener, const Char* seperator, const Char* closer)
00187 {
00188     std::basic_ostringstream<Char, Traits> buffer;
00189     buffer.copyfmt(stream);
00190     buffer.width(0);
00191 
00192     buffer << opener;
00193     for (Iterator i = begin; i != end; ++i)
00194     {
00195         if (i != begin)
00196         {
00197             buffer << seperator;
00198         }
00199         buffer << *i;
00200     }
00201     buffer << closer;
00202 
00203     LASS_ENFORCE_STREAM(stream) << buffer.str();
00204     return stream;
00205 }
00206 
00207 /** @ingroup extended_io
00208  *  @internal
00209  */
00210 template <typename Char, typename Traits, typename Iterator>
00211 std::basic_ostream<Char, Traits>& print_map(
00212         std::basic_ostream<Char, Traits>& stream, Iterator begin, Iterator end,
00213         const Char* opener, const Char* seperator_1, const Char* seperator_2, const Char* closer)
00214 {
00215     std::basic_ostringstream<Char, Traits> buffer;
00216     buffer.copyfmt(stream);
00217     buffer.width(0);
00218 
00219     buffer << opener;
00220     for (Iterator i = begin; i != end; ++i)
00221     {
00222         if (i != begin)
00223         {
00224             buffer << seperator_1;
00225         }
00226         buffer << i->first << seperator_2 << i->second;
00227     }
00228     buffer << closer;
00229 
00230     LASS_ENFORCE_STREAM(stream) << buffer.str();
00231     return stream;
00232 }
00233 
00234 /** @ingroup extended_io
00235  *  @internal
00236  */
00237 template
00238 <
00239     typename ContainerTraits, typename DataTraits, typename T,
00240     typename Char, typename Traits,
00241     typename Container
00242 >
00243 std::basic_istream<Char, Traits>& read_container(
00244         std::basic_istream<Char, Traits>& stream, Container& container,
00245         Char opener, Char inter_seperator, Char intra_seperator, Char closer)
00246 {
00247     Container result;
00248 
00249     bool good = true;
00250     Char c = 0;
00251     eat_whitespace(stream);
00252     if (stream.get(c))
00253     {
00254         if (c == opener)
00255         {
00256             T temp;
00257             good = DataTraits::read(stream, temp, inter_seperator, intra_seperator, closer);
00258             if (good)
00259             {
00260                 ContainerTraits::push(result, temp);
00261             }
00262         }
00263         else
00264         {
00265             stream.putback(c);
00266             good = false;
00267         }
00268     }
00269     else
00270     {
00271         good = false;
00272     }
00273 
00274     while (good && stream.get(c) && c != closer)
00275     {
00276         if (c == inter_seperator)
00277         {
00278             T temp;
00279             good = DataTraits::read(stream, temp, inter_seperator, intra_seperator, closer);
00280             if (good)
00281             {
00282                 ContainerTraits::push(result, temp);
00283             }
00284         }
00285         else
00286         {
00287             stream.putback(c);
00288             good = false;
00289         }
00290     }
00291 
00292     if (good)
00293     {
00294         ContainerTraits::temp_to_output(result, container);
00295     }
00296     else
00297     {
00298         stream.clear(std::ios::failbit);
00299     }
00300 
00301     return stream;
00302 }
00303 
00304 }
00305 
00306 }
00307 
00308 }
00309 
00310 // --- free ----------------------------------------------------------------------------------------
00311 
00312 namespace std
00313 {
00314 
00315 // output
00316 
00317 /** @ingroup extended_io
00318  */
00319 template <typename T1, typename T2, typename Char, typename Traits>
00320 std::basic_ostream<Char, Traits>& operator<<(
00321         std::basic_ostream<Char, Traits>& stream, const std::pair<T1, T2>& x)
00322 {
00323     std::basic_ostringstream<Char, Traits> buffer;
00324     buffer.copyfmt(stream);
00325     buffer.width(0);
00326     buffer << "(" << x.first << ", " << x.second << ")";
00327     LASS_ENFORCE_STREAM(stream) << buffer.str();
00328     return stream;
00329 }
00330 
00331 /** @ingroup extended_io
00332  */
00333 template <typename T, typename Alloc, typename Char, typename Traits>
00334 std::basic_ostream<Char, Traits>& operator<<(
00335         std::basic_ostream<Char, Traits>& stream, const std::vector<T, Alloc>& container)
00336 {
00337     return lass::stde::impl::print_sequence(
00338         stream, container.begin(), container.end(), "[", ", ", "]");
00339 }
00340 
00341 /** @ingroup extended_io
00342  */
00343 template <typename T, typename Alloc, typename Char, typename Traits>
00344 std::basic_ostream<Char, Traits>& operator<<(
00345         std::basic_ostream<Char, Traits>& stream, const std::list<T, Alloc>& container)
00346 {
00347     return lass::stde::impl::print_sequence(
00348         stream, container.begin(), container.end(), "[", ", ", "]");
00349 }
00350 
00351 /** @ingroup extended_io
00352  */
00353 template <typename T, typename Alloc, typename Char, typename Traits>
00354 std::basic_ostream<Char, Traits>& operator<<(
00355         std::basic_ostream<Char, Traits>& stream, const std::deque<T, Alloc>& container)
00356 {
00357     return lass::stde::impl::print_sequence(
00358         stream, container.begin(), container.end(), "[", ", ", "]");
00359 }
00360 
00361 /** @ingroup extended_io
00362  */
00363 template <typename Key, typename Data, typename Comp, typename Alloc, typename Char, typename Traits>
00364 std::basic_ostream<Char, Traits>& operator<<(
00365         std::basic_ostream<Char, Traits>& stream,
00366         const std::map<Key, Data, Comp, Alloc>& container)
00367 {
00368     return lass::stde::impl::print_map<Char>(
00369         stream, container.begin(), container.end(), "{", ", ", ": ", "}");
00370 }
00371 
00372 /** @ingroup extended_io
00373  */
00374 template <typename Key, typename Data, typename Comp, typename Alloc, typename Char, typename Traits>
00375 std::basic_ostream<Char, Traits>& operator<<(
00376         std::basic_ostream<Char, Traits>& stream,
00377         const std::multimap<Key, Data, Comp, Alloc>& container)
00378 {
00379     return lass::stde::impl::print_map<Char>(
00380         stream, container.begin(), container.end(), "{", ", ", ": ", "}");
00381 }
00382 
00383 /** @ingroup extended_io
00384  */
00385 template <typename Key, typename Comp, typename Alloc, typename Char, typename Traits>
00386 std::basic_ostream<Char, Traits>& operator<<(
00387         std::basic_ostream<Char, Traits>& stream, 
00388         const std::set<Key, Comp, Alloc>& container)
00389 {
00390     return lass::stde::impl::print_sequence(
00391         stream, container.begin(), container.end(), "{", ", ", "}");
00392 }
00393 
00394 /** @ingroup extended_io
00395  */
00396 template <typename Key, typename Comp, typename Alloc, typename Char, typename Traits>
00397 std::basic_ostream<Char, Traits>& operator<<(
00398         std::basic_ostream<Char, Traits>& stream,
00399         const std::multiset<Key, Comp, Alloc>& container)
00400 {
00401     return lass::stde::impl::print_sequence(
00402         stream, container.begin(), container.end(), "{", ", ", "}");
00403 }
00404 
00405 
00406 
00407 // input
00408 
00409 /** @ingroup extended_io
00410  */
00411 template <typename Char, typename Traits, typename T1, typename T2>
00412 std::basic_istream<Char, Traits>& operator>>(
00413         std::basic_istream<Char, Traits>& stream, std::pair<T1, T2>& x)
00414 {
00415     using namespace lass::stde;
00416 
00417     Char c = 0;
00418     if (stream.get(c))
00419     {
00420         if (c == '(')
00421         {
00422             std::pair<T1, T2> temp;
00423             if (impl::pair_traits::read<Char>(stream, temp, ')', ',', ')'))
00424             {
00425                 x = temp;
00426                 stream.ignore();
00427             }
00428         }
00429         else
00430         {
00431             stream.putback(c);
00432             stream.clear(std::ios::failbit);
00433         }
00434     }
00435     else
00436     {
00437         stream.clear(std::ios::failbit);
00438     }
00439 
00440     return stream;
00441 }
00442 
00443 
00444 
00445 /** @ingroup extended_io
00446  */
00447 template <typename Char, typename Traits, typename T, typename Alloc>
00448 std::basic_istream<Char, Traits>& operator>>(
00449         std::basic_istream<Char, Traits>& stream, std::vector<T, Alloc>& container)
00450 {
00451     return ::lass::stde::impl::read_container<
00452 		::lass::stde::impl::sequence_traits, 
00453 		::lass::stde::impl::value_traits, 
00454         T, Char>(
00455             stream, container, '[', ',', 0, ']');
00456 }
00457 
00458 
00459 
00460 /** @ingroup extended_io
00461  */
00462 template <typename Char, typename Traits, typename T, typename Alloc>
00463 std::basic_istream<Char, Traits>& operator>>(
00464         std::basic_istream<Char, Traits>& stream, std::list<T, Alloc>& container)
00465 {
00466     return ::lass::stde::impl::read_container<
00467 		::lass::stde::impl::sequence_traits, 
00468 		::lass::stde::impl::value_traits,
00469         T, Char>(
00470             stream, container, '[', ',', 0, ']');
00471 }
00472 
00473 
00474 
00475 /** @ingroup extended_io
00476  */
00477 template <typename Char, typename Traits, typename T, typename Alloc>
00478 std::basic_istream<Char, Traits>& operator>>(
00479         std::basic_istream<Char, Traits>& stream, std::deque<T, Alloc>& container)
00480 {
00481     return ::lass::stde::impl::read_container<
00482 		::lass::stde::impl::sequence_traits, 
00483 		::lass::stde::impl::value_traits, 
00484         T, Char>(
00485             stream, container, '[', ',', 0, ']');
00486 }
00487 
00488 
00489 
00490 /** @ingroup extended_io
00491  */
00492 template <typename Char, typename Traits, typename Key, typename Data, typename Comp, typename Alloc>
00493 std::basic_istream<Char, Traits>& operator>>(
00494         std::basic_istream<Char, Traits>& stream, std::map<Key, Data, Comp, Alloc>& container)
00495 {
00496     return ::lass::stde::impl::read_container<
00497 		::lass::stde::impl::set_traits, 
00498 		::lass::stde::impl::pair_traits, 
00499         std::pair<Key, Data>, Char>(
00500             stream, container, '{', ',', ':', '}');
00501 }
00502 
00503 
00504 
00505 /** @ingroup extended_io
00506  */
00507 template <typename Char, typename Traits, typename Key, typename Data, typename Comp, typename Alloc>
00508 std::basic_istream<Char, Traits>& operator>>(
00509         std::basic_istream<Char, Traits>& stream,
00510         std::multimap<Key, Data, Comp, Alloc>& container)
00511 {
00512     return ::lass::stde::impl::read_container<
00513 		::lass::stde::impl::set_traits, 
00514 		::lass::stde::impl::pair_traits, 
00515         std::pair<Key, Data>, Char>(
00516             stream, container, '{', ',', ':', '}');
00517 }
00518 
00519 
00520 
00521 /** @ingroup extended_io
00522  */
00523 template <typename Char, typename Traits, typename Key, typename Comp, typename Alloc>
00524 std::basic_istream<Char, Traits>& operator>>(
00525         std::basic_istream<Char, Traits>& stream, std::set<Key, Comp, Alloc>& container)
00526 {
00527     return ::lass::stde::impl::read_container<
00528 		::lass::stde::impl::set_traits, 
00529 		::lass::stde::impl::value_traits, 
00530         Key, Char>(
00531             stream, container, '{', ',', 0, '}');
00532 }
00533 
00534 
00535 
00536 /** @ingroup extended_io
00537  */
00538 template <typename Char, typename Traits, typename Key, typename Comp, typename Alloc>
00539 std::basic_istream<Char, Traits>& operator>>(
00540         std::basic_istream<Char, Traits>& stream, std::multiset<Key, Comp, Alloc>& container)
00541 {
00542     return ::lass::stde::impl::read_container<
00543 		::lass::stde::impl::set_traits, 
00544 		::lass::stde::impl::value_traits, 
00545         Key, Char>(
00546             stream, container, '{', ',', 0, '}');
00547 }
00548 
00549 
00550 
00551 }
00552 
00553 // EOF

Generated on Mon Nov 10 14:20:04 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo