[Tizen] Remove graphics-api relative codes in public-api/application.h
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor-framework / generic / file-stream-impl-generic.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // CLASS HEADER
18 #include <dali/internal/adaptor-framework/common/file-stream-impl.h>
19
20 // EXTERNAL INCLUDES
21 #include <cstring>
22 #include <fstream>
23
24 #include <dali/integration-api/debug.h>
25
26 namespace Dali
27 {
28 FileStream::Impl::Impl(const std::string& filename, uint8_t mode)
29 : mFileName(filename),
30   mMode(mode),
31   mBuffer(nullptr),
32   mDataSize(0),
33   mFile(nullptr)
34 {
35   DALI_ASSERT_DEBUG(!filename.empty() && "Can't open a empty filename.");
36   DALI_ASSERT_DEBUG(mode != 0 && "No mode is undefined behaviour");
37 }
38
39 FileStream::Impl::Impl(uint8_t* buffer, size_t dataSize, uint8_t mode)
40 : mMode(mode),
41   mBuffer(buffer),
42   mDataSize(dataSize),
43   mFile(nullptr)
44 {
45   DALI_ASSERT_DEBUG(buffer != 0 && "Can't open file on null buffer.");
46   DALI_ASSERT_DEBUG(dataSize > 0 && "Pointless to open file on empty buffer.");
47   DALI_ASSERT_DEBUG(mode != 0 && "No mode is undefined behaviour.");
48 }
49
50 FileStream::Impl::Impl(Dali::Vector<uint8_t>& vector, size_t dataSize, uint8_t mode)
51 : mMode(mode),
52   mBuffer(nullptr),
53   mDataSize(dataSize),
54   mFile(nullptr)
55 {
56   // Resize the buffer to ensure any null that gets written by
57   // fmemopen is written past the end of any data that is written to the buffer.
58   // (Workaround for a bug in Ubuntu that overwrites null to the last byte of the
59   // data block regardless of whether binary mode was specified. Tizen doesn't write
60   // null if binary mode is specified).
61
62   ++mDataSize;
63   vector.Resize(mDataSize);
64   mBuffer = &vector[0];
65
66   DALI_ASSERT_DEBUG(mBuffer != nullptr && "Can't open file on null buffer.");
67   DALI_ASSERT_DEBUG(dataSize > 0 && "Pointless to open file on empty buffer.");
68   DALI_ASSERT_DEBUG(mode != 0 && "No mode is undefined behaviour.");
69 }
70
71 FileStream::Impl::~Impl()
72 {
73   if(mFile)
74   {
75     const int closeFailed = fclose(mFile);
76     if(closeFailed)
77     {
78       DALI_LOG_WARNING("File close failed for FILE: \"%p\".\n", static_cast<void*>(mFile));
79     }
80
81     mFile = nullptr;
82   }
83
84   if(mFileStream.is_open())
85   {
86     mFileStream.close();
87   }
88 }
89
90 std::iostream& FileStream::Impl::GetStream()
91 {
92   if(mFile)
93   {
94     // return empty stream if FILE stream is open to avoid simultaneous access to the same file
95     return mFileStream;
96   }
97
98   if(mFileStream.is_open())
99   {
100     return mFileStream;
101   }
102
103   if(mBufferStream.rdbuf()->in_avail())
104   {
105     return mBufferStream;
106   }
107
108   int openMode = 0;
109
110   if(mMode & Dali::FileStream::APPEND)
111   {
112     openMode |= (std::ios::out | std::ios::app);
113   }
114   else if(mMode & Dali::FileStream::WRITE)
115   {
116     openMode |= (std::ios::out | std::ios::ate);
117   }
118
119   if(mMode & Dali::FileStream::READ)
120   {
121     openMode |= std::ios::in;
122   }
123
124   if(mMode & Dali::FileStream::BINARY)
125   {
126     openMode |= std::ios::binary;
127   }
128
129   if(!mFileName.empty())
130   {
131     mFileStream.open(mFileName, static_cast<std::ios_base::openmode>(openMode));
132     if(!mFileStream.is_open())
133     {
134       DALI_LOG_WARNING("stream open failed for: \"%s\", in mode: \"%d\".\n", mFileName.c_str(), openMode);
135     }
136     return mFileStream;
137   }
138   else if(mBuffer)
139   {
140     mBufferStream.rdbuf()->pubsetbuf(reinterpret_cast<char*>(mBuffer), mDataSize);
141     if(!mBufferStream.rdbuf()->in_avail())
142     {
143       DALI_LOG_WARNING("File open failed for memory buffer at location: \"%p\", of size: \"%u\", in mode: \"%d\".\n",
144                        static_cast<void*>(mBuffer),
145                        static_cast<unsigned>(mDataSize),
146                        openMode);
147     }
148   }
149
150   return mBufferStream;
151 }
152
153 FILE* FileStream::Impl::GetFile()
154 {
155   if(mFileStream.is_open() || mBufferStream.rdbuf()->in_avail())
156   {
157     // return empty FILE stream if the stream is open to avoid simultaneous access to the same file
158     return nullptr;
159   }
160
161   if(mFile)
162   {
163     return mFile;
164   }
165
166   char openMode[16] = {0};
167   int  i            = 0;
168
169   if(mMode & Dali::FileStream::APPEND)
170   {
171     openMode[i++] = 'a';
172   }
173   else if(mMode & Dali::FileStream::WRITE)
174   {
175     openMode[i++] = 'w';
176   }
177   else
178   {
179     openMode[i++] = 'r';
180   }
181
182   if(mMode & Dali::FileStream::BINARY)
183   {
184     openMode[i++] = 'b';
185   }
186
187   openMode[i++] = 0;
188
189   if(!mFileName.empty())
190   {
191     mFile = fopen(mFileName.c_str(), openMode);
192     if(!mFile)
193     {
194       char buf[512];
195       DALI_LOG_ERROR("file open failed for: \"%s\", in mode: \"%s\".\n", mFileName.c_str(), openMode);
196       DALI_LOG_ERROR("file open failed error : %s\n", strerror_r(errno, buf, 512));
197     }
198   }
199   else if(mBuffer)
200   {
201     mFile = fmemopen(mBuffer, mDataSize, openMode);
202     if(!mFile)
203     {
204       char buf[512];
205       DALI_LOG_ERROR("File open failed for memory buffer at location: \"%p\", of size: \"%u\", in mode: \"%s\".\n",
206                      static_cast<void*>(mBuffer),
207                      static_cast<unsigned>(mDataSize),
208                      openMode);
209       DALI_LOG_ERROR("file open failed error : %s\n", strerror_r(errno, buf, 512));
210     }
211   }
212
213   return mFile;
214 }
215
216 } // namespace Dali