1 /*
2  * BlockBufferedFileBinaryInputOutputPort.h -
3  *
4  *   Copyright (c) 2009  Higepon(Taro Minowa)  <higepon@users.sourceforge.jp>
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *   1. Redistributions of source code must retain the above copyright
11  *      notice, this list of conditions and the following disclaimer.
12  *
13  *   2. Redistributions in binary form must reproduce the above copyright
14  *      notice, this list of conditions and the following disclaimer in the
15  *      documentation and/or other materials provided with the distribution.
16  *
17  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23  *   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  *   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  *   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  $Id: BlockBufferedFileBinaryInputOutputPort.h 261 2008-07-25 06:16:44Z higepon $
30  */
31 
32 #ifndef SCHEME_BLOCKBUFFERED_FILE_BINARY_INPUT_OUTPUT_PORT_
33 #define SCHEME_BLOCKBUFFERED_FILE_BINARY_INPUT_OUTPUT_PORT_
34 
35 #include "OSCompat.h"
36 #include "BufferedFileBinaryInputOutputPort.h"
37 
38 namespace scheme {
39 
40 class BlockBufferedFileBinaryInputOutputPort : public BufferedFileBinaryInputOutputPort
41 {
42 public:
BlockBufferedFileBinaryInputOutputPort(const ucs4string & filename,int openFlags)43     BlockBufferedFileBinaryInputOutputPort(const ucs4string& filename, int openFlags) :
44         BufferedFileBinaryInputOutputPort(filename, openFlags) {}
~BlockBufferedFileBinaryInputOutputPort()45     virtual ~BlockBufferedFileBinaryInputOutputPort() {}
46 
47 protected:
48     // N.B. writeToFile doesn't change the fd's position.
writeToBuffer(uint8_t * data,int64_t reqSize)49     int64_t writeToBuffer(uint8_t* data, int64_t reqSize)
50     {
51         if (reqSize > 0) {
52             isDirty_ = true;
53         }
54         int64_t writeSize = 0;
55         const int64_t origPositon = file_->seek(0, File::Current);
56         MOSH_ASSERT(origPositon >= 0);
57         bool needUnwind = false;
58 
59         while (writeSize < reqSize) {
60             MOSH_ASSERT(BUF_SIZE >= bufferIndex_);
61             const int64_t bufferRestSize = BUF_SIZE - bufferIndex_;
62             MOSH_ASSERT(reqSize > writeSize);
63             const int64_t restSize = reqSize - writeSize;
64             if (bufferRestSize >= restSize) {
65                 moshMemcpy(buffer_ + bufferIndex_, data + writeSize, restSize);
66                 bufferIndex_ += restSize;
67                 writeSize += restSize;
68             } else {
69                 moshMemcpy(buffer_ + bufferIndex_, data + writeSize, bufferRestSize);
70                 bufferIndex_ += bufferRestSize;
71                 writeSize += bufferRestSize;
72                 internalFlush();
73                 needUnwind = true;
74             }
75         }
76         if (needUnwind) {
77             file_->seek(origPositon);
78         }
79         return writeSize;
80     }
81 };
82 
83 } // namespace scheme
84 
85 #endif // SCHEME_BLOCKBUFFERED_FILE_BINARY_INPUT_OUTPUT_PORT_
86