Skip to content
Browse files

adds LoadFile to CFileUtils, copied from CTextureBase::LoadFromFileIn…

…ternal
  • Loading branch information...
1 parent 0aa4105 commit 230afda785ecb5b409e7697fd0566e0570009976 Jonathan Marshall committed with May 13, 2013
Showing with 74 additions and 0 deletions.
  1. +73 −0 xbmc/utils/FileUtils.cpp
  2. +1 −0 xbmc/utils/FileUtils.h
View
73 xbmc/utils/FileUtils.cpp
@@ -129,3 +129,76 @@ bool CFileUtils::RemoteAccessAllowed(const CStdString &strPath)
}
return false;
}
+
+
+unsigned int CFileUtils::LoadFile(const std::string &filename, void* &outputBuffer)
+{
+ outputBuffer = NULL;
+ if (filename.empty())
+ return 0;
+
+ // Read image into memory to use our vfs
+ unsigned char *inputBuff = NULL;
+ unsigned int inputBuffSize = 0;
+
+ XFILE::CFile file;
+ if (file.Open(filename.c_str(), READ_TRUNCATED))
+ {
+ /*
+ GetLength() will typically return values that fall into three cases:
+ 1. The real filesize. This is the typical case.
+ 2. Zero. This is the case for some http:// streams for example.
+ 3. Some value smaller than the real filesize. This is the case for an expanding file.
+
+ In order to handle all three cases, we read the file in chunks, relying on Read()
+ returning 0 at EOF. To minimize (re)allocation of the buffer, the chunksize in
+ cases 1 and 3 is set to one byte larger than the value returned by GetLength().
+ The chunksize in case 2 is set to the larger of 64k and GetChunkSize().
+
+ We fill the buffer entirely before reallocation. Thus, reallocation never occurs in case 1
+ as the buffer is larger than the file, so we hit EOF before we hit the end of buffer.
+
+ To minimize reallocation, we double the chunksize each time up to a maxchunksize of 2MB.
+ */
+ unsigned int filesize = (unsigned int)file.GetLength();
+ unsigned int chunksize = filesize ? (filesize + 1) : std::max(65536U, (unsigned int)file.GetChunkSize());
+ unsigned int maxchunksize = 2048*1024U; /* max 2MB chunksize */
+ unsigned char *tempinputBuff = NULL;
+
+ unsigned int total_read = 0, free_space = 0;
+ while (true)
+ {
+ if (!free_space)
+ { // (re)alloc
+ inputBuffSize += chunksize;
+ tempinputBuff = (unsigned char *)realloc(inputBuff, inputBuffSize);
+ if (!tempinputBuff)
+ {
+ CLog::Log(LOGERROR, "%s unable to allocate buffer of size %u", __FUNCTION__, inputBuffSize);
+ free(inputBuff);
+ file.Close();
+ return 0;
+ }
+ inputBuff = tempinputBuff;
+ free_space = chunksize;
+ chunksize = std::min(chunksize*2, maxchunksize);
+ }
+ unsigned int read = file.Read(inputBuff + total_read, free_space);
+ free_space -= read;
+ total_read += read;
+ if (!read)
+ break;
+ }
+ inputBuffSize = total_read;
+ file.Close();
+
+ if (inputBuffSize == 0)
+ return 0;
+
+ outputBuffer = (void *) inputBuff;
+ return inputBuffSize;
+ }
+
+ return 0;
+}
+
View
1 xbmc/utils/FileUtils.h
@@ -8,4 +8,5 @@ class CFileUtils
static bool DeleteItem(const CStdString &strPath, bool force=false);
static bool RenameFile(const CStdString &strFile);
static bool RemoteAccessAllowed(const CStdString &strPath);
+ static unsigned int LoadFile(const std::string &filename, void* &outputBuffer);
};

0 comments on commit 230afda

Please sign in to comment.
Something went wrong with that request. Please try again.