xref: /AOO41X/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