1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 13 мар. 2019 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <core/io/StdioFile.h>
23 #include <core/io/NativeFile.h>
24 #include <core/io/OutFileStream.h>
25 
26 namespace lsp
27 {
28     namespace io
29     {
30 
OutFileStream()31         OutFileStream::OutFileStream()
32         {
33             pFD         = NULL;
34             nWrapFlags  = 0;
35         }
36 
~OutFileStream()37         OutFileStream::~OutFileStream()
38         {
39             // Close file descriptor
40             if (pFD != NULL)
41             {
42                 if (nWrapFlags & WRAP_CLOSE)
43                     pFD->close();
44                 if (nWrapFlags & WRAP_DELETE)
45                     delete pFD;
46                 pFD         = NULL;
47             }
48             nWrapFlags  = 0;
49         }
50 
close()51         status_t OutFileStream::close()
52         {
53             status_t res = STATUS_OK;
54 
55             if (pFD != NULL)
56             {
57                 // Perform close
58                 if (nWrapFlags & WRAP_CLOSE)
59                     res = pFD->close();
60                 if (nWrapFlags & WRAP_DELETE)
61                     delete pFD;
62                 pFD         = NULL;
63             }
64             nWrapFlags  = 0;
65 
66             return set_error(res);
67         }
68 
wrap(FILE * fd,bool close)69         status_t OutFileStream::wrap(FILE *fd, bool close)
70         {
71             if (pFD != NULL)
72                 return set_error(STATUS_BAD_STATE);
73             else if (fd == NULL)
74                 return set_error(STATUS_BAD_ARGUMENTS);
75 
76             StdioFile *f = new StdioFile();
77             if (f == NULL)
78                 return set_error(STATUS_NO_MEM);
79             status_t res = f->wrap(fd, File::FM_WRITE, close);
80             if (res != STATUS_OK)
81             {
82                 f->close();
83                 delete f;
84                 return set_error(res);
85             }
86 
87             res = wrap(f, WRAP_DELETE);
88             if (res != STATUS_OK)
89             {
90                 f->close();
91                 delete f;
92             }
93             return set_error(res);
94         }
95 
wrap_native(lsp_fhandle_t fd,bool close)96         status_t OutFileStream::wrap_native(lsp_fhandle_t fd, bool close)
97         {
98             if (pFD != NULL)
99                 return set_error(STATUS_BAD_STATE);
100 
101             NativeFile *f = new NativeFile();
102             if (f == NULL)
103                 return set_error(STATUS_NO_MEM);
104             status_t res = f->wrap(fd, File::FM_WRITE, close);
105             if (res != STATUS_OK)
106             {
107                 f->close();
108                 delete f;
109                 return set_error(res);
110             }
111 
112             res = wrap(f, WRAP_DELETE);
113             if (res != STATUS_OK)
114             {
115                 f->close();
116                 delete f;
117             }
118             return set_error(res);
119         }
120 
wrap(File * fd,size_t flags)121         status_t OutFileStream::wrap(File *fd, size_t flags)
122         {
123             if (pFD != NULL)
124                 return set_error(STATUS_BAD_STATE);
125             else if (fd == NULL)
126                 return set_error(STATUS_BAD_ARGUMENTS);
127 
128             // Store pointers
129             pFD         = fd;
130             nWrapFlags  = flags;
131 
132             return STATUS_OK;
133         }
134 
open(const char * path,size_t mode)135         status_t OutFileStream::open(const char *path, size_t mode)
136         {
137             if (pFD != NULL)
138                 return set_error(STATUS_BAD_STATE);
139             else if (path == NULL)
140                 return set_error(STATUS_BAD_ARGUMENTS);
141 
142             LSPString tmp;
143             if (!tmp.set_utf8(path))
144                 return set_error(STATUS_NO_MEM);
145             return open(&tmp, mode);
146         }
147 
open(const LSPString * path,size_t mode)148         status_t OutFileStream::open(const LSPString *path, size_t mode)
149         {
150             if (pFD != NULL)
151                 return set_error(STATUS_BAD_STATE);
152             else if (path == NULL)
153                 return set_error(STATUS_BAD_ARGUMENTS);
154 
155             NativeFile *f = new NativeFile();
156             if (f == NULL)
157                 return set_error(STATUS_NO_MEM);
158 
159             status_t res = f->open(path, mode | File::FM_WRITE);
160             if (res != STATUS_OK)
161             {
162                 f->close();
163                 delete f;
164                 return set_error(res);
165             }
166 
167             return wrap(f, WRAP_CLOSE | WRAP_DELETE);
168         }
169 
open(const Path * path,size_t mode)170         status_t OutFileStream::open(const Path *path, size_t mode)
171         {
172             return open(path->as_string(), mode);
173         }
174 
position()175         wssize_t OutFileStream::position()
176         {
177             if (pFD == NULL)
178                 return set_error(STATUS_CLOSED);
179             wssize_t pos = pFD->position();
180             set_error((pos < 0) ? status_t(-pos) : STATUS_OK);
181             return pos;
182         }
183 
write(const void * buf,size_t count)184         ssize_t OutFileStream::write(const void *buf, size_t count)
185         {
186             if (pFD == NULL)
187                 return set_error(STATUS_CLOSED);
188             ssize_t res = pFD->write(buf, count);
189             set_error((res < 0) ? status_t(-res) : STATUS_OK);
190             return res;
191         }
192 
seek(wsize_t position)193         wssize_t OutFileStream::seek(wsize_t position)
194         {
195             if (pFD == NULL)
196                 return set_error(STATUS_CLOSED);
197             status_t res = pFD->seek(position, File::FSK_SET);
198             if (res != STATUS_OK)
199                 return -set_error(res);
200             wssize_t pos = pFD->position();
201             set_error((pos < 0) ? status_t(-pos) : STATUS_OK);
202             return pos;
203         }
204 
flush()205         status_t OutFileStream::flush()
206         {
207             if (pFD == NULL)
208                 return set_error(STATUS_CLOSED);
209             return set_error(pFD->flush());
210         }
211 
212     } /* namespace io */
213 } /* namespace lsp */
214