1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MacabHeader.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include "MacabHeader.hxx"
35 #include "MacabRecord.hxx"
36 #include "macabutilities.hxx"
39 #include <com/sun/star/sdbc/DataType.hpp>
40 #include <connectivity/dbconversion.hxx>
42 using namespace connectivity::macab
;
43 using namespace com::sun::star::sdbc
;
44 using namespace com::sun::star::util
;
45 using namespace ::dbtools
;
47 // -------------------------------------------------------------------------
48 MacabHeader::MacabHeader(const sal_Int32 _size
, macabfield
**_fields
)
52 fields
= new macabfield
*[size
];
53 for(i
= 0; i
< size
; i
++)
55 if(_fields
[i
] == NULL
)
61 /* The constructor duplicates the macabfields it gets because they
62 * are either deleted later or used for other purposes.
64 fields
[i
] = new macabfield
;
65 fields
[i
]->type
= _fields
[i
]->type
;
66 fields
[i
]->value
= _fields
[i
]->value
;
68 CFRetain(fields
[i
]->value
);
74 // -------------------------------------------------------------------------
75 MacabHeader::MacabHeader()
81 // -------------------------------------------------------------------------
82 MacabHeader::~MacabHeader()
86 // -------------------------------------------------------------------------
87 void MacabHeader::operator+= (const MacabHeader
*r
)
89 /* Add one MacabHeader to another. Anything not already in the header is
90 * added to the end of it.
92 sal_Int32 rSize
= r
->getSize();
93 if(rSize
!= 0) // If the new header does actually have fields
95 /* If our header is currently empty, just copy all of the fields from
96 * the new header to this one.
102 fields
= new macabfield
*[size
];
103 for(i
= 0; i
< size
; i
++)
105 fields
[i
] = r
->copy(i
);
109 /* Otherwise, only add the duplicates. We do this with a two-pass
110 * approach. First, find out how many fields to add, then reallocate
111 * the size of the fields array and add the old ones at the end.
112 * (More precisely, we create a _new_ fields array with the new length
113 * allocated to it, then get all of the fields from the current
114 * fields array to it, then copy the non-duplicates from the new
115 * header to the end.)
120 sal_Int32 numToAdd
= 0, numAdded
= 0;
121 macabfield
**newFields
;
122 for( i
= 0; i
< rSize
; i
++)
124 if(!contains(r
->get(i
)))
130 newFields
= new macabfield
*[size
+numToAdd
];
131 for(i
= 0; i
< size
; i
++)
133 newFields
[i
] = copy(i
);
136 for( i
= 0; i
< rSize
; i
++)
138 if(!contains(r
->get(i
)))
140 newFields
[size
+numAdded
] = r
->copy(i
);
142 if(numAdded
== numToAdd
)
155 // -------------------------------------------------------------------------
156 ::rtl::OUString
MacabHeader::getString(const sal_Int32 i
) const
158 ::rtl::OUString nRet
;
162 if(fields
[i
] == NULL
|| fields
[i
]->value
== NULL
|| CFGetTypeID(fields
[i
]->value
) != CFStringGetTypeID())
163 return ::rtl::OUString();
166 nRet
= CFStringToOUString( (CFStringRef
) fields
[i
]->value
);
174 // -------------------------------------------------------------------------
175 void MacabHeader::sortRecord()
180 // -------------------------------------------------------------------------
181 macabfield
**MacabHeader::sortRecord(const sal_Int32 _start
, const sal_Int32 _length
)
183 /* Sort using mergesort. Because it uses mergesort, it is recursive and
184 * not in place (so it creates a new array at every step of the
185 * recursion), so if you prefer to use a different sort, please feel
186 * free to implement it.
188 macabfield
** sorted
= new macabfield
*[_length
];
193 if(compareFields(fields
[_start
], fields
[_start
+1]) > 0)
195 sorted
[0] = get(_start
+1);
196 sorted
[1] = get(_start
);
200 sorted
[0] = get(_start
);
201 sorted
[1] = get(_start
+1);
204 else if(_length
== 1)
206 sorted
[0] = get(_start
);
211 sal_Int32 halfLength
= floor(_length
/2);
212 sal_Int32 fp
= 0, lp
= 0;
214 macabfield
**firstHalf
= new macabfield
*[halfLength
];
215 macabfield
**lastHalf
= new macabfield
*[_length
- halfLength
];
217 firstHalf
= sortRecord(_start
, halfLength
);
218 lastHalf
= sortRecord(_start
+halfLength
, _length
-halfLength
);
219 for(i
= 0; i
< _length
; i
++)
221 if(compareFields(firstHalf
[fp
],lastHalf
[lp
]) < 0)
223 sorted
[i
] = firstHalf
[fp
++];
226 for( i
++; i
< _length
; i
++)
228 sorted
[i
] = lastHalf
[lp
++];
235 sorted
[i
] = lastHalf
[lp
++];
236 if(lp
== _length
- halfLength
)
238 for( i
++; i
< _length
; i
++)
240 sorted
[i
] = firstHalf
[fp
++];
254 sal_Int32
MacabHeader::compareFields(const macabfield
*_field1
, const macabfield
*_field2
)
256 /* Comparing two fields in a MacabHeader is different than comparing two
257 * fields in a MacabRecord. It starts in the same way (if one of the two
258 * fields is NULL, it belongs after the other, so it is considered
259 * "greater"). But, then, all headers are CFStrings, no matter what
260 * type they claim to be (since they actually hold the expected type for
261 * the records with that header). That being said, all we have to do is
262 * the built-in CFStringCompare.
264 if(_field1
== _field2
)
271 CFComparisonResult result
= CFStringCompare(
272 (CFStringRef
) _field1
->value
,
273 (CFStringRef
) _field2
->value
,
274 0); // 0 = no options (like ignore case)
276 return (sal_Int32
) result
;
279 // -------------------------------------------------------------------------
280 sal_Int32
MacabHeader::getColumnNumber(const ::rtl::OUString s
) const
283 for(i
= 0; i
< size
; i
++)
285 if(getString(i
) == s
)
295 // -------------------------------------------------------------------------
296 MacabHeader
*MacabHeader::begin()
301 // -------------------------------------------------------------------------
302 MacabHeader::iterator::iterator ()
306 // -------------------------------------------------------------------------
307 MacabHeader::iterator::~iterator ()
311 void MacabHeader::iterator::operator= (MacabHeader
*_record
)
317 // -------------------------------------------------------------------------
318 void MacabHeader::iterator::operator++ ()
323 // -------------------------------------------------------------------------
324 sal_Bool
MacabHeader::iterator::operator!= (const sal_Int32 i
) const
329 // -------------------------------------------------------------------------
330 sal_Bool
MacabHeader::iterator::operator== (const sal_Int32 i
) const
335 // -------------------------------------------------------------------------
336 macabfield
*MacabHeader::iterator::operator* () const
338 return record
->get(id
);
341 // -------------------------------------------------------------------------
342 sal_Int32
MacabHeader::end() const