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
= new macabfield
*[size
];
40 for(i
= 0; i
< size
; i
++)
42 if(_fields
[i
] == NULL
)
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
= 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.)
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
)
143 OUString
MacabHeader::getString(const sal_Int32 i
) const
149 if(fields
[i
] == NULL
|| fields
[i
]->value
== NULL
|| CFGetTypeID(fields
[i
]->value
) != CFStringGetTypeID())
153 nRet
= CFStringToOUString( (CFStringRef
) fields
[i
]->value
);
162 void MacabHeader::sortRecord()
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
];
180 if(compareFields(fields
[_start
], fields
[_start
+1]) > 0)
182 sorted
[0] = get(_start
+1);
183 sorted
[1] = get(_start
);
187 sorted
[0] = get(_start
);
188 sorted
[1] = get(_start
+1);
191 else if(_length
== 1)
193 sorted
[0] = get(_start
);
198 sal_Int32 halfLength
= floor(_length
/2);
199 sal_Int32 fp
= 0, lp
= 0;
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
++];
213 for( i
++; i
< _length
; i
++)
215 sorted
[i
] = lastHalf
[lp
++];
222 sorted
[i
] = lastHalf
[lp
++];
223 if(lp
== _length
- halfLength
)
225 for( i
++; i
< _length
; i
++)
227 sorted
[i
] = firstHalf
[fp
++];
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
)
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
270 for(i
= 0; i
< size
; i
++)
272 if(getString(i
) == s
)
283 MacabHeader
*MacabHeader::begin()
289 MacabHeader::iterator::iterator ()
294 MacabHeader::iterator::~iterator ()
298 MacabHeader::iterator
& MacabHeader::iterator::operator= (MacabHeader
*_record
)
306 void MacabHeader::iterator::operator++ ()
312 sal_Bool
MacabHeader::iterator::operator!= (const sal_Int32 i
) const
318 sal_Bool
MacabHeader::iterator::operator== (const sal_Int32 i
) const
324 macabfield
*MacabHeader::iterator::operator* () const
326 return record
->get(id
);
330 sal_Int32
MacabHeader::end() const
335 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */