/* * $Id$ * Copyright (C) 2010 gingko - http://gingko.homeip.net/ * * This file is part of Pouchin TV Mod, a free DVB-T viewer. * See http://www.pouchintv.fr/ for updates. * * Pouchin TV Mod is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Pouchin TV Mod is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * * Most files of this project have been changed from the Pouchin TV * project (Copyright (C) 2006 Pouchin ), * to use with a modified version of this software. * See http://pouchinteve.free.fr/ for the original project. */ /** \file * \brief Définition d'une classe permettant l'accès à un fichier en mode "file mapping" * * Ce fichier définit une classe permettant d'accèder à un fichier en mode "file mapping", * dans lequel une partie du contenu du fichier est placée dans une fenêtre de mémoire * dédiée, permettant un accès rapide à son contenu. **/ #pragma once #include #include #include "sbuffer.h" typedef const UINT8 * LPCBYTE; class FileMapping { struct Mapping { HANDLE hMap; DWORD flProtect; Mapping(DWORD flProt) : hMap(INVALID_HANDLE_VALUE), flProtect(flProt) { } bool isValid() const { return hMap != INVALID_HANDLE_VALUE; } bool Set(HANDLE hFile, UINT64 qwFileSize); void Reset(); ~Mapping() { Reset(); } }; struct View { PUINT8 ptr; UINT64 nStart; UINT32 nSize; DWORD dwDesiredAccess; UINT nFlushCount; View(DWORD dwDesAcc) : ptr(NULL), nStart(0), nSize(0), dwDesiredAccess(dwDesAcc), nFlushCount(0) { } enum : UINT32 { INVALID_OFFSET = UINT32(-1) }; bool isValid() const { return ptr != NULL && nSize != 0; } bool Map(Mapping & cMap, UINT64 nSt, UINT32 nSz) throw(...); void Unmap() throw(...); bool isInView(UINT64 nPos, UINT32 Sz = 0) const { return isValid() && nPos >= nStart && nPos+Sz < nStart+nSize; } UINT32 viewOffset(UINT64 nPos) const { return isInView(nPos) ? UINT32(nPos - nStart) : INVALID_OFFSET; } MemRng GetRng() const { return MemRng(ptr, nSize); } ~View() throw(...) { Unmap(); } }; HANDLE hFile; Mapping cMap; View cView; UINT32 dwSysGran; UINT32 dwMaxMapSize; INT last_progress; bool bWriteMode; public: UINT64 qwFileSize; UINT64 qwLastOffset; //!< offset absolu calculé après le dernier appel à 'remap' INT64 qwRemSize; //!< Taille restante calculée après le dernier appel à 'remap' /// Obtenir la granularité de l'allocation système static UINT32 GetSystemGranularity(); static bool isValid(HANDLE hHandle) { return hHandle != INVALID_HANDLE_VALUE; } bool isValid() const { return isValid(hFile);} /** \brief Positionnement dans le fichier * \param[in] qwPos Position absolue désirée * \param[in] nNeeded Quantité de mémoire disponible souhaitée dans la vue * \param[out] sMm Descripteur d'intervalle mémoire initialisé à la plus large vue possible pour cette position * \return Le nombre d'octets disponibles (= \p sMm.siz), ou 0 si aucun. * \note Si 0 est retourné, l'intervalle renvoyé dans \p sMm ne sera pas valide. **/ UINT seek(UINT64 qwPos, MemRng & sMm, UINT nNeeded=MAXDWORD) throw(...); /** \brief Réalignement de la vue décalée * * Vérifie que l'intervalle \p sMm est toujours entièrement inclus dans la vue, et si nécessaire, procède * à un réalignement de cette vue afin d'y inclure le maximum possible de l'intervalle. * * Normalement destiné à gérer un avancement progressif dans un fichier en cours de lecture. Utiliser * \p seek pour des déplacements aléatoires ou bien plus importants. * \param[in] sMm Intervalle de mémoire dont on requiert la disponibilité du pointeur initial * \param[in] nNeeded Quantité de mémoire disponible souhaitée dans la vue * \param[out] sMm Intervalle avec origine réajustée, et taille plafonnée si fin de fichier. * \return Le nombre d'octets disponibles, ou 0 si aucun. * \note Si 'sMm.ptr' = NULL en entrée, un repositionnement au début du fichier est effectué (avec \p seek). * \note Si 0 est retourné, l'intervalle renvoyé dans \p sMm ne sera pas valide. **/ UINT remap(MemRng & sMm, UINT nNeeded) throw(...); void reset() throw(...) { cView.Unmap(); } /// Obtenir l'offset du fichier correspondant à la position de pPtr dans la "vue". UINT64 fileoffset(PCUINT8 pPtr) const; /// Fonction retournant 1 si 'pPtr' pointe la fin du fichier, -1 si 'pPtr' pointe au-delà /// de la fin du fichier, et 0 si la fin du fichier n'est pas atteinte. int eof(PUINT8 pPtr) const; // Retourner la progression dans le fichier, sur une échelle de 0 à 'scale' : UINT32 getProgress(UINT32 scale) const { return UINT32(qwLastOffset*scale/qwFileSize); } INT chkProgress(UINT scale) { INT progress = (INT)getProgress(scale); if (progress == last_progress) return -1; return last_progress = progress; } /** \brief Constructeur * * Initialisation d'un accès fichier en mode "file mapping" * \param[in] bWrite \p true si fichier ouvert en écriture * \param[in] pszFileName Si != NULL, nom de fichier à ouvrir * \param[in] viewsize Taille de vue souhaitée (ajustée à la valeur de granularité inférieure) **/ FileMapping(bool bWrite, PCTSTR pszFileName=NULL, UINT32 viewsize=0x200000); UINT64 GetFileSize() const; bool OpenFile(PCTSTR pszFileName); bool SetEndOfFile(UINT64 nSize); bool SetEndOfFile(MemRng sMm); void CloseFile(); /// Destructeur ~FileMapping(); };