Use COMReference to handle COM pointers in CreateShortcut
[LibreOffice.git] / connectivity / source / drivers / macab / MacabHeader.cxx
blobda270dd05ac8263c025449ea02779ae38b5b55db
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 = std::make_unique<macabfield *[]>(size);
40 for(i = 0; i < size; i++)
42 if(_fields[i] == nullptr)
44 fields[i] = nullptr;
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 = nullptr;
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 = std::make_unique<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 size += numAdded;
136 fields.reset(newFields);
142 OUString MacabHeader::getString(const sal_Int32 i) const
144 OUString nRet;
146 if(i < size)
148 if(fields[i] == nullptr || fields[i]->value == nullptr || CFGetTypeID(fields[i]->value) != CFStringGetTypeID())
149 return OUString();
152 nRet = CFStringToOUString(static_cast<CFStringRef>(fields[i]->value));
154 catch(...){ }
157 return nRet;
161 void MacabHeader::sortRecord()
163 sortRecord(0,size);
167 macabfield **MacabHeader::sortRecord(const sal_Int32 _start, const sal_Int32 _length)
169 /* Sort using mergesort. Because it uses mergesort, it is recursive and
170 * not in place (so it creates a new array at every step of the
171 * recursion), so if you prefer to use a different sort, please feel
172 * free to implement it.
174 macabfield** sorted = new macabfield *[_length];
175 if(_length <= 2)
177 if(_length == 2)
179 if(compareFields(fields[_start], fields[_start+1]) > 0)
181 sorted[0] = get(_start+1);
182 sorted[1] = get(_start);
184 else
186 sorted[0] = get(_start);
187 sorted[1] = get(_start+1);
190 else if(_length == 1)
192 sorted[0] = get(_start);
195 else
197 sal_Int32 halfLength = floor(_length/2);
198 sal_Int32 fp = 0, lp = 0;
199 sal_Int32 i;
200 macabfield **firstHalf = sortRecord(_start, halfLength);
201 macabfield **lastHalf = sortRecord(_start+halfLength, _length-halfLength);
203 for(i = 0; i < _length; i++)
205 if(compareFields(firstHalf[fp],lastHalf[lp]) < 0)
207 sorted[i] = firstHalf[fp++];
208 if(fp == halfLength)
210 for( i++; i < _length; i++)
212 sorted[i] = lastHalf[lp++];
214 break;
217 else
219 sorted[i] = lastHalf[lp++];
220 if(lp == _length - halfLength)
222 for( i++; i < _length; i++)
224 sorted[i] = firstHalf[fp++];
226 break;
230 if(_length == size)
232 fields.reset(sorted);
234 delete firstHalf;
235 delete lastHalf;
237 return sorted;
240 sal_Int32 MacabHeader::compareFields(const macabfield *_field1, const macabfield *_field2)
242 /* Comparing two fields in a MacabHeader is different than comparing two
243 * fields in a MacabRecord. It starts in the same way (if one of the two
244 * fields is NULL, it belongs after the other, so it is considered
245 * "greater"). But, then, all headers are CFStrings, no matter what
246 * type they claim to be (since they actually hold the expected type for
247 * the records with that header). That being said, all we have to do is
248 * the built-in CFStringCompare.
250 if(_field1 == _field2)
251 return 0;
252 if(_field1 == nullptr)
253 return 1;
254 if(_field2 == nullptr)
255 return -1;
257 CFComparisonResult result = CFStringCompare(
258 static_cast<CFStringRef>(_field1->value),
259 static_cast<CFStringRef>(_field2->value),
260 0); // 0 = no options (like ignore case)
262 return static_cast<sal_Int32>(result);
266 sal_Int32 MacabHeader::getColumnNumber(std::u16string_view s) const
268 sal_Int32 i;
269 for(i = 0; i < size; i++)
271 if(getString(i) == s)
272 break;
275 if(i == size)
276 i = -1;
278 return i;
282 MacabHeader *MacabHeader::begin()
284 return this;
288 MacabHeader::iterator::iterator ()
293 MacabHeader::iterator& MacabHeader::iterator::operator= (MacabHeader *_record)
295 id = 0;
296 record = _record;
297 return *this;
301 void MacabHeader::iterator::operator++ ()
303 id++;
307 bool MacabHeader::iterator::operator!= (const sal_Int32 i) const
309 return(id != i);
313 bool MacabHeader::iterator::operator== (const sal_Int32 i) const
315 return(id == i);
319 macabfield *MacabHeader::iterator::operator* () const
321 return record->get(id);
325 sal_Int32 MacabHeader::end() const
327 return size;
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */