Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / macab / MacabHeader.cxx
bloba12ce3d0a0cde51f5c8cfcd2f992f51f0fa7df7f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include "MacabHeader.hxx"
22 #include "MacabRecord.hxx"
23 #include "macabutilities.hxx"
25 #include <math.h>
26 #include <com/sun/star/sdbc/DataType.hpp>
27 #include <connectivity/dbconversion.hxx>
29 using namespace connectivity::macab;
30 using namespace com::sun::star::sdbc;
31 using namespace com::sun::star::util;
32 using namespace ::dbtools;
35 MacabHeader::MacabHeader(const sal_Int32 _size, macabfield **_fields)
37 sal_Int32 i;
38 size = _size;
39 fields = new macabfield *[size];
40 for(i = 0; i < size; i++)
42 if(_fields[i] == NULL)
44 fields[i] = NULL;
46 else
48 /* The constructor duplicates the macabfields it gets because they
49 * are either deleted later or used for other purposes.
51 fields[i] = new macabfield;
52 fields[i]->type = _fields[i]->type;
53 fields[i]->value = _fields[i]->value;
54 if (fields[i]->value)
55 CFRetain(fields[i]->value);
62 MacabHeader::MacabHeader()
64 size = 0;
65 fields = NULL;
69 MacabHeader::~MacabHeader()
74 void MacabHeader::operator+= (const MacabHeader *r)
76 /* Add one MacabHeader to another. Anything not already in the header is
77 * added to the end of it.
79 sal_Int32 rSize = r->getSize();
80 if(rSize != 0) // If the new header does actually have fields
82 /* If our header is currently empty, just copy all of the fields from
83 * the new header to this one.
85 if(size == 0)
87 sal_Int32 i;
88 size = rSize;
89 fields = new macabfield *[size];
90 for(i = 0; i < size; i++)
92 fields[i] = r->copy(i);
96 /* Otherwise, only add the duplicates. We do this with a two-pass
97 * approach. First, find out how many fields to add, then reallocate
98 * the size of the fields array and add the old ones at the end.
99 * (More precisely, we create a _new_ fields array with the new length
100 * allocated to it, then get all of the fields from the current
101 * fields array to it, then copy the non-duplicates from the new
102 * header to the end.)
104 else
106 sal_Int32 i;
107 sal_Int32 numToAdd = 0, numAdded = 0;
108 macabfield **newFields;
109 for( i = 0; i < rSize; i++)
111 if(!contains(r->get(i)))
113 numToAdd++;
117 newFields = new macabfield *[size+numToAdd];
118 for(i = 0; i < size; i++)
120 newFields[i] = copy(i);
123 for( i = 0; i < rSize; i++)
125 if(!contains(r->get(i)))
127 newFields[size+numAdded] = r->copy(i);
128 numAdded++;
129 if(numAdded == numToAdd)
130 break;
134 releaseFields();
135 delete [] fields;
136 size += numAdded;
137 fields = newFields;
143 OUString MacabHeader::getString(const sal_Int32 i) const
145 OUString nRet;
147 if(i < size)
149 if(fields[i] == NULL || fields[i]->value == NULL || CFGetTypeID(fields[i]->value) != CFStringGetTypeID())
150 return OUString();
153 nRet = CFStringToOUString( (CFStringRef) fields[i]->value);
155 catch(...){ }
158 return nRet;
162 void MacabHeader::sortRecord()
164 sortRecord(0,size);
168 macabfield **MacabHeader::sortRecord(const sal_Int32 _start, const sal_Int32 _length)
170 /* Sort using mergesort. Because it uses mergesort, it is recursive and
171 * not in place (so it creates a new array at every step of the
172 * recursion), so if you prefer to use a different sort, please feel
173 * free to implement it.
175 macabfield** sorted = new macabfield *[_length];
176 if(_length <= 2)
178 if(_length == 2)
180 if(compareFields(fields[_start], fields[_start+1]) > 0)
182 sorted[0] = get(_start+1);
183 sorted[1] = get(_start);
185 else
187 sorted[0] = get(_start);
188 sorted[1] = get(_start+1);
191 else if(_length == 1)
193 sorted[0] = get(_start);
196 else
198 sal_Int32 halfLength = floor(_length/2);
199 sal_Int32 fp = 0, lp = 0;
200 sal_Int32 i;
201 macabfield **firstHalf = new macabfield *[halfLength];
202 macabfield **lastHalf = new macabfield *[_length - halfLength];
204 firstHalf = sortRecord(_start, halfLength);
205 lastHalf = sortRecord(_start+halfLength, _length-halfLength);
206 for(i = 0; i < _length; i++)
208 if(compareFields(firstHalf[fp],lastHalf[lp]) < 0)
210 sorted[i] = firstHalf[fp++];
211 if(fp == halfLength)
213 for( i++; i < _length; i++)
215 sorted[i] = lastHalf[lp++];
217 break;
220 else
222 sorted[i] = lastHalf[lp++];
223 if(lp == _length - halfLength)
225 for( i++; i < _length; i++)
227 sorted[i] = firstHalf[fp++];
229 break;
233 if(_length == size)
235 fields = sorted;
238 return sorted;
241 sal_Int32 MacabHeader::compareFields(const macabfield *_field1, const macabfield *_field2)
243 /* Comparing two fields in a MacabHeader is different than comparing two
244 * fields in a MacabRecord. It starts in the same way (if one of the two
245 * fields is NULL, it belongs after the other, so it is considered
246 * "greater"). But, then, all headers are CFStrings, no matter what
247 * type they claim to be (since they actually hold the expected type for
248 * the records with that header). That being said, all we have to do is
249 * the built-in CFStringCompare.
251 if(_field1 == _field2)
252 return 0;
253 if(_field1 == NULL)
254 return 1;
255 if(_field2 == NULL)
256 return -1;
258 CFComparisonResult result = CFStringCompare(
259 (CFStringRef) _field1->value,
260 (CFStringRef) _field2->value,
261 0); // 0 = no options (like ignore case)
263 return (sal_Int32) result;
267 sal_Int32 MacabHeader::getColumnNumber(const OUString& s) const
269 sal_Int32 i;
270 for(i = 0; i < size; i++)
272 if(getString(i) == s)
273 break;
276 if(i == size)
277 i = -1;
279 return i;
283 MacabHeader *MacabHeader::begin()
285 return this;
289 MacabHeader::iterator::iterator ()
294 MacabHeader::iterator::~iterator ()
298 MacabHeader::iterator& MacabHeader::iterator::operator= (MacabHeader *_record)
300 id = 0;
301 record = _record;
302 return *this;
306 void MacabHeader::iterator::operator++ ()
308 id++;
312 sal_Bool MacabHeader::iterator::operator!= (const sal_Int32 i) const
314 return(id != i);
318 sal_Bool MacabHeader::iterator::operator== (const sal_Int32 i) const
320 return(id == i);
324 macabfield *MacabHeader::iterator::operator* () const
326 return record->get(id);
330 sal_Int32 MacabHeader::end() const
332 return size;
335 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */