/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #ifndef INCLUDED_STORE_SOURCE_STORDATA_HXX #define INCLUDED_STORE_SOURCE_STORDATA_HXX #include "sal/config.h" #include "sal/types.h" #include "sal/macros.h" #include "store/types.h" #include "storbase.hxx" namespace store { /*======================================================================== * * OStoreDataPageData. * *======================================================================*/ #define STORE_MAGIC_DATAPAGE sal_uInt32(0x94190310) struct OStoreDataPageData : public store::OStorePageData { typedef OStorePageData base; typedef OStoreDataPageData self; typedef OStorePageDescriptor D; /** Representation. */ sal_uInt8 m_pData[1]; /** type. */ static const sal_uInt32 theTypeId = STORE_MAGIC_DATAPAGE; /** size. */ static const size_t theSize = 0; static const sal_uInt16 thePageSize = base::theSize + self::theSize; static_assert(STORE_MINIMUM_PAGESIZE >= self::thePageSize, "got to be at least equal in size"); /** capacity. */ static sal_uInt16 capacity (const D& rDescr) // @see inode::ChunkDescriptor { return (store::ntohs(rDescr.m_nSize) - self::thePageSize); } sal_uInt16 capacity() const { return self::capacity (base::m_aDescr); } /** usage. */ sal_uInt16 usage() const { return (store::ntohs(base::m_aDescr.m_nUsed) - self::thePageSize); } /** Construction. */ explicit OStoreDataPageData (sal_uInt16 nPageSize = self::thePageSize) : base (nPageSize) { base::m_aGuard.m_nMagic = store::htonl(self::theTypeId); base::m_aDescr.m_nUsed = store::htons(self::thePageSize); if (capacity()) memset (m_pData, 0, capacity()); } }; /*======================================================================== * * OStoreDataPageObject. * *======================================================================*/ class OStoreDataPageObject : public store::OStorePageObject { typedef OStorePageObject base; typedef OStoreDataPageData page; public: /** Construction. */ explicit OStoreDataPageObject (PageHolder const & rxPage = PageHolder()) : OStorePageObject (rxPage) {} /** External representation. */ virtual storeError guard (sal_uInt32 nAddr) SAL_OVERRIDE; virtual storeError verify (sal_uInt32 nAddr) const SAL_OVERRIDE; }; /*======================================================================== * * OStoreIndirectionPageData. * *======================================================================*/ #define STORE_MAGIC_INDIRECTPAGE sal_uInt32(0x89191107) struct OStoreIndirectionPageData : public store::OStorePageData { typedef OStorePageData base; typedef OStoreIndirectionPageData self; typedef OStorePageGuard G; typedef OStorePageDescriptor D; /** Representation. */ G m_aGuard; sal_uInt32 m_pData[1]; /** type. */ static const sal_uInt32 theTypeId = STORE_MAGIC_INDIRECTPAGE; /** size. */ static const size_t theSize = sizeof(G); static const sal_uInt16 thePageSize = base::theSize + self::theSize; static_assert(STORE_MINIMUM_PAGESIZE >= self::thePageSize, "got to be at least equal in size"); /** capacity. */ static sal_uInt16 capacity (const D& rDescr) { return (store::ntohs(rDescr.m_nSize) - self::thePageSize); } sal_uInt16 capacity() const { return self::capacity (base::m_aDescr); } /** capacityCount. */ static sal_uInt16 capacityCount (const D& rDescr) // @see DirectoryPageObject::scope() { return sal_uInt16(capacity(rDescr) / sizeof(sal_uInt32)); } sal_uInt16 capacityCount() const { return sal_uInt16(capacity() / sizeof(sal_uInt32)); } /** Construction. */ explicit OStoreIndirectionPageData (sal_uInt16 nPageSize) : base (nPageSize) { base::m_aGuard.m_nMagic = store::htonl(self::theTypeId); base::m_aDescr.m_nUsed = store::htons(self::thePageSize); self::m_aGuard.m_nMagic = store::htonl(0); memset (m_pData, STORE_PAGE_NULL, capacity()); } /** guard (external representation). */ void guard() { sal_uInt32 nCRC32 = 0; nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = rtl_crc32 (nCRC32, m_pData, capacity()); m_aGuard.m_nCRC32 = store::htonl(nCRC32); } /** verify (external representation). */ storeError verify() const { sal_uInt32 nCRC32 = 0; nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = rtl_crc32 (nCRC32, m_pData, capacity()); if (m_aGuard.m_nCRC32 != store::htonl(nCRC32)) return store_E_InvalidChecksum; else return store_E_None; } }; /*======================================================================== * * OStoreIndirectionPageObject. * *======================================================================*/ class OStoreIndirectionPageObject : public store::OStorePageObject { typedef OStorePageObject base; typedef OStoreIndirectionPageData page; public: /** Construction. */ explicit OStoreIndirectionPageObject (PageHolder const & rxPage = PageHolder()) : OStorePageObject (rxPage) {} /** External representation. */ storeError loadOrCreate ( sal_uInt32 nAddr, OStorePageBIOS & rBIOS); virtual storeError guard (sal_uInt32 nAddr) SAL_OVERRIDE; virtual storeError verify (sal_uInt32 nAddr) const SAL_OVERRIDE; /** read (indirect data page). */ storeError read ( sal_uInt16 nSingle, OStoreDataPageObject &rData, OStorePageBIOS &rBIOS); storeError read ( sal_uInt16 nDouble, sal_uInt16 nSingle, OStoreDataPageObject &rData, OStorePageBIOS &rBIOS); storeError read ( sal_uInt16 nTriple, sal_uInt16 nDouble, sal_uInt16 nSingle, OStoreDataPageObject &rData, OStorePageBIOS &rBIOS); /** write (indirect data page). */ storeError write ( sal_uInt16 nSingle, OStoreDataPageObject &rData, OStorePageBIOS &rBIOS); storeError write ( sal_uInt16 nDouble, sal_uInt16 nSingle, OStoreDataPageObject &rData, OStorePageBIOS &rBIOS); storeError write ( sal_uInt16 nTriple, sal_uInt16 nDouble, sal_uInt16 nSingle, OStoreDataPageObject &rData, OStorePageBIOS &rBIOS); /** truncate (indirect data page). */ storeError truncate ( sal_uInt16 nSingle, OStorePageBIOS &rBIOS); storeError truncate ( sal_uInt16 nDouble, sal_uInt16 nSingle, OStorePageBIOS &rBIOS); storeError truncate ( sal_uInt16 nTriple, sal_uInt16 nDouble, sal_uInt16 nSingle, OStorePageBIOS &rBIOS); }; /*======================================================================== * * OStorePageNameBlock. * *======================================================================*/ struct OStorePageNameBlock { typedef OStorePageGuard G; typedef OStorePageKey K; /** Representation. */ G m_aGuard; K m_aKey; sal_uInt32 m_nAttrib; sal_Char m_pData[STORE_MAXIMUM_NAMESIZE]; /** size. */ static const size_t theSize = sizeof(G) + sizeof(K) + sizeof(sal_uInt32) + sizeof(sal_Char[STORE_MAXIMUM_NAMESIZE]); /** initialize. */ void initialize() { m_aGuard = G(); m_aKey = K(); m_nAttrib = 0; memset (m_pData, 0, sizeof(m_pData)); } /** Construction. */ OStorePageNameBlock() : m_aGuard(), m_aKey(), m_nAttrib (0) { memset (m_pData, 0, sizeof(m_pData)); } /** guard (external representation). */ void guard() { sal_uInt32 nCRC32 = 0; nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = rtl_crc32 (nCRC32, &m_aKey, theSize - sizeof(G)); m_aGuard.m_nCRC32 = store::htonl(nCRC32); } /** verify (external representation). */ storeError verify() const { sal_uInt32 nCRC32 = 0; nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = rtl_crc32 (nCRC32, &m_aKey, theSize - sizeof(G)); if (m_aGuard.m_nCRC32 != store::htonl(nCRC32)) return store_E_InvalidChecksum; else return store_E_None; } }; /*======================================================================== * * OStoreDirectoryDataBlock. * *======================================================================*/ #define STORE_LIMIT_DATAPAGE_DIRECT 16 #define STORE_LIMIT_DATAPAGE_SINGLE 8 #define STORE_LIMIT_DATAPAGE_DOUBLE 1 #define STORE_LIMIT_DATAPAGE_TRIPLE 1 struct OStoreDirectoryDataBlock { typedef OStorePageGuard G; /** LinkDescriptor. */ struct LinkDescriptor { /** Representation. */ sal_uInt16 m_nIndex0; sal_uInt16 m_nIndex1; sal_uInt16 m_nIndex2; sal_uInt16 m_nIndex3; /** Construction. */ LinkDescriptor() : m_nIndex0 ((sal_uInt16)(~0)), m_nIndex1 ((sal_uInt16)(~0)), m_nIndex2 ((sal_uInt16)(~0)), m_nIndex3 ((sal_uInt16)(~0)) {} }; /** LinkTable. */ struct LinkTable { /** Representation. */ sal_uInt32 m_pDirect[STORE_LIMIT_DATAPAGE_DIRECT]; sal_uInt32 m_pSingle[STORE_LIMIT_DATAPAGE_SINGLE]; sal_uInt32 m_pDouble[STORE_LIMIT_DATAPAGE_DOUBLE]; sal_uInt32 m_pTriple[STORE_LIMIT_DATAPAGE_TRIPLE]; /** initialize. */ void initialize() { memset(m_pDirect, STORE_PAGE_NULL, sizeof(m_pDirect)); memset(m_pSingle, STORE_PAGE_NULL, sizeof(m_pSingle)); memset(m_pDouble, STORE_PAGE_NULL, sizeof(m_pDouble)); memset(m_pTriple, STORE_PAGE_NULL, sizeof(m_pTriple)); } /** Construction. */ LinkTable() { initialize(); } }; /** Representation. */ G m_aGuard; LinkTable m_aTable; sal_uInt32 m_nDataLen; /** size. */ static const size_t theSize = sizeof(G) + sizeof(LinkTable) + sizeof(sal_uInt32); /** initialize. */ void initialize() { m_aGuard = G(); m_aTable.initialize(); m_nDataLen = 0; } /** Construction. */ OStoreDirectoryDataBlock() : m_aGuard(), m_aTable(), m_nDataLen (0) {} /** guard (external representation). */ void guard() { sal_uInt32 nCRC32 = 0; nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = rtl_crc32 (nCRC32, &m_aTable, theSize - sizeof(G)); m_aGuard.m_nCRC32 = store::htonl(nCRC32); } /** verify (external representation). */ storeError verify() const { sal_uInt32 nCRC32 = 0; nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = rtl_crc32 (nCRC32, &m_aTable, theSize - sizeof(G)); if (m_aGuard.m_nCRC32 != store::htonl(nCRC32)) return store_E_InvalidChecksum; else return store_E_None; } /** direct. */ static const sal_uInt16 directCount = ((sal_uInt16)(STORE_LIMIT_DATAPAGE_DIRECT)); sal_uInt32 directLink (sal_uInt16 nIndex) const { if (nIndex < directCount) return store::ntohl(m_aTable.m_pDirect[nIndex]); else return STORE_PAGE_NULL; } void directLink (sal_uInt16 nIndex, sal_uInt32 nAddr) { if (nIndex < directCount) m_aTable.m_pDirect[nIndex] = store::htonl(nAddr); } /** single. */ static const sal_uInt16 singleCount = ((sal_uInt16)(STORE_LIMIT_DATAPAGE_SINGLE)); sal_uInt32 singleLink (sal_uInt16 nIndex) const { if (nIndex < singleCount) return store::ntohl(m_aTable.m_pSingle[nIndex]); else return STORE_PAGE_NULL; } void singleLink (sal_uInt16 nIndex, sal_uInt32 nAddr) { if (nIndex < singleCount) m_aTable.m_pSingle[nIndex] = store::htonl(nAddr); } /** double. */ static const sal_uInt16 doubleCount = ((sal_uInt16)(STORE_LIMIT_DATAPAGE_DOUBLE)); sal_uInt32 doubleLink (sal_uInt16 nIndex) const { if (nIndex < doubleCount) return store::ntohl(m_aTable.m_pDouble[nIndex]); else return STORE_PAGE_NULL; } void doubleLink (sal_uInt16 nIndex, sal_uInt32 nAddr) { if (nIndex < doubleCount) m_aTable.m_pDouble[nIndex] = store::htonl(nAddr); } /** triple. */ static const sal_uInt16 tripleCount = ((sal_uInt16)(STORE_LIMIT_DATAPAGE_TRIPLE)); sal_uInt32 tripleLink (sal_uInt16 nIndex) const { if (nIndex < tripleCount) return store::ntohl(m_aTable.m_pTriple[nIndex]); else return STORE_PAGE_NULL; } void tripleLink (sal_uInt16 nIndex, sal_uInt32 nAddr) { if (nIndex < tripleCount) m_aTable.m_pTriple[nIndex] = store::htonl(nAddr); } }; /*======================================================================== * * OStoreDirectoryPageData. * *======================================================================*/ #define STORE_MAGIC_DIRECTORYPAGE sal_uInt32(0x62190120) struct OStoreDirectoryPageData : public store::OStorePageData { typedef OStorePageData base; typedef OStoreDirectoryPageData self; typedef OStorePageDescriptor D; typedef OStorePageNameBlock NameBlock; typedef OStoreDirectoryDataBlock DataBlock; /** Representation. */ NameBlock m_aNameBlock; DataBlock m_aDataBlock; sal_uInt8 m_pData[1]; /** type. */ static const sal_uInt32 theTypeId = STORE_MAGIC_DIRECTORYPAGE; /** size. */ static const size_t theSize = NameBlock::theSize + DataBlock::theSize; static const sal_uInt16 thePageSize = base::theSize + self::theSize; static_assert(STORE_MINIMUM_PAGESIZE >= self::thePageSize, "got to be at least equal in size"); /** capacity. */ sal_uInt16 capacity() const { return (store::ntohs(base::m_aDescr.m_nSize) - self::thePageSize); } /** usage. */ sal_uInt16 usage() const { return (store::ntohs(base::m_aDescr.m_nUsed) - self::thePageSize); } /** initialize. */ void initialize() { base::m_aGuard.m_nMagic = store::htonl(self::theTypeId); base::m_aDescr.m_nUsed = store::htons(self::thePageSize); m_aNameBlock.initialize(); m_aDataBlock.initialize(); memset (m_pData, 0, capacity()); } /** Construction. */ explicit OStoreDirectoryPageData (sal_uInt16 nPageSize) : base (nPageSize), m_aNameBlock(), m_aDataBlock() { base::m_aGuard.m_nMagic = store::htonl(self::theTypeId); base::m_aDescr.m_nUsed = store::htons(self::thePageSize); memset (m_pData, 0, capacity()); } /** guard (external representation). */ void guard() { m_aNameBlock.guard(); m_aDataBlock.guard(); } /** verify (external representation). */ storeError verify() const { storeError eErrCode = m_aNameBlock.verify(); if (eErrCode == store_E_None) eErrCode = m_aDataBlock.verify(); return eErrCode; } /** ChunkDescriptor. */ struct ChunkDescriptor { /** Representation. */ sal_uInt32 m_nPage; sal_uInt16 m_nOffset; sal_uInt16 m_nLength; /** Construction. */ ChunkDescriptor (sal_uInt32 nPosition, sal_uInt16 nCapacity) { m_nPage = nPosition / nCapacity; m_nOffset = (sal_uInt16)((nPosition % nCapacity) & 0xffff); m_nLength = nCapacity - m_nOffset; } }; /** ChunkScope. */ enum ChunkScope { SCOPE_INTERNAL, SCOPE_EXTERNAL, SCOPE_DIRECT, SCOPE_SINGLE, SCOPE_DOUBLE, SCOPE_TRIPLE, SCOPE_UNREACHABLE, SCOPE_UNKNOWN }; /** scope (internal). */ ChunkScope scope (sal_uInt32 nPosition) const { sal_uInt32 nCapacity = capacity(); if (nPosition < nCapacity) return SCOPE_INTERNAL; else return SCOPE_EXTERNAL; } }; /*======================================================================== * * OStoreDirectoryPageObject. * *======================================================================*/ class OStoreDirectoryPageObject : public store::OStorePageObject { typedef OStorePageObject base; typedef OStoreDirectoryPageData page; typedef OStoreIndirectionPageData indirect; typedef OStorePageDescriptor D; public: /** Construction. */ explicit OStoreDirectoryPageObject (PageHolder const & rxPage = PageHolder()) : OStorePageObject (rxPage) {} /** External representation. */ virtual storeError guard (sal_uInt32 nAddr) SAL_OVERRIDE; virtual storeError verify (sal_uInt32 nAddr) const SAL_OVERRIDE; /** attrib. */ sal_uInt32 attrib() const { return store::ntohl(PAGE().m_aNameBlock.m_nAttrib); } void attrib (sal_uInt32 nAttrib) { PAGE().m_aNameBlock.m_nAttrib = store::htonl(nAttrib); touch(); } /** key. */ OStorePageKey key() const { return PAGE().m_aNameBlock.m_aKey; } void key (OStorePageKey const & rKey) { PAGE().m_aNameBlock.m_aKey = rKey; touch(); } /** path. */ sal_uInt32 path() const { page const & rPage = PAGE(); const sal_Char * pszName = rPage.m_aNameBlock.m_pData; sal_uInt32 nPath = store::ntohl(rPage.m_aNameBlock.m_aKey.m_nHigh); return rtl_crc32 (nPath, pszName, rtl_str_getLength(pszName)); } sal_Size getName (sal_Char * pBuffer, sal_Size nBufsize) const { sal_Char const * pszName = PAGE().m_aNameBlock.m_pData; sal_Size nLength = rtl_str_getLength(pszName); memcpy (pBuffer, pszName, nLength < nBufsize ? nLength : nBufsize); return nLength; } /** dataLength. */ sal_uInt32 dataLength() const { return store::ntohl(PAGE().m_aDataBlock.m_nDataLen); } void dataLength (sal_uInt32 nLength) { PAGE().m_aDataBlock.m_nDataLen = store::htonl(nLength); touch(); } /** direct. */ sal_uInt32 directLink (sal_uInt16 nIndex) const { return PAGE().m_aDataBlock.directLink (nIndex); } void directLink (sal_uInt16 nIndex, sal_uInt32 nAddr) { PAGE().m_aDataBlock.directLink (nIndex, nAddr); touch(); } /** single indirect. */ sal_uInt32 singleLink (sal_uInt16 nIndex) const { return PAGE().m_aDataBlock.singleLink (nIndex); } void singleLink (sal_uInt16 nIndex, sal_uInt32 nAddr) { PAGE().m_aDataBlock.singleLink (nIndex, nAddr); touch(); } /** double indirect. */ sal_uInt32 doubleLink (sal_uInt16 nIndex) const { return PAGE().m_aDataBlock.doubleLink (nIndex); } void doubleLink (sal_uInt16 nIndex, sal_uInt32 nAddr) { PAGE().m_aDataBlock.doubleLink (nIndex, nAddr); touch(); } /** triple indirect. */ sal_uInt32 tripleLink (sal_uInt16 nIndex) const { return PAGE().m_aDataBlock.tripleLink (nIndex); } void tripleLink (sal_uInt16 nIndex, sal_uInt32 nAddr) { PAGE().m_aDataBlock.tripleLink (nIndex, nAddr); touch(); } /** read (external data page). */ storeError read ( sal_uInt32 nPage, OStoreDataPageObject &rData, OStorePageBIOS &rBIOS); /** write (external data page). */ storeError write ( sal_uInt32 nPage, OStoreDataPageObject &rData, OStorePageBIOS &rBIOS); /** truncate (external data page). */ storeError truncate ( sal_uInt32 nPage, OStorePageBIOS &rBIOS); private: /** Representation. */ page & PAGE() { page * pImpl = static_cast(m_xPage.get()); OSL_PRECOND(pImpl != 0, "OStoreDirectoryPageObject::PAGE(): Null pointer"); return (*pImpl); } page const & PAGE() const { page const * pImpl = static_cast(m_xPage.get()); OSL_PRECOND(pImpl != 0, "OStoreDirectoryPageObject::PAGE(): Null pointer"); return (*pImpl); } /** scope (external data page; private). */ page::ChunkScope scope ( sal_uInt32 nPage, page::DataBlock::LinkDescriptor &rDescr) const; /** truncate (external data page scope; private). */ storeError truncate ( page::ChunkScope eScope, sal_uInt16 nRemain, OStorePageBIOS &rBIOS); }; /*======================================================================== * * The End. * *======================================================================*/ } // namespace store #endif // INCLUDED_STORE_SOURCE_STORDATA_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */