| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed |
| with this work for additional information regarding copyright |
| ownership. The ASF licenses this file to you under the Apache |
| License, Version 2.0 (the License); you may not use this file |
| except in compliance with the License. You may obtain a copy of |
| the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| implied. See the License for the specific language governing |
| permissions and limitations under the License. |
| |
| Copyright 1999-2007 Rogue Wave Software, Inc. |
| --> |
| |
| <HTML> |
| <HEAD> |
| <TITLE>Another Look at the Date Format String</TITLE> |
| <LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD> |
| <BODY BGCOLOR=#FFFFFF> |
| <A HREF="36-2.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="36-4.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library User's Guide</B></DIV> |
| <H2>36.3 Another Look at the Date Format String</H2> |
| <A NAME="idx891"><!></A> |
| <P>We would like to store the date format string in the iostream storage through <SAMP>std::ios_base::iword()</SAMP> and <SAMP>std::ios_base::pword()</SAMP>. In this way, the input and output operations for <SAMP>date</SAMP> objects can access the format string for parsing and formatting. Format parameters are often set with manipulators (see <A HREF="28-3.html#2832">Section 28.3.2</A>), so we should add a manipulator that sets the date format string. It could be used like this:</P> |
| |
| <UL><PRE> |
| date today; |
| std::ofstream ostr; |
| // ... |
| ostr << setfmt("%D") << today; |
| </PRE></UL> |
| <A NAME="idx892"><!></A> |
| <P>Here is a suggested implementation for such a manipulator (note that the name of the base class is implementation-defined):</P> |
| |
| <UL><PRE> |
| class setfmt : public <I>smanip</I><const char*> |
| { |
| public: |
| setfmt(const char* fmt) |
| : <I>smanip</I><const char*>(setfmt_,fmt) {} |
| private: |
| static const int datfmtIdx; //1 |
| |
| static std::ios_base& setfmt_(std::ios_base& str, |
| const char* fmt) |
| { |
| str.pword(datfmtIdx) = const_cast<char*> (fmt); //2 |
| return str; |
| } |
| |
| template<class charT, class Traits> |
| friend std::basic_ostream<charT, Traits>& //3 |
| operator<<(basic_ostream<charT, Traits>& os, |
| const date& dat); |
| }; |
| |
| const int setfmt::datfmtIdx = std::ios_base::xalloc(); //4 |
| </PRE></UL> |
| <A NAME="idx893"><!></A> |
| <P>The technique applied to implement the manipulator is described in detail in Example 2 of <A HREF="33-3.html">Section 33.3</A>, so we won't repeat it here. But regarding this manipulator and the private use of iostream storage, there are other interesting details:</P> |
| <TABLE CELLPADDING="3"> |
| |
| <TR VALIGN="top"><TD><SAMP>//1</SAMP></TD><TD>The manipulator class owns the index of the element in the iostream storage where we want to store the format string. It is initialized in <SAMP>//4</SAMP> by a call to <SAMP>xalloc()</SAMP>. |
| <TR VALIGN="top"><TD><SAMP>//2</SAMP></TD><TD>The manipulator accesses the array <SAMP>pword()</SAMP> using the index <SAMP>datfmtIdx</SAMP>, and stores the pointer to the date format string. [For brevity, error handling is omitted in the example. If allocation fails, then <SAMP>std::ios_base::badbit</SAMP> is set.] Note that the reference returned by <SAMP>pword()</SAMP> is only used for <I>storing</I> the pointer to the date format string. Generally, you should never store a reference returned by <SAMP>iword()</SAMP> or <SAMP>pword()</SAMP> in order to access the stored data through this reference later on. This is because these references can become invalid once the array is reallocated or copied. (See the <A HREF="../stdlibref/noframes.html"><I>Apache C++ Standard Library Reference Guide</I></A> for more details.) |
| <TR VALIGN="top"><TD><SAMP>//3</SAMP></TD><TD>The inserter for <SAMP>date</SAMP> objects needs to access the index into the array of pointers, so that it can read the format string and use it. Therefore, the inserter must be declared as a friend. In principle, the extractor must be a friend, too; however, the standard C++ locale falls short of supporting the use of format strings like the ones used by the standard C function <SAMP>strptime()</SAMP>. Hence, the implementation of a date extractor that supports date format strings would be a lot more complicated than the implementation for the inserter, which can use the stream's locale. We have omitted the extractor for the sake of brevity. |
| <TR VALIGN="top"><TD><SAMP>//4</SAMP></TD><TD>Initializes the index of elements in istream storage where the format string is kept. |
| </TABLE> |
| <A NAME="idx894"><!></A> |
| <P>The inserter for <SAMP>date</SAMP> objects given below is almost identical to the one we described in <A HREF="32-5.html#3251">Section 32.5.1</A>:</P> |
| |
| <UL><PRE> |
| template<class charT, class Traits> |
| std::basic_ostream<charT, Traits> & |
| operator << (std::basic_ostream<charT, Traits >& os, |
| const date& dat) |
| { |
| std::ios_base::iostate err = 0; |
| charT* fmt = 0; |
| |
| try { |
| typename std::basic_ostream<charT, Traits>::sentry opfx(os); |
| |
| if(opfx) |
| { |
| char* patt = static_cast<char*> |
| (os.pword(setfmt.datfmtIdx); //1 |
| std::size_t len = std::strlen(patt); |
| fmt = new charT[len]; |
| |
| std::use_facet<std::ctype<charT> >(os.getloc()). |
| widen(patt, patt+len, fmt); |
| |
| if (std::use_facet<std::time_put<charT, |
| std::ostreambuf_iterator<charT,Traits> > > |
| (os.getloc()) |
| .put(os,os,os.fill(),&dat.tm_date,fmt,fmt+len) //2 |
| .failed() |
| ) |
| err = std::ios_base::badbit; |
| os.width(0); |
| } |
| } |
| catch(...) |
| { |
| delete [] fmt; |
| bool flag = false; |
| try { |
| os.setstate(std::ios_base::failbit); |
| } |
| catch(std::ios_base::failure) { |
| flag = true; |
| } |
| if (flag) |
| throw; |
| } |
| |
| delete [] fmt; |
| if ( err ) |
| os.setstate(err); |
| return os; |
| } |
| </PRE></UL> |
| <P>The only change from the previous inserter is that the format string here is read from the iostream storage (in statement <SAMP>//1</SAMP>) instead of being the fixed string <SAMP>"%x"</SAMP>. The format string is then provided to the locale's time formatting facet (in statement <SAMP>//2</SAMP>).</P> |
| |
| <BR> |
| <HR> |
| <A HREF="36-2.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="36-4.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A> |
| |
| <!-- Google Analytics tracking code --> |
| <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> |
| </script> |
| <script type="text/javascript"> |
| _uacct = "UA-1775151-1"; |
| urchinTracker(); |
| </script> |
| <!-- end of Google Analytics tracking code --> |
| |
| </BODY> |
| </HTML> |