zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
File_Ops.cpp
Go to the documentation of this file.
1 /* This file is part of the Zenipex Library (zenilib).
2  * Copyright (C) 2011 Mitchell Keith Bloch (bazald).
3  *
4  * zenilib is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * zenilib is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with zenilib. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <zeni.h>
19 
20 #include <iostream>
21 #include <fstream>
22 #include <cassert>
23 
24 #ifdef _WINDOWS
25 #include <io.h>
26 #include <shlobj.h>
27 #include <WinUser.h>
28 #else
29 #include <sys/errno.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <pwd.h>
33 #include <unistd.h>
34 #endif
35 
36 #if defined(_DEBUG) && defined(_WINDOWS)
37 #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
38 #define new DEBUG_NEW
39 #endif
40 
41 #include <Zeni/Singleton.hxx>
42 
43 #ifdef ANDROID
44 #include <jni.h>
45 #if defined(ENABLE_SLES)
46 extern "C" {
47 
48  JNIEXPORT void JNICALL Java_com_zenilib_app_ZenilibActivity_provideAssetManager(JNIEnv* env, jclass clazz, jobject assetManager) {
49  Zeni::File_Ops::init_AAssetManager(AAssetManager_fromJava(env, assetManager));
50  }
51 
52 }
53 #endif
54 #endif
55 
56 namespace Zeni {
57 
58  template class Singleton<File_Ops>;
59 
60  File_Ops * File_Ops::create() {
61  return new File_Ops;
62  }
63 
64  File_Ops::File_Ops()
65  : m_username("username"),
66  m_appdata_path("./")
67  {
70  static bool once = true;
71  if(once) {
72  once = false;
73 
74  freopen("stderr.txt", "w", stderr);
75 #if defined(_WINDOWS) || defined(NDEBUG)
76  freopen("stdout.txt", "w", stdout);
77 #else
78  FILE * const stdout_txt = popen("tee stdout.txt", "w");
79  if(stdout_txt)
80  dup2(fileno(stdout_txt), STDOUT_FILENO);
81 #endif
82  }
83 
86 #ifdef _WINDOWS
87  char username[MAX_PATH];
88  DWORD username_len = sizeof(username);
89  if(!GetUserName(username, &username_len))
90  throw File_Ops_Init_Failure();
91 #else
92  passwd * const pws = getpwuid(geteuid());
93  const char * const username = pws ? pws->pw_name : "default";
94 #endif
95  m_username = username;
96 
99 #ifdef _WINDOWS
100  char appdata_path[MAX_PATH];
101  if(SHGetFolderPath(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, SHGFP_TYPE_CURRENT, appdata_path) != S_OK)
102  throw File_Ops_Init_Failure();
103 #else
104  const char * const appdata_path = pws ? pws->pw_dir : "/tmp/";
105 #endif
106  m_appdata_path = appdata_path;
107 
110  String &unique_app_identifier = get_unique_app_identifier();
111  if(unique_app_identifier.empty())
112  unique_app_identifier = "zenilib";
113  }
114 
115  File_Ops::~File_Ops() {
116  }
117 
119  return File_Ops::get();
120  }
121 
122 #if defined(ANDROID)
123  void File_Ops::init_AAssetManager(AAssetManager * const &asset_manager) {
124  m_asset_manager = asset_manager;
125  }
126 
127  AAssetManager * const File_Ops::get_AAssetManager() {
128  if(!m_asset_manager)
129  throw File_Ops_No_AAssetManager();
130  return m_asset_manager;
131  }
132 #endif
133 
134  FILE * File_Ops::get_asset_FILE(const String &filename, off_t * const &start_, off_t * const &length_) {
135  ZENI_LOGI(("Loading asset from file '" + filename + "'.").c_str());
136 
137 #ifdef ANDROID
138  AAsset* asset = AAssetManager_open(File_Ops::get_AAssetManager(), filename.c_str(), AASSET_MODE_UNKNOWN);
139  if(!asset) {
140  ZENI_LOGE("!asset, throwing Error");
142  }
143 
144  // open asset as file descriptor
145  off_t start, length;
146  int fd = AAsset_openFileDescriptor(asset, &start, &length);
147  AAsset_close(asset);
148  if(fd < 0) {
149  ZENI_LOGE("!fd, throwing Error");
151  }
152 
153  FILE *file = fdopen(fd, "rb");
154 #else
155  FILE *file = fopen(filename.c_str(), "rb");
156 #endif
157  if(!file) {
158  ZENI_LOGE("!file, throwing Error");
160  }
161 
162 #ifndef ANDROID
163  if(fseek(file, 0, SEEK_END)) {
164  ZENI_LOGE("!fseek, throwing Error");
166  }
167 
168  off_t start = 0;
169  off_t length = ftell(file);
170 #endif
171 
172  if(fseek(file, start, SEEK_SET)) {
173  ZENI_LOGE("!fseek, throwing Error");
175  }
176 
177 #ifndef ANDROID
178  start = ftell(file);
179  length -= start;
180 #endif
181 
182  if(start_)
183  *start_ = start;
184  if(length_)
185  *length_ = length;
186 
187  return file;
188  }
189 
190  String & File_Ops::load_asset(String &memory, const String &filename) {
191  off_t length;
192  FILE * const file = get_asset_FILE(filename, 0, &length);
193 
194  try {
195  memory.resize(length, '\0');
196 
197  for(String::iterator it = memory.begin(), iend = memory.end(); it != iend; ++it) {
198  int c;
199  c = fgetc(file);
200  if(c != EOF)
201  *it = char(c);
202  else {
203  fclose(file);
204  ZENI_LOGE("Loading from fd failed, throwing Error");
206  }
207  }
208  }
209  catch(...) {
210  fclose(file);
211  throw;
212  }
213 
214  fclose(file);
215 
216  return memory;
217  }
218 
219  const String & File_Ops::get_username() {
220  return m_username;
221  }
222 
223  String File_Ops::get_appdata_path() {
224 #ifdef _WINDOWS
225  return m_appdata_path + "\\" + get_unique_app_identifier() + "\\";
226 #else
227  return m_appdata_path + "/." + get_unique_app_identifier() + "/";
228 #endif
229  }
230 
231  bool File_Ops::create_directory(const String &directory_path) {
232 #ifdef _WINDOWS
233  return CreateDirectory(directory_path.c_str(), NULL) != 0 ||
234  GetLastError() == ERROR_ALREADY_EXISTS;
235 #else
236  const int status = mkdir(directory_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
237  return !status || errno == EEXIST;
238 #endif
239  }
240 
241  bool File_Ops::remove_directory(const String &directory_path) {
242 #ifdef _WINDOWS
243  return RemoveDirectory(directory_path.c_str()) != 0 ||
244  GetLastError() == ERROR_PATH_NOT_FOUND;
245 #else
246  return !rmdir(directory_path.c_str()) || errno == ENOENT;
247 #endif
248  }
249 
250  bool File_Ops::file_exists(const String &file_path) {
251  std::ifstream fin(file_path.c_str());
252  return fin.good();
253  }
254 
255  bool File_Ops::delete_file(const String &file_path) {
256 #ifdef _WINDOWS
257  return DeleteFile(file_path.c_str()) != 0 ||
258  GetLastError() == ERROR_PATH_NOT_FOUND;
259 #else
260  return system(("rm " + file_path).c_str()) == 0;
261 #endif
262  }
263 
264  bool File_Ops::copy_file(const String &from, const String &to) {
265  std::ifstream fin(from.c_str());
266  if(!fin)
267  return false;
268 
269  std::ofstream fout(to.c_str());
270 
271  for(char c; fin.get(c); fout.put(c));
272 
273  return fout.good();
274  }
275 
276  void File_Ops::preinit(const String &unique_app_identifier_) {
277  String &unique_app_identifier = get_unique_app_identifier();
278 
279  if(!unique_app_identifier.empty())
280  throw File_Ops_Initialized();
281 
282  unique_app_identifier = unique_app_identifier_;
283  }
284 
285  String & File_Ops::get_unique_app_identifier() {
286  static String unique_app_identifier;
287  return unique_app_identifier;
288  }
289 
290 #ifdef ANDROID
291  AAssetManager * File_Ops::m_asset_manager = 0;
292 #endif
293 
294 }
#define NULL
Definition: ftobjs.h:61
GLuint start
Definition: glew.h:1239
bool empty() const
Definition: String.cpp:325
FILE * file
Definition: visualinfo.c:88
const char * c_str() const
Definition: String.cpp:467
void resize(size_t n, char c)
Definition: String.cpp:316
iterator end()
Definition: String.cpp:301
GLsizei GLsizei * length
Definition: gl2ext.h:792
const GLfloat * c
Definition: glew.h:14913
iterator begin()
Definition: String.cpp:298
#define EOF
Definition: afmparse.c:57
void ZENI_LOGE(const Zeni::String &str)
Definition: Android.h:59
jmp_buf env
Definition: jumphack.c:12
#define SEEK_SET
Definition: zconf.h:249
#define SEEK_END
Definition: zconf.h:251
void ZENI_LOGI(const Zeni::String &str)
Definition: Android.h:53
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
def file_exists
Definition: utils.py:93
File_Ops & get_File_Ops()
Get access to the singleton.
Definition: File_Ops.cpp:118