1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef INCLUDED_PLCF_HXX
25 #define INCLUDED_PLCF_HXX
26 
27 #include <boost/shared_ptr.hpp>
28 #include <WW8StructBase.hxx>
29 
30 namespace writerfilter {
31 namespace doctok
32 {
33 
34 class Empty
35 {
36 public:
37     typedef boost::shared_ptr<Empty> Pointer_t;
38 
Empty()39     Empty() {}
~Empty()40     virtual ~Empty() {}
41 
getSize()42     sal_uInt32 getSize() { return 0; }
43 };
44 
45 template <class T>
46 /**
47    Plex in File
48 
49    A PLCF is a concatenation of two arrays. The first array contains
50    file character positions. The second array contains elements of
51    type T. If the first array contains N elements, the second contains
52    N - 1 elements. The N-th element in the first array corresponds to
53    the N-th element of the second array.
54 
55    The second array is referred to as the payload.
56  */
57 class PLCF : public WW8StructBase
58 {
59     /// number of entries
60     sal_uInt32 nEntryCount;
61 
62     /// offset to payload
63     sal_uInt32 nPayloadOffset;
64 
65     /// internal method to calculate the number of entries
66     sal_uInt32 getEntryCount_() const;
67 
68 public:
69     typedef boost::shared_ptr< PLCF< T > > Pointer_t;
70 
PLCF(sal_uInt32 nLength)71     PLCF(sal_uInt32 nLength)
72     : WW8StructBase(nLength), nEntryCount(getEntryCount_()),
73       nPayloadOffset((nEntryCount + 1) * 4)
74     {
75     }
76 
PLCF(WW8Stream & rStream,sal_Int32 nOffset,sal_Int32 nCount)77     PLCF(WW8Stream & rStream,
78          sal_Int32 nOffset, sal_Int32 nCount)
79     : WW8StructBase(rStream, nOffset, nCount),
80       nEntryCount(getEntryCount_()),
81       nPayloadOffset((nEntryCount + 1) * 4)
82     {
83     }
84 
PLCF(const Sequence & rSequence)85     PLCF(const Sequence & rSequence)
86     : WW8StructBase(rSequence), nEntryCount(getEntryCount_()),
87       nPayloadOffset((nEntryCount + 1) * 4)
88     {
89     }
90 
91     /**
92        Return the number of elements in the PLCF-
93      */
getEntryCount() const94     sal_uInt32 getEntryCount() const { return nEntryCount; }
95 
96     /**
97        Return the file character position of a certain element.
98 
99        @param nIndex      the index of the element
100      */
101     sal_uInt32 getFc(sal_uInt32 nIndex) const;
102 
103     /**
104        Return a C++ pointer to a certain payload entry.
105 
106        @param nIndex      the index of the element
107      */
108     T * getEntryPointer(sal_uInt32 nIndex) const;
109 
110     /**
111        Return a shared pointer to a certain payload element.
112 
113        @param nIndex      the index of the element
114      */
115     typename T::Pointer_t getEntry(sal_uInt32 nIndex) const;
116 
117     /**
118        Return a C++ pointer a certain payload element.
119 
120        @param nFc         the file character position of the element
121      */
122     T * getEntryByFc(sal_uInt32 nFc) const;
123 
124     virtual void dump(OutputWithDepth<string> & out) const;
125 };
126 
127 template <class T>
getEntryCount_() const128 sal_uInt32 PLCF<T>::getEntryCount_() const
129 {
130     return (getCount() - 4) / (T::getSize() + 4);
131 }
132 
133 template <class T>
getFc(sal_uInt32 nIndex) const134 sal_uInt32 PLCF<T>::getFc(sal_uInt32 nIndex) const
135 {
136     return getU32(nIndex * 4);
137 }
138 
139 template <class T>
getEntryPointer(sal_uInt32 nIndex) const140 T * PLCF<T>::getEntryPointer(sal_uInt32 nIndex) const
141 {
142     return new T(mSequence, nPayloadOffset + nIndex * T::getSize(),
143                  T::getSize());
144 }
145 
146 template <class T>
getEntry(sal_uInt32 nIndex) const147 typename T::Pointer_t PLCF<T>::getEntry(sal_uInt32 nIndex) const
148 {
149     typename T::Pointer_t pResult(getEntryPointer(nIndex));
150 
151     return pResult;
152 }
153 
154 
155 template <class T>
getEntryByFc(sal_uInt32 nFc) const156 T * PLCF<T>::getEntryByFc(sal_uInt32 nFc) const
157 {
158     T * pResult = NULL;
159 
160     sal_uInt32 n = getEntryCount();
161 
162     while (getFc(n) > nFc)
163         n--;
164 
165     pResult = getEntryPointer(n);
166 
167     return pResult;
168 }
169 
170 template <class T>
dump(OutputWithDepth<string> & output_) const171 void PLCF<T>::dump(OutputWithDepth<string> & output_) const
172 {
173     output_.addItem("<plcf>");
174     WW8StructBase::dump(output_);
175 
176     sal_uInt32 nCount = getEntryCount();
177     for (sal_uInt32 n = 0; n < nCount; ++n)
178     {
179         Fc aFc = getFc(n);
180         typename T::Pointer_t pT = getEntry(n);
181 
182         output_.addItem("<plcfentry cpandfc=\"" + aFc.toString() + "\">");
183         pT->dump(output_);
184         output_.addItem("</plcfentry>");
185     }
186     output_.addItem("</plcf>>");
187 }
188 
189 }}
190 
191 #endif // INCLUDED_PLCF_HXX
192