Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Filesystem.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. 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 General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "precompiled.h"
19 #include "Filesystem.h"
20 
21 #include "gui/GUIManager.h"
22 #include "ps/CLogger.h"
23 #include "ps/Profile.h"
24 
25 #include "lib/res/h_mgr.h" // h_reload
26 #include "lib/sysdep/dir_watch.h"
27 #include "lib/utf8.h"
28 
29 
31 
32 static std::vector<std::pair<FileReloadFunc, void*> > g_ReloadFuncs;
33 
34 bool VfsFileExists(const VfsPath& pathname)
35 {
36  return g_VFS->GetFileInfo(pathname, 0) == INFO::OK;
37 }
38 
40 {
41  g_ReloadFuncs.push_back(std::make_pair(func, obj));
42 }
43 
45 {
46  g_ReloadFuncs.erase(std::remove(g_ReloadFuncs.begin(), g_ReloadFuncs.end(), std::make_pair(func, obj)));
47 }
48 
49 // try to skip unnecessary work by ignoring uninteresting notifications.
50 static bool CanIgnore(const DirWatchNotification& notification)
51 {
52  // ignore directories
53  const OsPath& pathname = notification.Pathname();
54  if(pathname.IsDirectory())
55  return true;
56 
57  // ignore uninteresting file types (e.g. temp files, or the
58  // hundreds of XMB files that are generated from XML)
59  const OsPath extension = pathname.Extension();
60  const wchar_t* extensionsToIgnore[] = { L".xmb", L".tmp" };
61  for(size_t i = 0; i < ARRAY_SIZE(extensionsToIgnore); i++)
62  {
63  if(extension == extensionsToIgnore[i])
64  return true;
65  }
66 
67  return false;
68 }
69 
71 {
72  PROFILE3("hotload");
73 
74  std::vector<DirWatchNotification> notifications;
75  RETURN_STATUS_IF_ERR(dir_watch_Poll(notifications));
76  for(size_t i = 0; i < notifications.size(); i++)
77  {
78  if(!CanIgnore(notifications[i]))
79  {
80  VfsPath pathname;
81  RETURN_STATUS_IF_ERR(g_VFS->GetVirtualPath(notifications[i].Pathname(), pathname));
82  RETURN_STATUS_IF_ERR(g_VFS->RemoveFile(pathname));
83  RETURN_STATUS_IF_ERR(g_VFS->RepopulateDirectory(pathname.Parent()/""));
84 
85  // Tell each hotloadable system about this file change:
86 
88 
89  for (size_t j = 0; j < g_ReloadFuncs.size(); ++j)
90  g_ReloadFuncs[j].first(g_ReloadFuncs[j].second, pathname);
91 
93  }
94  }
95  return INFO::OK;
96 }
97 
98 std::wstring GetWstringFromWpath(const fs::wpath& path)
99 {
100 #if BOOST_FILESYSTEM_VERSION == 3
101  return path.wstring();
102 #else
103  return path.string();
104 #endif
105 }
106 
107 
109  : m_BufferSize(0)
110 {
111 }
112 
114 {
115 }
116 
117 PSRETURN CVFSFile::Load(const PIVFS& vfs, const VfsPath& filename)
118 {
119  // Load should never be called more than once, so complain
120  if (m_Buffer)
121  {
124  }
125 
126  Status ret = vfs->LoadFile(filename, m_Buffer, m_BufferSize);
127  if (ret != INFO::OK)
128  {
129  LOGERROR(L"CVFSFile: file %ls couldn't be opened (vfs_load: %lld)", filename.string().c_str(), (long long)ret);
130  m_Buffer.reset();
131  m_BufferSize = 0;
133  }
134 
135  return PSRETURN_OK;
136 }
137 
138 const u8* CVFSFile::GetBuffer() const
139 {
140  return m_Buffer.get();
141 }
142 
144 {
145  return m_BufferSize;
146 }
147 
149 {
150  return std::string((char*)GetBuffer(), GetBufferSize());
151 }
152 
154 {
155  const u8* buffer = GetBuffer();
156 
157  // Detect if there's a UTF-8 BOM and strip it
158  if (GetBufferSize() >= 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF)
159  {
160  return std::string(&buffer[3], buffer + GetBufferSize());
161  }
162  else
163  {
164  return std::string(buffer, buffer + GetBufferSize());
165  }
166 }
static bool CanIgnore(const DirWatchNotification &notification)
Definition: Filesystem.cpp:50
#define u8
Definition: types.h:39
const Status LOGIC
Definition: status.h:409
CStr DecodeUTF8() const
Returns contents of a UTF-8 encoded file as a string with optional BOM removed.
Definition: Filesystem.cpp:153
const OsPath & Pathname() const
Definition: dir_watch.h:69
size_t m_BufferSize
Definition: Filesystem.h:102
const PSRETURN PSRETURN_CVFSFile_LoadFailed
const Status OK
Definition: status.h:386
#define LOGERROR
Definition: CLogger.h:35
const PSRETURN PSRETURN_OK
Definition: Errors.h:103
bool IsDirectory() const
Definition: path.h:143
shared_ptr< IVFS > PIVFS
Definition: vfs.h:226
Path Parent() const
Definition: path.h:150
CGUIManager * g_GUI
Definition: GUIManager.cpp:32
std::wstring GetWstringFromWpath(const fs::wpath &path)
Helper function to handle API differences between Boost Filesystem v2 and v3.
Definition: Filesystem.cpp:98
#define ARRAY_SIZE(name)
CStr GetAsString() const
Returns contents of file as a string.
Definition: Filesystem.cpp:148
const PSRETURN PSRETURN_CVFSFile_AlreadyLoaded
Status(* FileReloadFunc)(void *param, const VfsPath &path)
callback function type for file change notifications
Definition: Filesystem.h:36
Status ReloadChangedFiles()
poll for directory change notifications and reload all affected files.
Definition: Filesystem.cpp:70
void UnregisterFileReloadFunc(FileReloadFunc func, void *obj)
delete a callback function registered with RegisterFileReloadFunc (removes any with the same func and...
Definition: Filesystem.cpp:44
u32 PSRETURN
Definition: Errors.h:75
void RegisterFileReloadFunc(FileReloadFunc func, void *obj)
register a callback function to be called by ReloadChangedFiles
Definition: Filesystem.cpp:39
Definition: path.h:75
const String & string() const
Definition: path.h:123
LIB_API Status dir_watch_Poll(DirWatchNotifications &notifications)
return all pending directory watch notifications.
Definition: dir_watch.cpp:33
Status h_reload(const PIVFS &vfs, const VfsPath &pathname)
Definition: h_mgr.cpp:637
const u8 * GetBuffer() const
Returns buffer of this file as a stream of bytes.
Definition: Filesystem.cpp:138
i64 Status
Error handling system.
Definition: status.h:171
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
Definition: debug.h:331
const char * extension
Definition: mongoose.cpp:1736
shared_ptr< u8 > m_Buffer
Definition: Filesystem.h:101
#define PROFILE3(name)
Definition: Profile.h:201
Path Extension() const
Definition: path.h:176
PSRETURN Load(const PIVFS &vfs, const VfsPath &filename)
Returns either PSRETURN_OK or PSRETURN_CVFSFile_LoadFailed.
Definition: Filesystem.cpp:117
bool VfsFileExists(const VfsPath &pathname)
Definition: Filesystem.cpp:34
size_t GetBufferSize() const
Definition: Filesystem.cpp:143
static std::vector< std::pair< FileReloadFunc, void * > > g_ReloadFuncs
Definition: Filesystem.cpp:32
PIVFS g_VFS
Definition: Filesystem.cpp:30
Status ReloadChangedFiles(const VfsPath &path)
Call when a file has bee modified, to hotload pages if their .xml files changed.
Definition: GUIManager.cpp:172
#define RETURN_STATUS_IF_ERR(expression)
Definition: status.h:276