LCOV - code coverage report
Current view: top level - source/ps - Filesystem.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 41 67 61.2 %
Date: 2023-01-19 00:18:29 Functions: 14 16 87.5 %

          Line data    Source code
       1             : /* Copyright (C) 2022 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             : 
      20             : #include "Filesystem.h"
      21             : 
      22             : #include "lib/sysdep/dir_watch.h"
      23             : #include "lib/utf8.h"
      24             : #include "ps/CLogger.h"
      25             : #include "ps/CStr.h"
      26             : #include "ps/Profile.h"
      27             : 
      28             : #include <boost/filesystem.hpp>
      29             : 
      30           1 : PIVFS g_VFS;
      31             : 
      32           1 : static std::vector<std::pair<FileReloadFunc, void*> > g_ReloadFuncs;
      33             : 
      34        2488 : bool VfsFileExists(const VfsPath& pathname)
      35             : {
      36        2488 :     return g_VFS->GetFileInfo(pathname, 0) == INFO::OK;
      37             : }
      38             : 
      39          14 : bool VfsDirectoryExists(const VfsPath& pathname)
      40             : {
      41          14 :     ENSURE(pathname.IsDirectory());
      42          14 :     return g_VFS->GetDirectoryEntries(pathname, NULL, NULL) == INFO::OK;
      43             : }
      44             : 
      45          39 : void RegisterFileReloadFunc(FileReloadFunc func, void* obj)
      46             : {
      47          39 :     g_ReloadFuncs.emplace_back(func, obj);
      48          39 : }
      49             : 
      50          39 : void UnregisterFileReloadFunc(FileReloadFunc func, void* obj)
      51             : {
      52          78 :     g_ReloadFuncs.erase(std::remove(g_ReloadFuncs.begin(), g_ReloadFuncs.end(), std::make_pair(func, obj)));
      53          39 : }
      54             : 
      55             : // try to skip unnecessary work by ignoring uninteresting notifications.
      56           0 : static bool CanIgnore(const DirWatchNotification& notification)
      57             : {
      58             :     // ignore directories
      59           0 :     const OsPath& pathname = notification.Pathname();
      60           0 :     if(pathname.IsDirectory())
      61           0 :         return true;
      62             : 
      63             :     // ignore uninteresting file types (e.g. temp files, or the
      64             :     // hundreds of XMB files that are generated from XML)
      65           0 :     const OsPath extension = pathname.Extension();
      66           0 :     const wchar_t* extensionsToIgnore[] = { L".xmb", L".tmp" };
      67           0 :     for(size_t i = 0; i < ARRAY_SIZE(extensionsToIgnore); i++)
      68             :     {
      69           0 :         if(extension == extensionsToIgnore[i])
      70           0 :             return true;
      71             :     }
      72             : 
      73           0 :     return false;
      74             : }
      75             : 
      76           0 : Status ReloadChangedFiles()
      77             : {
      78           0 :     PROFILE3("hotload");
      79             : 
      80           0 :     std::vector<DirWatchNotification> notifications;
      81           0 :     RETURN_STATUS_IF_ERR(dir_watch_Poll(notifications));
      82           0 :     for(size_t i = 0; i < notifications.size(); i++)
      83             :     {
      84           0 :         if(!CanIgnore(notifications[i]))
      85             :         {
      86           0 :             VfsPath pathname;
      87           0 :             RETURN_STATUS_IF_ERR(g_VFS->GetVirtualPath(notifications[i].Pathname(), pathname));
      88           0 :             RETURN_STATUS_IF_ERR(g_VFS->RemoveFile(pathname));
      89           0 :             RETURN_STATUS_IF_ERR(g_VFS->RepopulateDirectory(pathname.Parent()/""));
      90             : 
      91             :             // Tell each hotloadable system about this file change:
      92             : 
      93           0 :             for (size_t j = 0; j < g_ReloadFuncs.size(); ++j)
      94           0 :                 g_ReloadFuncs[j].first(g_ReloadFuncs[j].second, pathname);
      95             :         }
      96             :     }
      97           0 :     return INFO::OK;
      98             : }
      99             : 
     100          80 : std::wstring GetWstringFromWpath(const fs::wpath& path)
     101             : {
     102             : #if BOOST_FILESYSTEM_VERSION == 3
     103          80 :     return path.wstring();
     104             : #else
     105             :     return path.string();
     106             : #endif
     107             : }
     108             : 
     109             : 
     110        2479 : CVFSFile::CVFSFile()
     111        2479 :     : m_BufferSize(0)
     112             : {
     113        2479 : }
     114             : 
     115        2479 : CVFSFile::~CVFSFile()
     116             : {
     117        2479 : }
     118             : 
     119        2479 : PSRETURN CVFSFile::Load(const PIVFS& vfs, const VfsPath& filename, bool log /* = true */)
     120             : {
     121             :     // Load should never be called more than once, so complain
     122        2479 :     if (m_Buffer)
     123             :     {
     124           0 :         DEBUG_WARN_ERR(ERR::LOGIC);
     125           0 :         return PSRETURN_CVFSFile_AlreadyLoaded;
     126             :     }
     127             : 
     128        2479 :     Status ret = vfs->LoadFile(filename, m_Buffer, m_BufferSize);
     129        2479 :     if (ret != INFO::OK)
     130             :     {
     131           6 :         if (log)
     132           6 :             LOGERROR("CVFSFile: file %s couldn't be opened (vfs_load: %lld)", filename.string8(), (long long)ret);
     133           6 :         m_Buffer.reset();
     134           6 :         m_BufferSize = 0;
     135           6 :         return PSRETURN_CVFSFile_LoadFailed;
     136             :     }
     137             : 
     138        2473 :     return PSRETURN_OK;
     139             : }
     140             : 
     141        2473 : const u8* CVFSFile::GetBuffer() const
     142             : {
     143        2473 :     return m_Buffer.get();
     144             : }
     145             : 
     146        4888 : size_t CVFSFile::GetBufferSize() const
     147             : {
     148        4888 :     return m_BufferSize;
     149             : }
     150             : 
     151           5 : CStr CVFSFile::GetAsString() const
     152             : {
     153           5 :     return std::string((char*)GetBuffer(), GetBufferSize());
     154             : }
     155             : 
     156        2415 : CStr CVFSFile::DecodeUTF8() const
     157             : {
     158        2415 :     const u8* buffer = GetBuffer();
     159             : 
     160             :     // Detect if there's a UTF-8 BOM and strip it
     161        2415 :     if (GetBufferSize() >= 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF)
     162             :     {
     163           0 :         return std::string(&buffer[3], buffer + GetBufferSize());
     164             :     }
     165             :     else
     166             :     {
     167        2415 :         return std::string(buffer, buffer + GetBufferSize());
     168             :     }
     169           3 : }

Generated by: LCOV version 1.13