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