blob: 0f07ea42ddda00a8973b548fb184373c816b80d7 [file] [log] [blame]
<!--
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>Example 1: Defining a Narrow Character Code Conversion (ASCII &lt;-&gt; EBCDIC)</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="40-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="40-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>40.3 Example 1: Defining a Narrow Character Code Conversion (ASCII &lt;-&gt; EBCDIC)</H2>
<A NAME="idx951"><!></A>
<P>As an example of how file stream buffers and code conversion facets collaborate, we would now like to implement a code conversion facet that can translate text files encoded in EBCDIC into character streams encoded in ASCII. The conversion between ASCII characters and EBCDIC characters is a constant-size code conversion where each character is represented by one byte. Hence the conversion can be done on a character-by-character basis.</P>
<A NAME="idx952"><!></A>
<P>To implement and use an ASCII-EBCDIC code conversion facet, we:</P>
<OL>
<LI><P CLASS="LIST">Derive a new facet type from the standard code conversion facet type <SAMP>std::codecvt</SAMP>.</P></LI>
<LI><P CLASS="LIST">Specialize the new facet type for the character type <SAMP>char</SAMP>.</P></LI>
<LI><P CLASS="LIST">Implement the member functions that are used by the file buffer.</P></LI>
<LI><P CLASS="LIST">Imbue a file stream's buffer with a locale that carries an ASCII-EBCDIC code conversion facet.</P></LI>
</OL>
<P>The following sections explain these steps in detail.</P>
<A NAME="idx953"><!></A>
<A NAME="4031"><H3>40.3.1 Derive a New Facet Type</H3></A>
<A NAME="idx954"><!></A>
<P>Here is the new code conversion facet type <SAMP>AsciiEbcdicConversion</SAMP>:</P>
<UL><PRE>
template &lt;class internT, class externT, class stateT&gt;
class AsciiEbcdicConversion
: public std::codecvt&lt;internT, externT, stateT&gt;
{ };
</PRE></UL>
<P>It is empty because we will specialize the class template for the character type <SAMP>char</SAMP>.</P>
<A NAME="idx955"><!></A>
<A NAME="4032"><H3>40.3.2 Specialize the New Facet Type and Implement the Member Functions</H3></A>
<P>Each code conversion facet has two main member functions, <SAMP>in()</SAMP> and <SAMP>out()</SAMP>:</P>
<UL>
<LI><P CLASS="LIST">The public member function <SAMP>in()</SAMP> is responsible for the conversion done on reading from the external device.</P></LI>
<LI><P CLASS="LIST">The public member function <SAMP>out()</SAMP> is responsible for the conversion necessary for writing to the external device.</P></LI>
</UL>
<P>The other member functions of a code conversion facet used by a file stream buffer are: </P>
<UL>
<LI><P CLASS="LIST">The public member function <SAMP>always_noconv()</SAMP>, which returns <SAMP>true</SAMP> if no conversion is performed by the facet. This is because file stream buffers might want to bypass the code conversion facet when no conversion is necessary; for example, when the external encoding is identical to the internal. Our facet obviously will perform a conversion and does not want to be bypassed, so <SAMP>always_noconv()</SAMP> returns <SAMP>false</SAMP> in our example. </P></LI>
<LI><P CLASS="LIST">The public member function <SAMP>encoding()</SAMP>, which provides information about the type of conversion; that is, whether it is state-dependent or constant-size, etc. In our example, the conversion is constant-size. The function <SAMP>encoding()</SAMP> is supposed to return the size of the internal characters, which is 1 because the file buffer uses an ASCII encoding internally.</P></LI>
</UL>
<A NAME="idx956"><!></A>
<P>All public member functions of a facet call the respective, protected virtual member function, named <SAMP>do_...()</SAMP>. Here is the declaration of the specialized facet type:</P>
<UL><PRE>
template &lt;&gt;
class AsciiEbcdicConversion&lt;char, char, std::mbstate_t&gt;
: public std::codecvt&lt;char, char, std::mbstate_t&gt;
{
protected:
virtual std::codecvt_base::result
do_in (std::mbstate_t&amp; state, const char* from,
const char* from_end, const char*&amp; from_next,
char* to, char* to_limit,
char*&amp; to_next) const;
virtual std::codecvt_base::result
do_out(std::mbstate_t&amp; state,
const char* from, const char* from_end,
const char*&amp; from_next, char* to,
char* to_limit, char*&amp; to_next) const;
virtual
bool do_always_noconv() const throw(){
return false;
}
int do_encoding() const throw(){
return 1;
}
};
</PRE></UL>
<P>For the sake of brevity, we implement only those functions used by this implementation of file stream buffers. If you want to provide a code conversion facet that is more widely usable, you must also override the virtual member functions <SAMP>do_length()</SAMP> and <SAMP>do_max_length()</SAMP>. </P>
<P>The implementation of the functions <SAMP>do_in()</SAMP> and <SAMP>do_out()</SAMP> is straightforward. Each of the functions translates a sequence of characters in the range <SAMP>[from,from_end)</SAMP> into the corresponding sequence <SAMP>[to,to_end)</SAMP>. The pointers <SAMP>from_next</SAMP> and <SAMP>to_next</SAMP> point one beyond the last character successfully converted. In principle, you can do whatever you want, or whatever it takes, in these functions. However, for effective communication with the file stream buffer, it is important to indicate success or failure properly.</P>
<A NAME="4033"><H3>40.3.3 Use the New Code Conversion Facet</H3></A>
<A NAME="idx957"><!></A>
<P>Here is an example of how the new code conversion facet can be used:</P>
<UL><PRE>
std::fstream inout("/tmp/fil"); //1
AsciiEbcdicConversion&lt;char,char,std::mbstate_t&gt; cvtfac;
std::locale cvtloc(std::locale(),&amp;cvtfac);
inout.rdbuf()-&gt;pubimbue(cvtloc) //2
std::cout &lt;&lt; inout.rdbuf(); //3
</PRE></UL>
<TABLE CELLPADDING="3">
<TR VALIGN="top"><TD><SAMP>//1</SAMP></TD><TD>When a file is created, a snapshot of the current global locale is attached as the default locale. Remember that a stream has two locale objects: one used for formatting numeric items, and a second used by the stream's buffer for code conversions.
<TR VALIGN="top"><TD><SAMP>//2</SAMP></TD><TD>Here the stream buffer's locale is replaced by a copy of the global locale that has an ASCII-EBCDIC code conversion facet.
<TR VALIGN="top"><TD><SAMP>//3</SAMP></TD><TD>The content of the EBCDIC file <SAMP>"/tmp/fil"</SAMP> is read, automatically converted to ASCII, and written to <SAMP>std::cout</SAMP>.
</TABLE>
<BR>
<HR>
<A HREF="40-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="40-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>