1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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
)
39 fields
= std::make_unique
<macabfield
*[]>(size
);
40 for(i
= 0; i
< size
; i
++)
42 if(_fields
[i
] == nullptr)
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
;
55 CFRetain(fields
[i
]->value
);
62 MacabHeader::MacabHeader()
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.
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.)
107 sal_Int32 numToAdd
= 0, numAdded
= 0;
108 macabfield
**newFields
;
109 for( i
= 0; i
< rSize
; i
++)
111 if(!contains(r
->get(i
)))
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
);
129 if(numAdded
== numToAdd
)
136 fields
.reset(newFields
);
142 OUString
MacabHeader::getString(const sal_Int32 i
) const
148 if(fields
[i
] == nullptr || fields
[i
]->value
== nullptr || CFGetTypeID(fields
[i
]->value
) != CFStringGetTypeID())
152 nRet
= CFStringToOUString(static_cast<CFStringRef
>(fields
[i
]->value
));
161 void MacabHeader::sortRecord()
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
];
179 if(compareFields(fields
[_start
], fields
[_start
+1]) > 0)
181 sorted
[0] = get(_start
+1);
182 sorted
[1] = get(_start
);
186 sorted
[0] = get(_start
);
187 sorted
[1] = get(_start
+1);
190 else if(_length
== 1)
192 sorted
[0] = get(_start
);
197 sal_Int32 halfLength
= floor(_length
/2);
198 sal_Int32 fp
= 0, lp
= 0;
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
++];
210 for( i
++; i
< _length
; i
++)
212 sorted
[i
] = lastHalf
[lp
++];
219 sorted
[i
] = lastHalf
[lp
++];
220 if(lp
== _length
- halfLength
)
222 for( i
++; i
< _length
; i
++)
224 sorted
[i
] = firstHalf
[fp
++];
232 fields
.reset(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
)
252 if(_field1
== nullptr)
254 if(_field2
== nullptr)
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
269 for(i
= 0; i
< size
; i
++)
271 if(getString(i
) == s
)
282 MacabHeader
*MacabHeader::begin()
288 MacabHeader::iterator::iterator ()
293 MacabHeader::iterator
& MacabHeader::iterator::operator= (MacabHeader
*_record
)
301 void MacabHeader::iterator::operator++ ()
307 bool MacabHeader::iterator::operator!= (const sal_Int32 i
) const
313 bool MacabHeader::iterator::operator== (const sal_Int32 i
) const
319 macabfield
*MacabHeader::iterator::operator* () const
321 return record
->get(id
);
325 sal_Int32
MacabHeader::end() const
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */