1 /*
2     Copyright (c) 2009 NetAllied Systems GmbH
3 
4     This file is part of Common libBuffer.
5 
6     Licensed under the MIT Open Source License,
7     for details please see LICENSE file or the website
8     http://www.opensource.org/licenses/mit-license.php
9 */
10 
11 #include "CommonFWriteBufferFlusher.h"
12 
13 #include <cerrno>
14 #include <stdio.h>
15 
16 namespace Common
17 {
18 	//--------------------------------------------------------------------
FWriteBufferFlusher(const char * fileName,size_t bufferSize,const char * mode)19 	FWriteBufferFlusher::FWriteBufferFlusher( const char* fileName, size_t bufferSize, const char* mode/*="wb"*/ )
20 		: mBufferSize(bufferSize)
21 		, mBuffer( new char[bufferSize] )
22 #if defined(_WIN32) && !defined(__GNUC__)
23 		, mError( (int)fopen_s( &mStream, fileName, mode ) )
24 #else
25 		, mStream(fopen( fileName, mode ))
26 		, mError( mStream ? 0 : errno )
27 #endif
28 		, mLastMarkId(END_OF_STREAM)
29 		, mMarkIds()
30 	{
31 		if ( mError == 0 )
32 		{
33 			mError = ( setvbuf( mStream , mBuffer, _IOFBF, mBufferSize ) != 0 );
34 		}
35 	}
36 	//-----------------------------------------------------------------------
37 
38 	/* note: Unix has no _wfopen_s equivalent if its important we could
39 	 * impliment our own but most likely this function is only needed
40 	 * by windows developers - campbell */
41 #if defined(_WIN32) && !defined(__GNUC__)
FWriteBufferFlusher(const wchar_t * fileName,size_t bufferSize,const wchar_t * mode)42 	FWriteBufferFlusher::FWriteBufferFlusher( const wchar_t* fileName, size_t bufferSize, const wchar_t* mode/*=L"wb"*/ )
43 		: mBufferSize(bufferSize)
44 		, mBuffer( new char[bufferSize] )
45 		, mError( (int)_wfopen_s( &mStream, fileName, mode ) )
46 		, mLastMarkId(END_OF_STREAM)
47 		, mMarkIds()
48 	{
49 		if ( mError == 0 )
50 		{
51 			mError = ( setvbuf( mStream , mBuffer, _IOFBF, mBufferSize ) != 0 );
52 		}
53 	}
54 #endif
55 	//--------------------------------------------------------------------
~FWriteBufferFlusher()56 	FWriteBufferFlusher::~FWriteBufferFlusher()
57 	{
58 		if ( mStream )
59 		{
60 			fclose(mStream);
61 		}
62 		delete[] mBuffer;
63 	}
64 
65 	//--------------------------------------------------------------------
receiveData(const char * buffer,size_t length)66 	bool FWriteBufferFlusher::receiveData( const char* buffer, size_t length )
67 	{
68 		if ( !mStream )
69 		{
70 			return false;
71 		}
72 		return fwrite( buffer, 1, length, mStream ) == length;
73 	}
74 
75 	//--------------------------------------------------------------------
flush()76 	bool FWriteBufferFlusher::flush()
77 	{
78 		if ( !mStream )
79 		{
80 			return false;
81 		}
82 		return fflush( mStream ) == 0;
83 	}
84 
85 	//------------------------------
startMark()86 	void FWriteBufferFlusher::startMark()
87 	{
88 		// store the current file position
89 #ifdef __MINGW32__
90 		FilePosType currentPos = ftello64(mStream);
91 #elif defined( _WIN32)
92 		FilePosType currentPos = _ftelli64(mStream);
93 #elif defined (__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
94 		FilePosType currentPos = ftello(mStream);
95 #else
96 		FilePosType currentPos = ftello64(mStream);
97 #endif
98 
99 		mLastMarkId++;
100 		mMarkIds.insert(std::make_pair(mLastMarkId, currentPos));
101 	}
102 
103 	//------------------------------
endMark()104 	IBufferFlusher::MarkId FWriteBufferFlusher::endMark()
105 	{
106 		return mLastMarkId;
107 	}
108 
109 	//------------------------------
jumpToMark(IBufferFlusher::MarkId markId,bool keepMarkId)110 	bool FWriteBufferFlusher::jumpToMark( IBufferFlusher::MarkId markId, bool keepMarkId /*= false*/ )
111 	{
112 		if ( markId == END_OF_STREAM )
113 		{
114 #ifdef __MINGW32__
115   			return (fseeko64(mStream,0,SEEK_END) == 0);
116 #elif defined( _WIN32)
117 			return (_fseeki64(mStream, 0, SEEK_END) == 0);
118 #elif defined (__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
119 			return (fseeko(mStream, 0, SEEK_END) == 0);
120 #else
121 			return (fseeko64(mStream, 0, SEEK_END) == 0);
122 #endif
123 		}
124 		else
125 		{
126 			MarkIdToFilePos::const_iterator markIdIt = mMarkIds.find(markId);
127 			if ( markIdIt == mMarkIds.end() )
128 			{
129 				return false;
130 			}
131 			else
132 			{
133 				FilePosType pos = markIdIt->second;
134 #ifdef __MINGW32__
135   				bool success = (fseeko64(mStream,pos,SEEK_SET) == 0);
136 #elif defined( _WIN32)
137 				bool success = (_fseeki64(mStream, pos, SEEK_SET) == 0);
138 #elif defined (__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
139 				bool success = (fseeko(mStream, pos, SEEK_SET) == 0);
140 #else
141 				bool success = (fseeko64(mStream, pos, SEEK_SET) == 0);
142 #endif
143 				if ( !keepMarkId )
144 				{
145 					mMarkIds.erase(markIdIt);
146 				}
147 				return success;
148 			}
149 		}
150 	}
151 
152 } // namespace Common
153 
154