145 lines
7.8 KiB
HTML
145 lines
7.8 KiB
HTML
<!--
|
|
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>
|