<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ --> <title>GHC/IO/BufferedIO.hs</title> <link type='text/css' rel='stylesheet' href='hscolour.css' /> </head> <body> <pre><a name="line-1"></a><span class='hs-comment'>{-# OPTIONS_GHC -XNoImplicitPrelude -funbox-strict-fields #-}</span> <a name="line-2"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span> <a name="line-3"></a><span class='hs-comment'>-- |</span> <a name="line-4"></a><span class='hs-comment'>-- Module : GHC.IO.BufferedIO</span> <a name="line-5"></a><span class='hs-comment'>-- Copyright : (c) The University of Glasgow 2008</span> <a name="line-6"></a><span class='hs-comment'>-- License : see libraries/base/LICENSE</span> <a name="line-7"></a><span class='hs-comment'>-- </span> <a name="line-8"></a><span class='hs-comment'>-- Maintainer : cvs-ghc@haskell.org</span> <a name="line-9"></a><span class='hs-comment'>-- Stability : internal</span> <a name="line-10"></a><span class='hs-comment'>-- Portability : non-portable (GHC Extensions)</span> <a name="line-11"></a><span class='hs-comment'>--</span> <a name="line-12"></a><span class='hs-comment'>-- Class of buffered IO devices</span> <a name="line-13"></a><span class='hs-comment'>--</span> <a name="line-14"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span> <a name="line-15"></a> <a name="line-16"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>BufferedIO</span> <span class='hs-layout'>(</span> <a name="line-17"></a> <span class='hs-conid'>BufferedIO</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <a name="line-18"></a> <span class='hs-varid'>readBuf</span><span class='hs-layout'>,</span> <span class='hs-varid'>readBufNonBlocking</span><span class='hs-layout'>,</span> <span class='hs-varid'>writeBuf</span><span class='hs-layout'>,</span> <span class='hs-varid'>writeBufNonBlocking</span> <a name="line-19"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span> <a name="line-20"></a> <a name="line-21"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Base</span> <a name="line-22"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Ptr</span> <a name="line-23"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Word</span> <a name="line-24"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>Num</span> <a name="line-25"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Maybe</span> <a name="line-26"></a><span class='hs-comment'>-- import GHC.IO</span> <a name="line-27"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Device</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>IODevice</span> <a name="line-28"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Device</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>RawIO</span> <a name="line-29"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Buffer</span> <a name="line-30"></a> <a name="line-31"></a><a name="BufferedIO"></a><span class='hs-comment'>-- | The purpose of 'BufferedIO' is to provide a common interface for I/O</span> <a name="line-32"></a><a name="BufferedIO"></a><span class='hs-comment'>-- devices that can read and write data through a buffer. Devices that</span> <a name="line-33"></a><a name="BufferedIO"></a><span class='hs-comment'>-- implement 'BufferedIO' include ordinary files, memory-mapped files,</span> <a name="line-34"></a><a name="BufferedIO"></a><span class='hs-comment'>-- and bytestrings. The underlying device implementing a 'Handle' must</span> <a name="line-35"></a><a name="BufferedIO"></a><span class='hs-comment'>-- provide 'BufferedIO'.</span> <a name="line-36"></a><a name="BufferedIO"></a><span class='hs-comment'>--</span> <a name="line-37"></a><a name="BufferedIO"></a><span class='hs-keyword'>class</span> <span class='hs-conid'>BufferedIO</span> <span class='hs-varid'>dev</span> <span class='hs-keyword'>where</span> <a name="line-38"></a> <span class='hs-comment'>-- | allocate a new buffer. The size of the buffer is at the</span> <a name="line-39"></a> <span class='hs-comment'>-- discretion of the device; e.g. for a memory-mapped file the</span> <a name="line-40"></a> <span class='hs-comment'>-- buffer will probably cover the entire file.</span> <a name="line-41"></a> <span class='hs-varid'>newBuffer</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>BufferState</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-42"></a> <a name="line-43"></a> <span class='hs-comment'>-- | reads bytes into the buffer, blocking if there are no bytes</span> <a name="line-44"></a> <span class='hs-comment'>-- available. Returns the number of bytes read (zero indicates</span> <a name="line-45"></a> <span class='hs-comment'>-- end-of-file), and the new buffer.</span> <a name="line-46"></a> <span class='hs-varid'>fillReadBuffer</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-47"></a> <a name="line-48"></a> <span class='hs-comment'>-- | reads bytes into the buffer without blocking. Returns the</span> <a name="line-49"></a> <span class='hs-comment'>-- number of bytes read (Nothing indicates end-of-file), and the new</span> <a name="line-50"></a> <span class='hs-comment'>-- buffer.</span> <a name="line-51"></a> <span class='hs-varid'>fillReadBuffer0</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-52"></a> <a name="line-53"></a> <span class='hs-comment'>-- | Prepares an empty write buffer. This lets the device decide</span> <a name="line-54"></a> <span class='hs-comment'>-- how to set up a write buffer: the buffer may need to point to a</span> <a name="line-55"></a> <span class='hs-comment'>-- specific location in memory, for example. This is typically used</span> <a name="line-56"></a> <span class='hs-comment'>-- by the client when switching from reading to writing on a</span> <a name="line-57"></a> <span class='hs-comment'>-- buffered read/write device.</span> <a name="line-58"></a> <span class='hs-comment'>--</span> <a name="line-59"></a> <span class='hs-comment'>-- There is no corresponding operation for read buffers, because before</span> <a name="line-60"></a> <span class='hs-comment'>-- reading the client will always call 'fillReadBuffer'.</span> <a name="line-61"></a> <span class='hs-varid'>emptyWriteBuffer</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-62"></a> <span class='hs-varid'>emptyWriteBuffer</span> <span class='hs-sel'>_dev</span> <span class='hs-varid'>buf</span> <a name="line-63"></a> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-varid'>buf</span><span class='hs-layout'>{</span> <span class='hs-varid'>bufL</span><span class='hs-keyglyph'>=</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-varid'>bufR</span><span class='hs-keyglyph'>=</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-varid'>bufState</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>WriteBuffer</span> <span class='hs-layout'>}</span> <a name="line-64"></a> <a name="line-65"></a> <span class='hs-comment'>-- | Flush all the data from the supplied write buffer out to the device.</span> <a name="line-66"></a> <span class='hs-comment'>-- The returned buffer should be empty, and ready for writing.</span> <a name="line-67"></a> <span class='hs-varid'>flushWriteBuffer</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-68"></a> <a name="line-69"></a> <span class='hs-comment'>-- | Flush data from the supplied write buffer out to the device</span> <a name="line-70"></a> <span class='hs-comment'>-- without blocking. Returns the number of bytes written and the</span> <a name="line-71"></a> <span class='hs-comment'>-- remaining buffer.</span> <a name="line-72"></a> <span class='hs-varid'>flushWriteBuffer0</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-73"></a> <a name="line-74"></a><span class='hs-comment'>-- for an I/O device, these operations will perform reading/writing</span> <a name="line-75"></a><span class='hs-comment'>-- to/from the device.</span> <a name="line-76"></a> <a name="line-77"></a><span class='hs-comment'>-- for a memory-mapped file, the buffer will be the whole file in</span> <a name="line-78"></a><span class='hs-comment'>-- memory. fillReadBuffer sets the pointers to encompass the whole</span> <a name="line-79"></a><span class='hs-comment'>-- file, and flushWriteBuffer needs to do no I/O. A memory-mapped</span> <a name="line-80"></a><span class='hs-comment'>-- file has to maintain its own file pointer.</span> <a name="line-81"></a> <a name="line-82"></a><span class='hs-comment'>-- for a bytestring, again the buffer should match the bytestring in</span> <a name="line-83"></a><span class='hs-comment'>-- memory.</span> <a name="line-84"></a> <a name="line-85"></a><span class='hs-comment'>-- ---------------------------------------------------------------------------</span> <a name="line-86"></a><span class='hs-comment'>-- Low-level read/write to/from buffers</span> <a name="line-87"></a> <a name="line-88"></a><span class='hs-comment'>-- These operations make it easy to implement an instance of 'BufferedIO'</span> <a name="line-89"></a><span class='hs-comment'>-- for an object that supports 'RawIO'.</span> <a name="line-90"></a> <a name="line-91"></a><a name="readBuf"></a><span class='hs-definition'>readBuf</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>RawIO</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>=></span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-92"></a><span class='hs-definition'>readBuf</span> <span class='hs-varid'>dev</span> <span class='hs-varid'>bbuf</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-93"></a> <span class='hs-keyword'>let</span> <span class='hs-varid'>bytes</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bufferAvailable</span> <span class='hs-varid'>bbuf</span> <a name="line-94"></a> <span class='hs-varid'>res</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>withBuffer</span> <span class='hs-varid'>bbuf</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>ptr</span> <span class='hs-keyglyph'>-></span> <a name="line-95"></a> <span class='hs-conid'>RawIO</span><span class='hs-varop'>.</span><span class='hs-varid'>read</span> <span class='hs-varid'>dev</span> <span class='hs-layout'>(</span><span class='hs-varid'>ptr</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>bufR</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>)</span> <span class='hs-varid'>bytes</span> <a name="line-96"></a> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>res</span><span class='hs-layout'>,</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>{</span> <span class='hs-varid'>bufR</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bufR</span> <span class='hs-varid'>bbuf</span> <span class='hs-varop'>+</span> <span class='hs-varid'>res</span> <span class='hs-layout'>}</span><span class='hs-layout'>)</span> <a name="line-97"></a> <span class='hs-comment'>-- zero indicates end of file</span> <a name="line-98"></a> <a name="line-99"></a><a name="readBufNonBlocking"></a><span class='hs-definition'>readBufNonBlocking</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>RawIO</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>=></span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <a name="line-100"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-comment'>-- Nothing ==> end of file</span> <a name="line-101"></a> <span class='hs-comment'>-- Just n ==> n bytes were read (n>=0)</span> <a name="line-102"></a> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-103"></a><span class='hs-definition'>readBufNonBlocking</span> <span class='hs-varid'>dev</span> <span class='hs-varid'>bbuf</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-104"></a> <span class='hs-keyword'>let</span> <span class='hs-varid'>bytes</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bufferAvailable</span> <span class='hs-varid'>bbuf</span> <a name="line-105"></a> <span class='hs-varid'>res</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>withBuffer</span> <span class='hs-varid'>bbuf</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>ptr</span> <span class='hs-keyglyph'>-></span> <a name="line-106"></a> <span class='hs-conid'>IODevice</span><span class='hs-varop'>.</span><span class='hs-varid'>readNonBlocking</span> <span class='hs-varid'>dev</span> <span class='hs-layout'>(</span><span class='hs-varid'>ptr</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>bufR</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>)</span> <span class='hs-varid'>bytes</span> <a name="line-107"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>res</span> <span class='hs-keyword'>of</span> <a name="line-108"></a> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>)</span> <a name="line-109"></a> <span class='hs-conid'>Just</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>n</span><span class='hs-layout'>,</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>{</span> <span class='hs-varid'>bufR</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bufR</span> <span class='hs-varid'>bbuf</span> <span class='hs-varop'>+</span> <span class='hs-varid'>n</span> <span class='hs-layout'>}</span><span class='hs-layout'>)</span> <a name="line-110"></a> <a name="line-111"></a><a name="writeBuf"></a><span class='hs-definition'>writeBuf</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>RawIO</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>=></span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-112"></a><span class='hs-definition'>writeBuf</span> <span class='hs-varid'>dev</span> <span class='hs-varid'>bbuf</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-113"></a> <span class='hs-keyword'>let</span> <span class='hs-varid'>bytes</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bufferElems</span> <span class='hs-varid'>bbuf</span> <a name="line-114"></a> <span class='hs-varid'>withBuffer</span> <span class='hs-varid'>bbuf</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>ptr</span> <span class='hs-keyglyph'>-></span> <a name="line-115"></a> <span class='hs-conid'>IODevice</span><span class='hs-varop'>.</span><span class='hs-varid'>write</span> <span class='hs-varid'>dev</span> <span class='hs-layout'>(</span><span class='hs-varid'>ptr</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>bufL</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>)</span> <span class='hs-varid'>bytes</span> <a name="line-116"></a> <span class='hs-varid'>return</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>{</span> <span class='hs-varid'>bufL</span><span class='hs-keyglyph'>=</span><span class='hs-num'>0</span><span class='hs-layout'>,</span> <span class='hs-varid'>bufR</span><span class='hs-keyglyph'>=</span><span class='hs-num'>0</span> <span class='hs-layout'>}</span> <a name="line-117"></a> <a name="line-118"></a><a name="writeBufNonBlocking"></a><span class='hs-comment'>-- XXX ToDo</span> <a name="line-119"></a><span class='hs-definition'>writeBufNonBlocking</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>RawIO</span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>=></span> <span class='hs-varid'>dev</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>Buffer</span> <span class='hs-conid'>Word8</span><span class='hs-layout'>)</span> <a name="line-120"></a><span class='hs-definition'>writeBufNonBlocking</span> <span class='hs-varid'>dev</span> <span class='hs-varid'>bbuf</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <a name="line-121"></a> <span class='hs-keyword'>let</span> <span class='hs-varid'>bytes</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bufferElems</span> <span class='hs-varid'>bbuf</span> <a name="line-122"></a> <span class='hs-varid'>res</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>withBuffer</span> <span class='hs-varid'>bbuf</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>ptr</span> <span class='hs-keyglyph'>-></span> <a name="line-123"></a> <span class='hs-conid'>IODevice</span><span class='hs-varop'>.</span><span class='hs-varid'>writeNonBlocking</span> <span class='hs-varid'>dev</span> <span class='hs-layout'>(</span><span class='hs-varid'>ptr</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>bufL</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>)</span> <span class='hs-varid'>bytes</span> <a name="line-124"></a> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>res</span><span class='hs-layout'>,</span> <span class='hs-varid'>bufferAdjustL</span> <span class='hs-varid'>res</span> <span class='hs-varid'>bbuf</span><span class='hs-layout'>)</span> </pre></body> </html>