Files
wagic/thirdparty/zipFS/fileio.h
2015-09-26 21:52:07 +02:00

257 lines
6.4 KiB
C++
Raw Blame History

// bfileio.h: interface for the binary file i/o.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 Tanguy Fautre
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// Tanguy Fautr<74>E
// softdev@telenet.be
//
//////////////////////////////////////////////////////////////////////
//
// File I/O Facilities.
// ********************
//
// Current version: 1.00 BETA 4 (16/07/2004)
//
// Comment: readvar() and writevar() read a little endian ordered
// value on a file and put it in a variable.
// search_iterator only accepts "<directory>/*.<ext>".
// Uses ANSI C "assert()". Define NDEBUG to turn it off.
// (note: Visual C++ define NDEBUG in Release mode)
//
// History: - 1.00 BETA 4 (16/07/2004) - Fixed small bug in UNIX search_iterator
// - 1.00 BETA 3 (27/06/2004) - Added UNIX compatibility
// - 1.00 BETA 2 (21/02/2003) - Now endianess independent
// - 1.00 BETA 1 (06/09/2002) - First public release
//
//////////////////////////////////////////////////////////////////////
#pragma once
#if defined WIN32
#include <io.h> // Windows I/O facilities (Directories)
#else
#include <dirent.h>
#include <string.h>
#endif
#include <limits.h>
namespace io_facilities {
// Global function for reading binary variables
template <class T> std::istream & readvar(std::istream & File, T & Var, const std::streamsize NbBytes);
template <class T> std::ostream & writevar(std::ostream & File, const T & Var, const std::streamsize NbBytes);
// Class for searching files and directories
// (!!! not compliant with C++ std::iterator and is thus meant for specific use !!!)
class search_iterator
{
public:
search_iterator();
search_iterator(const char * FileSpec);
~search_iterator();
operator bool () const;
search_iterator & operator ++ ();
search_iterator & begin(const char * FileSpec);
search_iterator & next();
bool end() const;
std::string Name() const;
protected:
bool m_Valid;
#if defined WIN32
intptr_t m_hFiles;
_finddata_t m_FindData;
#else
DIR * m_Directory;
std::string m_Extension;
struct dirent * m_DirectoryEntry;
#endif
};
//////////////////////////////////////////////////////////////////////
// io_facilities:: Inline Functions
//////////////////////////////////////////////////////////////////////
template <class T>
inline std::istream & readvar(std::istream & File, T & Var, const std::streamsize NbBytes)
{
// Debug test to ensure type size is big enough
assert(sizeof(T) >= size_t(NbBytes));
// Var = 0 ensure type size won't matter
T TmpVar = Var = 0;
for (std::streamsize i = 0; i < NbBytes; ++i) {
File.read(reinterpret_cast<char *>(&TmpVar), 1);
Var |= TmpVar << (i * CHAR_BIT);
}
return File;
}
template <class T>
inline std::ostream & writevar(std::ostream & File, const T & Var, const std::streamsize NbBytes)
{
// Debug test to ensure type size is big enough
assert(sizeof(T) >= size_t(NbBytes));
T TmpVar = Var;
for (std::streamsize i = 0; i < NbBytes; ++i)
File.write(reinterpret_cast<const char *>(&(TmpVar >>= (CHAR_BIT * i))), 1);
return File;
}
//////////////////////////////////////////////////////////////////////
// io_facilities::search_iterator Inline Member Functions
//////////////////////////////////////////////////////////////////////
inline search_iterator::search_iterator()
: m_Valid(false),
#if defined WIN32
m_hFiles(-1)
#else
m_Directory(NULL)
#endif
{ }
inline search_iterator::search_iterator(const char * FileSpec)
: m_Valid(false),
#if defined WIN32
m_hFiles(-1)
#else
m_Directory(NULL)
#endif
{
begin(FileSpec);
}
inline search_iterator::~search_iterator() {
#if defined WIN32
if (m_hFiles != -1) _findclose(m_hFiles);
#else
if (m_Directory != NULL) closedir(m_Directory);
#endif
}
inline search_iterator::operator bool () const {
return m_Valid;
}
inline search_iterator & search_iterator::operator ++ () {
return next();
}
inline search_iterator & search_iterator::begin(const char * FileSpec) {
#if defined WIN32
if (m_hFiles != -1) _findclose(m_hFiles);
m_Valid = ((m_hFiles = _findfirst(FileSpec, &m_FindData)) != -1);
#else
std::string DirectoryName;
if (m_Directory != NULL) closedir(m_Directory);
int i;
for (i = strlen(FileSpec); i >= 0; --i)
if (FileSpec[i] == '/') break;
if (i < 0)
DirectoryName = ".";
else
DirectoryName.assign(FileSpec + 0, FileSpec + i++);
m_Extension = FileSpec + i + 1;
std::transform(m_Extension.begin(), m_Extension.end(), m_Extension.begin(), ::tolower);
m_Valid = ((m_Directory = opendir(DirectoryName.c_str())) != NULL);
if (! m_Valid)
return (* this);
next();
#endif
return (* this);
}
inline bool search_iterator::end() const {
return false;
}
inline search_iterator & search_iterator::next() {
#if defined WIN32
m_Valid = (_findnext(m_hFiles, &m_FindData) != -1);
#else
bool Found = false;
while (! Found) {
m_Valid = ((m_DirectoryEntry = readdir(m_Directory)) != NULL);
if (m_Valid) {
std::string FileName = m_DirectoryEntry->d_name;
if (FileName[0] == '.')
Found = false;
else if (FileName.size() <= m_Extension.size())
Found = false;
else {
std::transform(FileName.begin(), FileName.end(), FileName.begin(), ::tolower);
if (std::equal(m_Extension.rbegin(), m_Extension.rend(), FileName.rbegin()))
Found = true;
}
}
else
break;
}
#endif
return (* this);
}
inline std::string search_iterator::Name() const {
#if defined WIN32
return (m_FindData.name);
#else
return (m_DirectoryEntry->d_name);
#endif
}
} // namespace io_facilities