1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <sal/config.h>
26 #include <sal/types.h>
27 #include <rtl/string.h>
29 #include <store/types.h>
30 #include "storbase.hxx"
38 constexpr sal_uInt32
STORE_MAGIC_DATAPAGE(0x94190310);
40 struct OStoreDataPageData
: public store::PageData
42 typedef PageData base
;
43 typedef OStoreDataPageData self
;
45 typedef OStorePageDescriptor D
;
53 static const sal_uInt32 theTypeId
= STORE_MAGIC_DATAPAGE
;
57 static const size_t theSize
= 0;
58 static const sal_uInt16 thePageSize
= base::theSize
+ self::theSize
;
59 static_assert(STORE_MINIMUM_PAGESIZE
>= self::thePageSize
, "got to be at least equal in size");
63 static sal_uInt16
capacity (const D
& rDescr
) // @see inode::ChunkDescriptor
65 return static_cast<sal_uInt16
>(store::ntohs(rDescr
.m_nSize
) - self::thePageSize
);
67 sal_uInt16
capacity() const
69 return self::capacity (base::m_aDescr
);
74 explicit OStoreDataPageData (sal_uInt16 nPageSize
)
77 base::m_aGuard
.m_nMagic
= store::htonl(self::theTypeId
);
78 base::m_aDescr
.m_nUsed
= store::htons(self::thePageSize
);
79 if (capacity()) memset (m_pData
, 0, capacity());
82 /** guard (external representation).
84 void guard() const { (void) this; /* loplugin:staticmethods */ }
86 /** verify (external representation).
88 storeError
verify() const {
89 (void) this; // loplugin:staticmethods
94 class OStoreDataPageObject
: public store::OStorePageObject
96 typedef OStorePageObject base
;
97 typedef OStoreDataPageData page
;
102 explicit OStoreDataPageObject (std::shared_ptr
<PageData
> const & rxPage
= std::shared_ptr
<PageData
>())
103 : OStorePageObject (rxPage
)
106 /** External representation.
108 virtual storeError
guard (sal_uInt32 nAddr
) override
;
109 virtual storeError
verify (sal_uInt32 nAddr
) const override
;
112 constexpr sal_uInt32
STORE_MAGIC_INDIRECTPAGE(0x89191107);
114 struct OStoreIndirectionPageData
: public store::PageData
116 typedef PageData base
;
117 typedef OStoreIndirectionPageData self
;
119 typedef OStorePageGuard G
;
120 typedef OStorePageDescriptor D
;
125 sal_uInt32 m_pData
[1];
129 static const sal_uInt32 theTypeId
= STORE_MAGIC_INDIRECTPAGE
;
133 static const size_t theSize
= sizeof(G
);
134 static const sal_uInt16 thePageSize
= base::theSize
+ self::theSize
;
135 static_assert(STORE_MINIMUM_PAGESIZE
>= self::thePageSize
, "got to be at least equal in size");
139 static sal_uInt16
capacity (const D
& rDescr
)
141 return static_cast<sal_uInt16
>(store::ntohs(rDescr
.m_nSize
) - self::thePageSize
);
143 sal_uInt16
capacity() const
145 return self::capacity (base::m_aDescr
);
150 static sal_uInt16
capacityCount (const D
& rDescr
) // @see DirectoryPageObject::scope()
152 return sal_uInt16(capacity(rDescr
) / sizeof(sal_uInt32
));
154 sal_uInt16
capacityCount() const
156 return sal_uInt16(capacity() / sizeof(sal_uInt32
));
161 explicit OStoreIndirectionPageData (sal_uInt16 nPageSize
)
164 base::m_aGuard
.m_nMagic
= store::htonl(self::theTypeId
);
165 base::m_aDescr
.m_nUsed
= store::htons(self::thePageSize
);
166 self::m_aGuard
.m_nMagic
= store::htonl(0);
167 memset (m_pData
, STORE_PAGE_NULL
, capacity());
170 /** guard (external representation).
174 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
175 nCRC32
= rtl_crc32 (nCRC32
, m_pData
, capacity());
176 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
179 /** verify (external representation).
181 storeError
verify() const
183 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
184 nCRC32
= rtl_crc32 (nCRC32
, m_pData
, capacity());
185 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
186 return store_E_InvalidChecksum
;
192 class OStoreIndirectionPageObject
: public store::OStorePageObject
194 typedef OStorePageObject base
;
195 typedef OStoreIndirectionPageData page
;
200 explicit OStoreIndirectionPageObject (std::shared_ptr
<PageData
> const & rxPage
= std::shared_ptr
<PageData
>())
201 : OStorePageObject (rxPage
)
204 /** External representation.
206 storeError
loadOrCreate (
208 OStorePageBIOS
& rBIOS
);
210 virtual storeError
guard (sal_uInt32 nAddr
) override
;
211 virtual storeError
verify (sal_uInt32 nAddr
) const override
;
213 /** read (indirect data page).
217 OStoreDataPageObject
&rData
,
218 OStorePageBIOS
&rBIOS
) const;
223 OStoreDataPageObject
&rData
,
224 OStorePageBIOS
&rBIOS
) const;
230 OStoreDataPageObject
&rData
,
231 OStorePageBIOS
&rBIOS
) const;
233 /** write (indirect data page).
237 OStoreDataPageObject
&rData
,
238 OStorePageBIOS
&rBIOS
);
243 OStoreDataPageObject
&rData
,
244 OStorePageBIOS
&rBIOS
);
250 OStoreDataPageObject
&rData
,
251 OStorePageBIOS
&rBIOS
);
253 /** truncate (indirect data page).
255 storeError
truncate (
257 OStorePageBIOS
&rBIOS
);
259 storeError
truncate (
262 OStorePageBIOS
&rBIOS
);
264 storeError
truncate (
268 OStorePageBIOS
&rBIOS
);
271 struct OStorePageNameBlock
273 typedef OStorePageGuard G
;
274 typedef OStorePageKey K
;
280 sal_uInt32 m_nAttrib
= 0;
281 char m_pData
[STORE_MAXIMUM_NAMESIZE
] = {};
285 static const size_t theSize
= sizeof(G
) + sizeof(K
) + sizeof(sal_uInt32
) + sizeof(char[STORE_MAXIMUM_NAMESIZE
]);
289 OStorePageNameBlock() = default;
291 /** guard (external representation).
295 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
296 nCRC32
= rtl_crc32 (nCRC32
, &m_aKey
, static_cast<sal_uInt32
>(theSize
- sizeof(G
)));
297 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
300 /** verify (external representation).
302 storeError
verify() const
304 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
305 nCRC32
= rtl_crc32 (nCRC32
, &m_aKey
, static_cast<sal_uInt32
>(theSize
- sizeof(G
)));
306 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
307 return store_E_InvalidChecksum
;
313 #define STORE_LIMIT_DATAPAGE_DIRECT 16
314 #define STORE_LIMIT_DATAPAGE_SINGLE 8
315 #define STORE_LIMIT_DATAPAGE_DOUBLE 1
316 #define STORE_LIMIT_DATAPAGE_TRIPLE 1
318 struct OStoreDirectoryDataBlock
320 typedef OStorePageGuard G
;
324 struct LinkDescriptor
328 sal_uInt16 m_nIndex0
;
329 sal_uInt16 m_nIndex1
;
330 sal_uInt16 m_nIndex2
;
331 sal_uInt16 m_nIndex3
;
336 : m_nIndex0 (sal_uInt16(~0)),
337 m_nIndex1 (sal_uInt16(~0)),
338 m_nIndex2 (sal_uInt16(~0)),
339 m_nIndex3 (sal_uInt16(~0))
349 sal_uInt32 m_pDirect
[STORE_LIMIT_DATAPAGE_DIRECT
];
350 sal_uInt32 m_pSingle
[STORE_LIMIT_DATAPAGE_SINGLE
];
351 sal_uInt32 m_pDouble
[STORE_LIMIT_DATAPAGE_DOUBLE
];
352 sal_uInt32 m_pTriple
[STORE_LIMIT_DATAPAGE_TRIPLE
];
358 memset(m_pDirect
, STORE_PAGE_NULL
, sizeof(m_pDirect
));
359 memset(m_pSingle
, STORE_PAGE_NULL
, sizeof(m_pSingle
));
360 memset(m_pDouble
, STORE_PAGE_NULL
, sizeof(m_pDouble
));
361 memset(m_pTriple
, STORE_PAGE_NULL
, sizeof(m_pTriple
));
376 sal_uInt32 m_nDataLen
;
380 static const size_t theSize
= sizeof(G
) + sizeof(LinkTable
) + sizeof(sal_uInt32
);
384 OStoreDirectoryDataBlock()
385 : m_aGuard(), m_aTable(), m_nDataLen (0)
388 /** guard (external representation).
392 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
393 nCRC32
= rtl_crc32 (nCRC32
, &m_aTable
, static_cast<sal_uInt32
>(theSize
- sizeof(G
)));
394 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
397 /** verify (external representation).
399 storeError
verify() const
401 sal_uInt32 nCRC32
= rtl_crc32 (0, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
402 nCRC32
= rtl_crc32 (nCRC32
, &m_aTable
, static_cast<sal_uInt32
>(theSize
- sizeof(G
)));
403 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
404 return store_E_InvalidChecksum
;
411 static const sal_uInt16 directCount
= sal_uInt16(STORE_LIMIT_DATAPAGE_DIRECT
);
413 sal_uInt32
directLink (sal_uInt16 nIndex
) const
415 if (nIndex
< directCount
)
416 return store::ntohl(m_aTable
.m_pDirect
[nIndex
]);
418 return STORE_PAGE_NULL
;
420 void directLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
)
422 if (nIndex
< directCount
)
423 m_aTable
.m_pDirect
[nIndex
] = store::htonl(nAddr
);
428 static const sal_uInt16 singleCount
= sal_uInt16(STORE_LIMIT_DATAPAGE_SINGLE
);
430 sal_uInt32
singleLink (sal_uInt16 nIndex
) const
432 if (nIndex
< singleCount
)
433 return store::ntohl(m_aTable
.m_pSingle
[nIndex
]);
435 return STORE_PAGE_NULL
;
437 void singleLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
)
439 if (nIndex
< singleCount
)
440 m_aTable
.m_pSingle
[nIndex
] = store::htonl(nAddr
);
445 static const sal_uInt16 doubleCount
= sal_uInt16(STORE_LIMIT_DATAPAGE_DOUBLE
);
447 sal_uInt32
doubleLink (sal_uInt16 nIndex
) const
449 if (nIndex
< doubleCount
)
450 return store::ntohl(m_aTable
.m_pDouble
[nIndex
]);
452 return STORE_PAGE_NULL
;
454 void doubleLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
)
456 if (nIndex
< doubleCount
)
457 m_aTable
.m_pDouble
[nIndex
] = store::htonl(nAddr
);
462 static const sal_uInt16 tripleCount
= sal_uInt16(STORE_LIMIT_DATAPAGE_TRIPLE
);
464 sal_uInt32
tripleLink (sal_uInt16 nIndex
) const
466 if (nIndex
< tripleCount
)
467 return store::ntohl(m_aTable
.m_pTriple
[nIndex
]);
469 return STORE_PAGE_NULL
;
471 void tripleLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
)
473 if (nIndex
< tripleCount
)
474 m_aTable
.m_pTriple
[nIndex
] = store::htonl(nAddr
);
478 #define STORE_MAGIC_DIRECTORYPAGE sal_uInt32(0x62190120)
480 struct OStoreDirectoryPageData
: public store::PageData
482 typedef PageData base
;
483 typedef OStoreDirectoryPageData self
;
485 typedef OStorePageDescriptor D
;
486 typedef OStorePageNameBlock NameBlock
;
487 typedef OStoreDirectoryDataBlock DataBlock
;
491 NameBlock m_aNameBlock
;
492 DataBlock m_aDataBlock
;
493 sal_uInt8 m_pData
[1];
497 static const sal_uInt32 theTypeId
= STORE_MAGIC_DIRECTORYPAGE
;
501 static const size_t theSize
= NameBlock::theSize
+ DataBlock::theSize
;
502 static const sal_uInt16 thePageSize
= base::theSize
+ self::theSize
;
503 static_assert(STORE_MINIMUM_PAGESIZE
>= self::thePageSize
, "got to be at least equal in size");
507 sal_uInt16
capacity() const
509 return static_cast<sal_uInt16
>(store::ntohs(base::m_aDescr
.m_nSize
) - self::thePageSize
);
514 explicit OStoreDirectoryPageData (sal_uInt16 nPageSize
)
515 : base (nPageSize
), m_aNameBlock(), m_aDataBlock()
517 base::m_aGuard
.m_nMagic
= store::htonl(self::theTypeId
);
518 base::m_aDescr
.m_nUsed
= store::htons(self::thePageSize
);
519 memset (m_pData
, 0, capacity());
522 /** guard (external representation).
526 m_aNameBlock
.guard();
527 m_aDataBlock
.guard();
530 /** verify (external representation).
532 storeError
verify() const
534 storeError eErrCode
= m_aNameBlock
.verify();
535 if (eErrCode
== store_E_None
)
536 eErrCode
= m_aDataBlock
.verify();
542 struct ChunkDescriptor
547 sal_uInt16 m_nOffset
;
548 sal_uInt16 m_nLength
;
552 ChunkDescriptor (sal_uInt32 nPosition
, sal_uInt16 nCapacity
)
553 : m_nPage(nPosition
/ nCapacity
),
554 m_nOffset(static_cast<sal_uInt16
>((nPosition
% nCapacity
) & 0xffff)),
555 m_nLength(nCapacity
- m_nOffset
)
574 /** scope (internal).
576 ChunkScope
scope (sal_uInt32 nPosition
) const
578 sal_uInt32 nCapacity
= capacity();
579 if (nPosition
< nCapacity
)
580 return SCOPE_INTERNAL
;
582 return SCOPE_EXTERNAL
;
586 class OStoreDirectoryPageObject
: public store::OStorePageObject
588 typedef OStorePageObject base
;
589 typedef OStoreDirectoryPageData page
;
590 typedef OStoreIndirectionPageData indirect
;
592 typedef OStorePageDescriptor D
;
597 explicit OStoreDirectoryPageObject (std::shared_ptr
<PageData
> const & rxPage
= std::shared_ptr
<PageData
>())
598 : OStorePageObject (rxPage
)
601 /** External representation.
603 virtual storeError
guard (sal_uInt32 nAddr
) override
;
604 virtual storeError
verify (sal_uInt32 nAddr
) const override
;
608 sal_uInt32
attrib() const
610 return store::ntohl(PAGE().m_aNameBlock
.m_nAttrib
);
612 void attrib (sal_uInt32 nAttrib
)
614 PAGE().m_aNameBlock
.m_nAttrib
= store::htonl(nAttrib
);
620 void key (OStorePageKey
const & rKey
)
622 PAGE().m_aNameBlock
.m_aKey
= rKey
;
628 sal_uInt32
path() const
630 page
const & rPage
= PAGE();
631 const char * pszName
= rPage
.m_aNameBlock
.m_pData
;
632 sal_uInt32 nPath
= store::ntohl(rPage
.m_aNameBlock
.m_aKey
.m_nHigh
);
633 return rtl_crc32 (nPath
, pszName
, rtl_str_getLength(pszName
));
638 sal_uInt32
dataLength() const
640 return store::ntohl(PAGE().m_aDataBlock
.m_nDataLen
);
642 void dataLength (sal_uInt32 nLength
)
644 PAGE().m_aDataBlock
.m_nDataLen
= store::htonl(nLength
);
650 sal_uInt32
directLink (sal_uInt16 nIndex
) const
652 return PAGE().m_aDataBlock
.directLink (nIndex
);
654 void directLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
)
656 PAGE().m_aDataBlock
.directLink (nIndex
, nAddr
);
662 sal_uInt32
singleLink (sal_uInt16 nIndex
) const
664 return PAGE().m_aDataBlock
.singleLink (nIndex
);
666 void singleLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
)
668 PAGE().m_aDataBlock
.singleLink (nIndex
, nAddr
);
674 sal_uInt32
doubleLink (sal_uInt16 nIndex
) const
676 return PAGE().m_aDataBlock
.doubleLink (nIndex
);
678 void doubleLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
)
680 PAGE().m_aDataBlock
.doubleLink (nIndex
, nAddr
);
686 sal_uInt32
tripleLink (sal_uInt16 nIndex
) const
688 return PAGE().m_aDataBlock
.tripleLink (nIndex
);
690 void tripleLink (sal_uInt16 nIndex
, sal_uInt32 nAddr
)
692 PAGE().m_aDataBlock
.tripleLink (nIndex
, nAddr
);
696 /** read (external data page).
700 OStoreDataPageObject
&rData
,
701 OStorePageBIOS
&rBIOS
) const;
703 /** write (external data page).
707 OStoreDataPageObject
&rData
,
708 OStorePageBIOS
&rBIOS
);
710 /** truncate (external data page).
712 storeError
truncate (
714 OStorePageBIOS
&rBIOS
);
721 page
* pImpl
= static_cast<page
*>(m_xPage
.get());
722 OSL_PRECOND(pImpl
!= nullptr, "OStoreDirectoryPageObject::PAGE(): Null pointer");
725 page
const & PAGE() const
727 page
const * pImpl
= static_cast<page
const *>(m_xPage
.get());
728 OSL_PRECOND(pImpl
!= nullptr, "OStoreDirectoryPageObject::PAGE(): Null pointer");
732 /** scope (external data page; private).
734 page::ChunkScope
scope (
736 page::DataBlock::LinkDescriptor
&rDescr
) const;
738 /** truncate (external data page scope; private).
740 storeError
truncate (
741 page::ChunkScope eScope
,
743 OStorePageBIOS
&rBIOS
);
748 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */