fileiter.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 909 行 · 第 1/2 页

CPP
909
字号
/* * * Copyright (c) 1998-2002 * John Maddock * * Use, modification and distribution are subject to the  * Boost Software License, Version 1.0. (See accompanying file  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * */  /*  *   LOCATION:    see http://www.boost.org for most recent version.  *   FILE:        fileiter.cpp  *   VERSION:     see <boost/version.hpp>  *   DESCRIPTION: Implements file io primitives + directory searching for class boost::RegEx.  */#define BOOST_REGEX_SOURCE#include <climits>#include <stdexcept>#include <string>#include <boost/throw_exception.hpp>#include <boost/regex/v4/fileiter.hpp>#include <boost/regex/v4/regex_workaround.hpp>#include <boost/regex/pattern_except.hpp>#include <cstdio>#if defined(BOOST_NO_STDC_NAMESPACE)namespace std{   using ::sprintf;   using ::fseek;   using ::fread;   using ::ftell;   using ::fopen;   using ::fclose;   using ::FILE;   using ::strcpy;   using ::strcpy;   using ::strcat;   using ::strcmp;   using ::strlen;}#endif#ifndef BOOST_REGEX_NO_FILEITER#if defined(__CYGWIN__) || defined(__CYGWIN32__)#include <sys/cygwin.h>#endif#ifdef BOOST_MSVC#  pragma warning(disable: 4800)#endifnamespace boost{   namespace re_detail{// start with the operating system specific stuff:#if (defined(__BORLANDC__) || defined(BOOST_REGEX_FI_WIN32_DIR) || defined(BOOST_MSVC)) && !defined(BOOST_RE_NO_WIN32)// platform is DOS or Windows// directories are separated with '\\'// and names are insensitive of caseBOOST_REGEX_DECL const char* _fi_sep = "\\";const char* _fi_sep_alt = "/";#define BOOST_REGEX_FI_TRANSLATE(c) std::tolower(c)#else// platform is not DOS or Windows// directories are separated with '/'// and names are sensitive of caseBOOST_REGEX_DECL const char* _fi_sep = "/";const char* _fi_sep_alt = _fi_sep;#define BOOST_REGEX_FI_TRANSLATE(c) c#endif#ifdef BOOST_REGEX_FI_WIN32_MAPvoid mapfile::open(const char* file){#if defined(BOOST_NO_ANSI_APIS)   int filename_size = strlen(file);   LPWSTR wide_file = (LPWSTR)_alloca( (filename_size + 1) * sizeof(WCHAR) );   if(::MultiByteToWideChar(CP_ACP, 0,  file, filename_size,  wide_file, filename_size + 1) == 0)      hfile = INVALID_HANDLE_VALUE;   else      hfile = CreateFileW(wide_file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);#elif defined(__CYGWIN__)||defined(__CYGWIN32__)   char win32file[ MAX_PATH ];   cygwin_conv_to_win32_path( file, win32file );   hfile = CreateFileA(win32file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);#else   hfile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);#endif   if(hfile != INVALID_HANDLE_VALUE)   {      hmap = CreateFileMapping(hfile, 0, PAGE_READONLY, 0, 0, 0);      if((hmap == INVALID_HANDLE_VALUE) || (hmap == NULL))      {         CloseHandle(hfile);         hmap = 0;         hfile = 0;         std::runtime_error err("Unable to create file mapping.");         boost::re_detail::raise_runtime_error(err);      }      _first = static_cast<const char*>(MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0));      if(_first == 0)      {         CloseHandle(hmap);         CloseHandle(hfile);         hmap = 0;         hfile = 0;         std::runtime_error err("Unable to create file mapping.");      }      _last = _first + GetFileSize(hfile, 0);   }   else   {      hfile = 0;#ifndef BOOST_NO_EXCEPTIONS      throw std::runtime_error("Unable to open file.");#else      BOOST_REGEX_NOEH_ASSERT(hfile != INVALID_HANDLE_VALUE);#endif   }}void mapfile::close(){   if(hfile != INVALID_HANDLE_VALUE)   {      UnmapViewOfFile((void*)_first);      CloseHandle(hmap);      CloseHandle(hfile);      hmap = hfile = 0;      _first = _last = 0;   }}#elif !defined(BOOST_RE_NO_STL)mapfile_iterator& mapfile_iterator::operator = (const mapfile_iterator& i){   if(file && node)      file->unlock(node);   file = i.file;   node = i.node;   offset = i.offset;   if(file)      file->lock(node);   return *this;}mapfile_iterator& mapfile_iterator::operator++ (){   if((++offset == mapfile::buf_size) && file)   {      ++node;      offset = 0;      file->lock(node);      file->unlock(node-1);   }   return *this;}mapfile_iterator mapfile_iterator::operator++ (int){   mapfile_iterator temp(*this);   if((++offset == mapfile::buf_size) && file)   {      ++node;      offset = 0;      file->lock(node);      file->unlock(node-1);   }   return temp;}mapfile_iterator& mapfile_iterator::operator-- (){   if((offset == 0) && file)   {      --node;      offset = mapfile::buf_size - 1;      file->lock(node);      file->unlock(node + 1);   }   else      --offset;   return *this;}mapfile_iterator mapfile_iterator::operator-- (int){   mapfile_iterator temp(*this);   if((offset == 0) && file)   {      --node;      offset = mapfile::buf_size - 1;      file->lock(node);      file->unlock(node + 1);   }   else      --offset;   return temp;}mapfile_iterator operator + (const mapfile_iterator& i, long off){   mapfile_iterator temp(i);   temp += off;   return temp;}mapfile_iterator operator - (const mapfile_iterator& i, long off){   mapfile_iterator temp(i);   temp -= off;   return temp;}mapfile::iterator mapfile::begin()const{   return mapfile_iterator(this, 0);}mapfile::iterator mapfile::end()const{   return mapfile_iterator(this, _size);}void mapfile::lock(pointer* node)const{   BOOST_ASSERT(node >= _first);   BOOST_ASSERT(node <= _last);   if(node < _last)   {      if(*node == 0)      {         if(condemed.empty())         {            *node = new char[sizeof(int) + buf_size];            *(reinterpret_cast<int*>(*node)) = 1;         }         else         {            pointer* p = condemed.front();            condemed.pop_front();            *node = *p;            *p = 0;            *(reinterpret_cast<int*>(*node)) = 1;         }         std::fseek(hfile, (node - _first) * buf_size, SEEK_SET);         if(node == _last - 1)            std::fread(*node + sizeof(int), _size % buf_size, 1, hfile);         else            std::fread(*node + sizeof(int), buf_size, 1, hfile);      }      else      {         if(*reinterpret_cast<int*>(*node) == 0)         {            *reinterpret_cast<int*>(*node) = 1;            condemed.remove(node);         }         else            ++(*reinterpret_cast<int*>(*node));      }   }}void mapfile::unlock(pointer* node)const{   BOOST_ASSERT(node >= _first);   BOOST_ASSERT(node <= _last);   if(node < _last)   {      if(--(*reinterpret_cast<int*>(*node)) == 0)      {         condemed.push_back(node);      }   }}long int get_file_length(std::FILE* hfile){   long int result;   std::fseek(hfile, 0, SEEK_END);   result = std::ftell(hfile);   std::fseek(hfile, 0, SEEK_SET);   return result;}void mapfile::open(const char* file){   hfile = std::fopen(file, "rb");#ifndef BOOST_NO_EXCEPTIONS   try{#endif   if(hfile != 0)   {      _size = get_file_length(hfile);      long cnodes = (_size + buf_size - 1) / buf_size;      // check that number of nodes is not too high:      if(cnodes > (long)((INT_MAX) / sizeof(pointer*)))      {         std::fclose(hfile);         hfile = 0;         _size = 0;         return;      }      _first = new pointer[(int)cnodes];      _last = _first + cnodes;      std::memset(_first, 0, cnodes*sizeof(pointer));   }   else   {       std::runtime_error err("Unable to open file.");   }#ifndef BOOST_NO_EXCEPTIONS   }catch(...)   { close(); throw; }#endif}void mapfile::close(){   if(hfile != 0)   {      pointer* p = _first;      while(p != _last)      {         if(*p)            delete[] *p;         ++p;      }      delete[] _first;      _size = 0;      _first = _last = 0;      std::fclose(hfile);      hfile = 0;      condemed.erase(condemed.begin(), condemed.end());   }}#endifinline _fi_find_handle find_first_file(const char* wild,  _fi_find_data& data){#ifdef BOOST_NO_ANSI_APIS   std::size_t wild_size = std::strlen(wild);   LPWSTR wide_wild = (LPWSTR)_alloca( (wild_size + 1) * sizeof(WCHAR) );   if (::MultiByteToWideChar(CP_ACP, 0,  wild, wild_size,  wide_wild, wild_size + 1) == 0)      return _fi_invalid_handle;   return FindFirstFileW(wide_wild, &data);#else   return FindFirstFileA(wild, &data);#endif}inline bool find_next_file(_fi_find_handle hf,  _fi_find_data& data){#ifdef BOOST_NO_ANSI_APIS   return FindNextFileW(hf, &data);#else   return FindNextFileA(hf, &data);#endif}   inline void copy_find_file_result_with_overflow_check(const _fi_find_data& data,  char* path, size_t max_size){#ifdef BOOST_NO_ANSI_APIS   if (::WideCharToMultiByte(CP_ACP, 0,  data.cFileName, -1,  path, max_size,  NULL, NULL) == 0)      re_detail::overflow_error_if_not_zero(1);#else   re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(path, max_size,  data.cFileName));#endif}inline bool is_not_current_or_parent_path_string(const _fi_find_data& data){#ifdef BOOST_NO_ANSI_APIS   return (std::wcscmp(data.cFileName, L".") && std::wcscmp(data.cFileName, L".."));#else   return (std::strcmp(data.cFileName, ".") && std::strcmp(data.cFileName, ".."));#endif}file_iterator::file_iterator(){   _root = _path = 0;   ref = 0;#ifndef BOOST_NO_EXCEPTIONS   try{#endif   _root = new char[MAX_PATH];   BOOST_REGEX_NOEH_ASSERT(_root)   _path = new char[MAX_PATH];   BOOST_REGEX_NOEH_ASSERT(_path)   ptr = _path;   *_path = 0;   *_root = 0;   ref = new file_iterator_ref();   BOOST_REGEX_NOEH_ASSERT(ref)   ref->hf = _fi_invalid_handle;   ref->count = 1;#ifndef BOOST_NO_EXCEPTIONS   }   catch(...)   {      delete[] _root;      delete[] _path;      delete ref;      throw;   }#endif}file_iterator::file_iterator(const char* wild){   _root = _path = 0;   ref = 0;#ifndef BOOST_NO_EXCEPTIONS   try{#endif   _root = new char[MAX_PATH];   BOOST_REGEX_NOEH_ASSERT(_root)   _path = new char[MAX_PATH];   BOOST_REGEX_NOEH_ASSERT(_path)   re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, wild));   ptr = _root;   while(*ptr)++ptr;   while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;   if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )   {     _root[1]='\0';     re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));   }   else   {     *ptr = 0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?