1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_connectivity.hxx"
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielski #include "MacabHeader.hxx"
28*b1cdbd2cSJim Jagielski #include "MacabRecord.hxx"
29*b1cdbd2cSJim Jagielski #include "macabutilities.hxx"
30*b1cdbd2cSJim Jagielski
31*b1cdbd2cSJim Jagielski #include <math.h>
32*b1cdbd2cSJim Jagielski #include <com/sun/star/sdbc/DataType.hpp>
33*b1cdbd2cSJim Jagielski #include <connectivity/dbconversion.hxx>
34*b1cdbd2cSJim Jagielski
35*b1cdbd2cSJim Jagielski using namespace connectivity::macab;
36*b1cdbd2cSJim Jagielski using namespace com::sun::star::sdbc;
37*b1cdbd2cSJim Jagielski using namespace com::sun::star::util;
38*b1cdbd2cSJim Jagielski using namespace ::dbtools;
39*b1cdbd2cSJim Jagielski
40*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
MacabHeader(const sal_Int32 _size,macabfield ** _fields)41*b1cdbd2cSJim Jagielski MacabHeader::MacabHeader(const sal_Int32 _size, macabfield **_fields)
42*b1cdbd2cSJim Jagielski {
43*b1cdbd2cSJim Jagielski sal_Int32 i;
44*b1cdbd2cSJim Jagielski size = _size;
45*b1cdbd2cSJim Jagielski fields = new macabfield *[size];
46*b1cdbd2cSJim Jagielski for(i = 0; i < size; i++)
47*b1cdbd2cSJim Jagielski {
48*b1cdbd2cSJim Jagielski if(_fields[i] == NULL)
49*b1cdbd2cSJim Jagielski {
50*b1cdbd2cSJim Jagielski fields[i] = NULL;
51*b1cdbd2cSJim Jagielski }
52*b1cdbd2cSJim Jagielski else
53*b1cdbd2cSJim Jagielski {
54*b1cdbd2cSJim Jagielski /* The constructor duplicates the macabfields it gets because they
55*b1cdbd2cSJim Jagielski * are either deleted later or used for other purposes.
56*b1cdbd2cSJim Jagielski */
57*b1cdbd2cSJim Jagielski fields[i] = new macabfield;
58*b1cdbd2cSJim Jagielski fields[i]->type = _fields[i]->type;
59*b1cdbd2cSJim Jagielski fields[i]->value = _fields[i]->value;
60*b1cdbd2cSJim Jagielski if (fields[i]->value)
61*b1cdbd2cSJim Jagielski CFRetain(fields[i]->value);
62*b1cdbd2cSJim Jagielski }
63*b1cdbd2cSJim Jagielski }
64*b1cdbd2cSJim Jagielski
65*b1cdbd2cSJim Jagielski }
66*b1cdbd2cSJim Jagielski
67*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
MacabHeader()68*b1cdbd2cSJim Jagielski MacabHeader::MacabHeader()
69*b1cdbd2cSJim Jagielski {
70*b1cdbd2cSJim Jagielski size = 0;
71*b1cdbd2cSJim Jagielski fields = NULL;
72*b1cdbd2cSJim Jagielski }
73*b1cdbd2cSJim Jagielski
74*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
~MacabHeader()75*b1cdbd2cSJim Jagielski MacabHeader::~MacabHeader()
76*b1cdbd2cSJim Jagielski {
77*b1cdbd2cSJim Jagielski }
78*b1cdbd2cSJim Jagielski
79*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator +=(const MacabHeader * r)80*b1cdbd2cSJim Jagielski void MacabHeader::operator+= (const MacabHeader *r)
81*b1cdbd2cSJim Jagielski {
82*b1cdbd2cSJim Jagielski /* Add one MacabHeader to another. Anything not already in the header is
83*b1cdbd2cSJim Jagielski * added to the end of it.
84*b1cdbd2cSJim Jagielski */
85*b1cdbd2cSJim Jagielski sal_Int32 rSize = r->getSize();
86*b1cdbd2cSJim Jagielski if(rSize != 0) // If the new header does actually have fields
87*b1cdbd2cSJim Jagielski {
88*b1cdbd2cSJim Jagielski /* If our header is currently empty, just copy all of the fields from
89*b1cdbd2cSJim Jagielski * the new header to this one.
90*b1cdbd2cSJim Jagielski */
91*b1cdbd2cSJim Jagielski if(size == 0)
92*b1cdbd2cSJim Jagielski {
93*b1cdbd2cSJim Jagielski sal_Int32 i;
94*b1cdbd2cSJim Jagielski size = rSize;
95*b1cdbd2cSJim Jagielski fields = new macabfield *[size];
96*b1cdbd2cSJim Jagielski for(i = 0; i < size; i++)
97*b1cdbd2cSJim Jagielski {
98*b1cdbd2cSJim Jagielski fields[i] = r->copy(i);
99*b1cdbd2cSJim Jagielski }
100*b1cdbd2cSJim Jagielski }
101*b1cdbd2cSJim Jagielski
102*b1cdbd2cSJim Jagielski /* Otherwise, only add the duplicates. We do this with a two-pass
103*b1cdbd2cSJim Jagielski * approach. First, find out how many fields to add, then reallocate
104*b1cdbd2cSJim Jagielski * the size of the fields array and add the old ones at the end.
105*b1cdbd2cSJim Jagielski * (More precisely, we create a _new_ fields array with the new length
106*b1cdbd2cSJim Jagielski * allocated to it, then get all of the fields from the current
107*b1cdbd2cSJim Jagielski * fields array to it, then copy the non-duplicates from the new
108*b1cdbd2cSJim Jagielski * header to the end.)
109*b1cdbd2cSJim Jagielski */
110*b1cdbd2cSJim Jagielski else
111*b1cdbd2cSJim Jagielski {
112*b1cdbd2cSJim Jagielski sal_Int32 i;
113*b1cdbd2cSJim Jagielski sal_Int32 numToAdd = 0, numAdded = 0;
114*b1cdbd2cSJim Jagielski macabfield **newFields;
115*b1cdbd2cSJim Jagielski for( i = 0; i < rSize; i++)
116*b1cdbd2cSJim Jagielski {
117*b1cdbd2cSJim Jagielski if(!contains(r->get(i)))
118*b1cdbd2cSJim Jagielski {
119*b1cdbd2cSJim Jagielski numToAdd++;
120*b1cdbd2cSJim Jagielski }
121*b1cdbd2cSJim Jagielski }
122*b1cdbd2cSJim Jagielski
123*b1cdbd2cSJim Jagielski newFields = new macabfield *[size+numToAdd];
124*b1cdbd2cSJim Jagielski for(i = 0; i < size; i++)
125*b1cdbd2cSJim Jagielski {
126*b1cdbd2cSJim Jagielski newFields[i] = copy(i);
127*b1cdbd2cSJim Jagielski }
128*b1cdbd2cSJim Jagielski
129*b1cdbd2cSJim Jagielski for( i = 0; i < rSize; i++)
130*b1cdbd2cSJim Jagielski {
131*b1cdbd2cSJim Jagielski if(!contains(r->get(i)))
132*b1cdbd2cSJim Jagielski {
133*b1cdbd2cSJim Jagielski newFields[size+numAdded] = r->copy(i);
134*b1cdbd2cSJim Jagielski numAdded++;
135*b1cdbd2cSJim Jagielski if(numAdded == numToAdd)
136*b1cdbd2cSJim Jagielski break;
137*b1cdbd2cSJim Jagielski }
138*b1cdbd2cSJim Jagielski }
139*b1cdbd2cSJim Jagielski
140*b1cdbd2cSJim Jagielski releaseFields();
141*b1cdbd2cSJim Jagielski delete [] fields;
142*b1cdbd2cSJim Jagielski size += numAdded;
143*b1cdbd2cSJim Jagielski fields = newFields;
144*b1cdbd2cSJim Jagielski }
145*b1cdbd2cSJim Jagielski }
146*b1cdbd2cSJim Jagielski }
147*b1cdbd2cSJim Jagielski
148*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
getString(const sal_Int32 i) const149*b1cdbd2cSJim Jagielski ::rtl::OUString MacabHeader::getString(const sal_Int32 i) const
150*b1cdbd2cSJim Jagielski {
151*b1cdbd2cSJim Jagielski ::rtl::OUString nRet;
152*b1cdbd2cSJim Jagielski
153*b1cdbd2cSJim Jagielski if(i < size)
154*b1cdbd2cSJim Jagielski {
155*b1cdbd2cSJim Jagielski if(fields[i] == NULL || fields[i]->value == NULL || CFGetTypeID(fields[i]->value) != CFStringGetTypeID())
156*b1cdbd2cSJim Jagielski return ::rtl::OUString();
157*b1cdbd2cSJim Jagielski try
158*b1cdbd2cSJim Jagielski {
159*b1cdbd2cSJim Jagielski nRet = CFStringToOUString( (CFStringRef) fields[i]->value);
160*b1cdbd2cSJim Jagielski }
161*b1cdbd2cSJim Jagielski catch(...){ }
162*b1cdbd2cSJim Jagielski }
163*b1cdbd2cSJim Jagielski
164*b1cdbd2cSJim Jagielski return nRet;
165*b1cdbd2cSJim Jagielski }
166*b1cdbd2cSJim Jagielski
167*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
sortRecord()168*b1cdbd2cSJim Jagielski void MacabHeader::sortRecord()
169*b1cdbd2cSJim Jagielski {
170*b1cdbd2cSJim Jagielski sortRecord(0,size);
171*b1cdbd2cSJim Jagielski }
172*b1cdbd2cSJim Jagielski
173*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
sortRecord(const sal_Int32 _start,const sal_Int32 _length)174*b1cdbd2cSJim Jagielski macabfield **MacabHeader::sortRecord(const sal_Int32 _start, const sal_Int32 _length)
175*b1cdbd2cSJim Jagielski {
176*b1cdbd2cSJim Jagielski /* Sort using mergesort. Because it uses mergesort, it is recursive and
177*b1cdbd2cSJim Jagielski * not in place (so it creates a new array at every step of the
178*b1cdbd2cSJim Jagielski * recursion), so if you prefer to use a different sort, please feel
179*b1cdbd2cSJim Jagielski * free to implement it.
180*b1cdbd2cSJim Jagielski */
181*b1cdbd2cSJim Jagielski macabfield** sorted = new macabfield *[_length];
182*b1cdbd2cSJim Jagielski if(_length <= 2)
183*b1cdbd2cSJim Jagielski {
184*b1cdbd2cSJim Jagielski if(_length == 2)
185*b1cdbd2cSJim Jagielski {
186*b1cdbd2cSJim Jagielski if(compareFields(fields[_start], fields[_start+1]) > 0)
187*b1cdbd2cSJim Jagielski {
188*b1cdbd2cSJim Jagielski sorted[0] = get(_start+1);
189*b1cdbd2cSJim Jagielski sorted[1] = get(_start);
190*b1cdbd2cSJim Jagielski }
191*b1cdbd2cSJim Jagielski else
192*b1cdbd2cSJim Jagielski {
193*b1cdbd2cSJim Jagielski sorted[0] = get(_start);
194*b1cdbd2cSJim Jagielski sorted[1] = get(_start+1);
195*b1cdbd2cSJim Jagielski }
196*b1cdbd2cSJim Jagielski }
197*b1cdbd2cSJim Jagielski else if(_length == 1)
198*b1cdbd2cSJim Jagielski {
199*b1cdbd2cSJim Jagielski sorted[0] = get(_start);
200*b1cdbd2cSJim Jagielski }
201*b1cdbd2cSJim Jagielski }
202*b1cdbd2cSJim Jagielski else
203*b1cdbd2cSJim Jagielski {
204*b1cdbd2cSJim Jagielski sal_Int32 halfLength = floor(_length/2);
205*b1cdbd2cSJim Jagielski sal_Int32 fp = 0, lp = 0;
206*b1cdbd2cSJim Jagielski sal_Int32 i;
207*b1cdbd2cSJim Jagielski macabfield **firstHalf = new macabfield *[halfLength];
208*b1cdbd2cSJim Jagielski macabfield **lastHalf = new macabfield *[_length - halfLength];
209*b1cdbd2cSJim Jagielski
210*b1cdbd2cSJim Jagielski firstHalf = sortRecord(_start, halfLength);
211*b1cdbd2cSJim Jagielski lastHalf = sortRecord(_start+halfLength, _length-halfLength);
212*b1cdbd2cSJim Jagielski for(i = 0; i < _length; i++)
213*b1cdbd2cSJim Jagielski {
214*b1cdbd2cSJim Jagielski if(compareFields(firstHalf[fp],lastHalf[lp]) < 0)
215*b1cdbd2cSJim Jagielski {
216*b1cdbd2cSJim Jagielski sorted[i] = firstHalf[fp++];
217*b1cdbd2cSJim Jagielski if(fp == halfLength)
218*b1cdbd2cSJim Jagielski {
219*b1cdbd2cSJim Jagielski for( i++; i < _length; i++)
220*b1cdbd2cSJim Jagielski {
221*b1cdbd2cSJim Jagielski sorted[i] = lastHalf[lp++];
222*b1cdbd2cSJim Jagielski }
223*b1cdbd2cSJim Jagielski break;
224*b1cdbd2cSJim Jagielski }
225*b1cdbd2cSJim Jagielski }
226*b1cdbd2cSJim Jagielski else
227*b1cdbd2cSJim Jagielski {
228*b1cdbd2cSJim Jagielski sorted[i] = lastHalf[lp++];
229*b1cdbd2cSJim Jagielski if(lp == _length - halfLength)
230*b1cdbd2cSJim Jagielski {
231*b1cdbd2cSJim Jagielski for( i++; i < _length; i++)
232*b1cdbd2cSJim Jagielski {
233*b1cdbd2cSJim Jagielski sorted[i] = firstHalf[fp++];
234*b1cdbd2cSJim Jagielski }
235*b1cdbd2cSJim Jagielski break;
236*b1cdbd2cSJim Jagielski }
237*b1cdbd2cSJim Jagielski }
238*b1cdbd2cSJim Jagielski }
239*b1cdbd2cSJim Jagielski if(_length == size)
240*b1cdbd2cSJim Jagielski {
241*b1cdbd2cSJim Jagielski fields = sorted;
242*b1cdbd2cSJim Jagielski }
243*b1cdbd2cSJim Jagielski }
244*b1cdbd2cSJim Jagielski return sorted;
245*b1cdbd2cSJim Jagielski }
246*b1cdbd2cSJim Jagielski
compareFields(const macabfield * _field1,const macabfield * _field2)247*b1cdbd2cSJim Jagielski sal_Int32 MacabHeader::compareFields(const macabfield *_field1, const macabfield *_field2)
248*b1cdbd2cSJim Jagielski {
249*b1cdbd2cSJim Jagielski /* Comparing two fields in a MacabHeader is different than comparing two
250*b1cdbd2cSJim Jagielski * fields in a MacabRecord. It starts in the same way (if one of the two
251*b1cdbd2cSJim Jagielski * fields is NULL, it belongs after the other, so it is considered
252*b1cdbd2cSJim Jagielski * "greater"). But, then, all headers are CFStrings, no matter what
253*b1cdbd2cSJim Jagielski * type they claim to be (since they actually hold the expected type for
254*b1cdbd2cSJim Jagielski * the records with that header). That being said, all we have to do is
255*b1cdbd2cSJim Jagielski * the built-in CFStringCompare.
256*b1cdbd2cSJim Jagielski */
257*b1cdbd2cSJim Jagielski if(_field1 == _field2)
258*b1cdbd2cSJim Jagielski return 0;
259*b1cdbd2cSJim Jagielski if(_field1 == NULL)
260*b1cdbd2cSJim Jagielski return 1;
261*b1cdbd2cSJim Jagielski if(_field2 == NULL)
262*b1cdbd2cSJim Jagielski return -1;
263*b1cdbd2cSJim Jagielski
264*b1cdbd2cSJim Jagielski CFComparisonResult result = CFStringCompare(
265*b1cdbd2cSJim Jagielski (CFStringRef) _field1->value,
266*b1cdbd2cSJim Jagielski (CFStringRef) _field2->value,
267*b1cdbd2cSJim Jagielski 0); // 0 = no options (like ignore case)
268*b1cdbd2cSJim Jagielski
269*b1cdbd2cSJim Jagielski return (sal_Int32) result;
270*b1cdbd2cSJim Jagielski }
271*b1cdbd2cSJim Jagielski
272*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
getColumnNumber(const::rtl::OUString s) const273*b1cdbd2cSJim Jagielski sal_Int32 MacabHeader::getColumnNumber(const ::rtl::OUString s) const
274*b1cdbd2cSJim Jagielski {
275*b1cdbd2cSJim Jagielski sal_Int32 i;
276*b1cdbd2cSJim Jagielski for(i = 0; i < size; i++)
277*b1cdbd2cSJim Jagielski {
278*b1cdbd2cSJim Jagielski if(getString(i) == s)
279*b1cdbd2cSJim Jagielski break;
280*b1cdbd2cSJim Jagielski }
281*b1cdbd2cSJim Jagielski
282*b1cdbd2cSJim Jagielski if(i == size)
283*b1cdbd2cSJim Jagielski i = -1;
284*b1cdbd2cSJim Jagielski
285*b1cdbd2cSJim Jagielski return i;
286*b1cdbd2cSJim Jagielski }
287*b1cdbd2cSJim Jagielski
288*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
begin()289*b1cdbd2cSJim Jagielski MacabHeader *MacabHeader::begin()
290*b1cdbd2cSJim Jagielski {
291*b1cdbd2cSJim Jagielski return this;
292*b1cdbd2cSJim Jagielski }
293*b1cdbd2cSJim Jagielski
294*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
iterator()295*b1cdbd2cSJim Jagielski MacabHeader::iterator::iterator ()
296*b1cdbd2cSJim Jagielski {
297*b1cdbd2cSJim Jagielski }
298*b1cdbd2cSJim Jagielski
299*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
~iterator()300*b1cdbd2cSJim Jagielski MacabHeader::iterator::~iterator ()
301*b1cdbd2cSJim Jagielski {
302*b1cdbd2cSJim Jagielski }
303*b1cdbd2cSJim Jagielski
operator =(MacabHeader * _record)304*b1cdbd2cSJim Jagielski void MacabHeader::iterator::operator= (MacabHeader *_record)
305*b1cdbd2cSJim Jagielski {
306*b1cdbd2cSJim Jagielski id = 0;
307*b1cdbd2cSJim Jagielski record = _record;
308*b1cdbd2cSJim Jagielski }
309*b1cdbd2cSJim Jagielski
310*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator ++()311*b1cdbd2cSJim Jagielski void MacabHeader::iterator::operator++ ()
312*b1cdbd2cSJim Jagielski {
313*b1cdbd2cSJim Jagielski id++;
314*b1cdbd2cSJim Jagielski }
315*b1cdbd2cSJim Jagielski
316*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator !=(const sal_Int32 i) const317*b1cdbd2cSJim Jagielski sal_Bool MacabHeader::iterator::operator!= (const sal_Int32 i) const
318*b1cdbd2cSJim Jagielski {
319*b1cdbd2cSJim Jagielski return(id != i);
320*b1cdbd2cSJim Jagielski }
321*b1cdbd2cSJim Jagielski
322*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator ==(const sal_Int32 i) const323*b1cdbd2cSJim Jagielski sal_Bool MacabHeader::iterator::operator== (const sal_Int32 i) const
324*b1cdbd2cSJim Jagielski {
325*b1cdbd2cSJim Jagielski return(id == i);
326*b1cdbd2cSJim Jagielski }
327*b1cdbd2cSJim Jagielski
328*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator *() const329*b1cdbd2cSJim Jagielski macabfield *MacabHeader::iterator::operator* () const
330*b1cdbd2cSJim Jagielski {
331*b1cdbd2cSJim Jagielski return record->get(id);
332*b1cdbd2cSJim Jagielski }
333*b1cdbd2cSJim Jagielski
334*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
end() const335*b1cdbd2cSJim Jagielski sal_Int32 MacabHeader::end() const
336*b1cdbd2cSJim Jagielski {
337*b1cdbd2cSJim Jagielski return size;
338*b1cdbd2cSJim Jagielski }
339*b1cdbd2cSJim Jagielski
340