[dali_2.3.26] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor-framework / android / file-loader-impl-android.cpp
1 /*
2  * Copyright (c) 2022 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-loader-impl.h>
19
20 // EXTERNAL INCLUDES
21 #include <dali/integration-api/debug.h>
22 #include <cstdio>
23 #include <fstream>
24 #include <string>
25
26 // INTERNAL INCLUDES
27 #include <dali/integration-api/adaptor-framework/android/android-framework.h>
28 #include <dali/internal/adaptor/common/framework.h>
29
30 namespace Dali
31 {
32 namespace Internal
33 {
34 namespace Adaptor
35 {
36 int ReadFile(const std::string& filename, Dali::Vector<char>& memblock, Dali::FileLoader::FileType fileType)
37 {
38   std::streampos size;
39
40   return Dali::Internal::Adaptor::ReadFile(filename, size, memblock, fileType);
41 }
42
43 int ReadFile(const std::string& filename, Dali::Vector<uint8_t>& memblock, Dali::FileLoader::FileType fileType)
44 {
45   std::streampos size;
46
47   return Dali::Internal::Adaptor::ReadFile(filename, size, memblock, fileType);
48 }
49
50 inline bool hasPrefix(const std::string& prefix, const std::string& path)
51 {
52   return std::mismatch(prefix.begin(), prefix.end(), path.begin()).first == prefix.end();
53 }
54
55 inline std::string ConvertToAssetsInternalPath(const std::string& path, int offset)
56 {
57   std::string internalPath = std::string(path.c_str() + offset);
58
59   int i = 0;
60   while((i = internalPath.find("//", i)) != std::string::npos)
61   {
62     internalPath.replace(i, 2, "/");
63   }
64
65   return internalPath;
66 }
67
68 template<typename T>
69 int ReadFile(const std::string& filename, std::streampos& fileSize, Dali::Vector<T>& memblock, Dali::FileLoader::FileType fileType)
70 {
71   int  errorCode = 0;
72   int  length    = 0;
73   char mode[3]   = {'r', 0, 0};
74
75   if(fileType == Dali::FileLoader::BINARY)
76   {
77     mode[1] = 'b';
78   }
79   else if(fileType != Dali::FileLoader::TEXT)
80   {
81     return errorCode;
82   }
83
84   const std::string assetsPrefix = "assets/";
85   if(hasPrefix(assetsPrefix, filename))
86   {
87     std::string    internalPath = ConvertToAssetsInternalPath(filename, assetsPrefix.length());
88     AAssetManager* assetManager = Dali::Integration::AndroidFramework::Get().GetApplicationAssets();
89     AAsset*        asset        = AAssetManager_open(assetManager, internalPath.c_str(), AASSET_MODE_BUFFER);
90     if(asset)
91     {
92       length = AAsset_getLength(asset);
93       memblock.ResizeUninitialized(length + 1);
94       memblock[length] = 0; // 1 for extra zero at the end
95
96       char* buffer = reinterpret_cast<char*>(memblock.Begin());
97       errorCode    = (AAsset_read(asset, buffer, length) != length) ? 0 : 1;
98       fileSize     = length;
99
100       AAsset_close(asset);
101     }
102     else
103     {
104       DALI_LOG_ERROR("Asset not found %s\n", internalPath.c_str());
105     }
106   }
107   else
108   {
109     FILE* file = fopen(filename.c_str(), mode);
110     if(file)
111     {
112       fseek(file, 0, SEEK_END);
113       length = ftell(file);
114       memblock.ResizeUninitialized(length + 1);
115       //put last byte as 0, in case this is a text file without null-terminator
116       memblock[length] = 0;
117
118       char* buffer = reinterpret_cast<char*>(memblock.Begin());
119       fseek(file, 0, SEEK_SET);
120       errorCode = (fread(buffer, 1, length, file) != length) ? 0 : 1;
121       fileSize  = length;
122
123       fclose(file);
124     }
125     else
126     {
127       DALI_LOG_ERROR("File not found %s\n", filename.c_str());
128     }
129   }
130
131   return errorCode;
132 }
133
134 std::streampos GetFileSize(const std::string& filename)
135 {
136   std::streampos size = 0;
137
138   const std::string assetsPrefix = "assets/";
139   if(hasPrefix(assetsPrefix, filename))
140   {
141     std::string    internalPath = ConvertToAssetsInternalPath(filename, assetsPrefix.length());
142     AAssetManager* assetManager = Dali::Integration::AndroidFramework::Get().GetApplicationAssets();
143     AAsset*        asset        = AAssetManager_open(assetManager, internalPath.c_str(), AASSET_MODE_BUFFER);
144     if(asset)
145     {
146       size = AAsset_getLength(asset);
147       AAsset_close(asset);
148     }
149     else
150     {
151       DALI_LOG_ERROR("Asset not found %s\n", internalPath.c_str());
152     }
153   }
154   else
155   {
156     FILE* file = fopen(filename.c_str(), "r");
157     if(file)
158     {
159       fseek(file, 0, SEEK_END);
160       size = ftell(file);
161       fclose(file);
162     }
163     else
164     {
165       DALI_LOG_ERROR("File not found %s\n", filename.c_str());
166     }
167   }
168
169   return size;
170 }
171
172 } // namespace Adaptor
173
174 } // namespace Internal
175
176 } // namespace Dali