2 ==============================================================================
4 This file is part of the Water library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2017 Filipe Coelho <falktx@falktx.com>
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 ==============================================================================
26 #include "FileOutputStream.h"
30 int64
water_fileSetPosition (void* handle
, int64 pos
);
32 //==============================================================================
33 FileOutputStream::FileOutputStream (const File
& f
, const size_t bufferSizeToUse
)
36 status (Result::ok()),
38 bufferSize (bufferSizeToUse
),
41 if (buffer
.malloc(jmax (bufferSizeToUse
, (size_t) 16)))
44 status
= Result::fail ("Allocation failure");
47 FileOutputStream::~FileOutputStream()
53 int64
FileOutputStream::getPosition()
55 return currentPosition
;
58 bool FileOutputStream::setPosition (int64 newPosition
)
60 if (newPosition
!= currentPosition
)
63 currentPosition
= water_fileSetPosition (fileHandle
, newPosition
);
66 return newPosition
== currentPosition
;
69 bool FileOutputStream::flushBuffer()
73 if (bytesInBuffer
> 0)
75 ok
= (writeInternal (buffer
, bytesInBuffer
) == (ssize_t
) bytesInBuffer
);
82 void FileOutputStream::flush()
88 bool FileOutputStream::write (const void* const src
, const size_t numBytes
)
90 wassert (src
!= nullptr && ((ssize_t
) numBytes
) >= 0);
92 if (bytesInBuffer
+ numBytes
< bufferSize
)
94 memcpy (buffer
+ bytesInBuffer
, src
, numBytes
);
95 bytesInBuffer
+= numBytes
;
96 currentPosition
+= (int64
) numBytes
;
103 if (numBytes
< bufferSize
)
105 memcpy (buffer
+ bytesInBuffer
, src
, numBytes
);
106 bytesInBuffer
+= numBytes
;
107 currentPosition
+= (int64
) numBytes
;
111 const ssize_t bytesWritten
= writeInternal (src
, numBytes
);
113 if (bytesWritten
< 0)
116 currentPosition
+= (int64
) bytesWritten
;
117 return bytesWritten
== (ssize_t
) numBytes
;
124 bool FileOutputStream::writeRepeatedByte (uint8 byte
, size_t numBytes
)
126 wassert (((ssize_t
) numBytes
) >= 0);
128 if (bytesInBuffer
+ numBytes
< bufferSize
)
130 memset (buffer
+ bytesInBuffer
, byte
, numBytes
);
131 bytesInBuffer
+= numBytes
;
132 currentPosition
+= (int64
) numBytes
;
136 return OutputStream::writeRepeatedByte (byte
, numBytes
);
140 void FileOutputStream::openHandle()
142 HANDLE h
= CreateFileA (file
.getFullPathName().toUTF8(), GENERIC_WRITE
, FILE_SHARE_READ
, 0,
143 OPEN_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, 0);
145 if (h
!= INVALID_HANDLE_VALUE
)
149 li
.LowPart
= SetFilePointer (h
, 0, &li
.HighPart
, FILE_END
);
151 if (li
.LowPart
!= INVALID_SET_FILE_POINTER
)
153 fileHandle
= (void*) h
;
154 currentPosition
= li
.QuadPart
;
159 status
= getResultForLastError();
162 void FileOutputStream::closeHandle()
164 CloseHandle ((HANDLE
) fileHandle
);
167 ssize_t
FileOutputStream::writeInternal (const void* bufferToWrite
, size_t numBytes
)
169 if (fileHandle
!= nullptr)
172 if (! WriteFile ((HANDLE
) fileHandle
, bufferToWrite
, (DWORD
) numBytes
, &actualNum
, 0))
173 status
= getResultForLastError();
175 return (ssize_t
) actualNum
;
181 void FileOutputStream::flushInternal()
183 if (fileHandle
!= nullptr)
184 if (! FlushFileBuffers ((HANDLE
) fileHandle
))
185 status
= getResultForLastError();
188 void FileOutputStream::openHandle()
192 const int f
= open (file
.getFullPathName().toUTF8(), O_RDWR
, 00644);
196 currentPosition
= lseek (f
, 0, SEEK_END
);
198 if (currentPosition
>= 0)
200 fileHandle
= fdToVoidPointer (f
);
204 status
= getResultForErrno();
210 status
= getResultForErrno();
215 const int f
= open (file
.getFullPathName().toUTF8(), O_RDWR
+ O_CREAT
, 00644);
218 fileHandle
= fdToVoidPointer (f
);
220 status
= getResultForErrno();
224 void FileOutputStream::closeHandle()
228 close (getFD (fileHandle
));
233 ssize_t
FileOutputStream::writeInternal (const void* const data
, const size_t numBytes
)
239 result
= ::write (getFD (fileHandle
), data
, numBytes
);
242 status
= getResultForErrno();
248 void FileOutputStream::flushInternal()
252 if (fsync (getFD (fileHandle
)) == -1)
253 status
= getResultForErrno();