1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_connectivity.hxx" 30 31 #include "MacabHeader.hxx" 32 #include "MacabRecord.hxx" 33 #include "macabutilities.hxx" 34 35 #include <math.h> 36 #include <com/sun/star/sdbc/DataType.hpp> 37 #include <connectivity/dbconversion.hxx> 38 39 using namespace connectivity::macab; 40 using namespace com::sun::star::sdbc; 41 using namespace com::sun::star::util; 42 using namespace ::dbtools; 43 44 // ------------------------------------------------------------------------- 45 MacabHeader::MacabHeader(const sal_Int32 _size, macabfield **_fields) 46 { 47 sal_Int32 i; 48 size = _size; 49 fields = new macabfield *[size]; 50 for(i = 0; i < size; i++) 51 { 52 if(_fields[i] == NULL) 53 { 54 fields[i] = NULL; 55 } 56 else 57 { 58 /* The constructor duplicates the macabfields it gets because they 59 * are either deleted later or used for other purposes. 60 */ 61 fields[i] = new macabfield; 62 fields[i]->type = _fields[i]->type; 63 fields[i]->value = _fields[i]->value; 64 if (fields[i]->value) 65 CFRetain(fields[i]->value); 66 } 67 } 68 69 } 70 71 // ------------------------------------------------------------------------- 72 MacabHeader::MacabHeader() 73 { 74 size = 0; 75 fields = NULL; 76 } 77 78 // ------------------------------------------------------------------------- 79 MacabHeader::~MacabHeader() 80 { 81 } 82 83 // ------------------------------------------------------------------------- 84 void MacabHeader::operator+= (const MacabHeader *r) 85 { 86 /* Add one MacabHeader to another. Anything not already in the header is 87 * added to the end of it. 88 */ 89 sal_Int32 rSize = r->getSize(); 90 if(rSize != 0) // If the new header does actually have fields 91 { 92 /* If our header is currently empty, just copy all of the fields from 93 * the new header to this one. 94 */ 95 if(size == 0) 96 { 97 sal_Int32 i; 98 size = rSize; 99 fields = new macabfield *[size]; 100 for(i = 0; i < size; i++) 101 { 102 fields[i] = r->copy(i); 103 } 104 } 105 106 /* Otherwise, only add the duplicates. We do this with a two-pass 107 * approach. First, find out how many fields to add, then reallocate 108 * the size of the fields array and add the old ones at the end. 109 * (More precisely, we create a _new_ fields array with the new length 110 * allocated to it, then get all of the fields from the current 111 * fields array to it, then copy the non-duplicates from the new 112 * header to the end.) 113 */ 114 else 115 { 116 sal_Int32 i; 117 sal_Int32 numToAdd = 0, numAdded = 0; 118 macabfield **newFields; 119 for( i = 0; i < rSize; i++) 120 { 121 if(!contains(r->get(i))) 122 { 123 numToAdd++; 124 } 125 } 126 127 newFields = new macabfield *[size+numToAdd]; 128 for(i = 0; i < size; i++) 129 { 130 newFields[i] = copy(i); 131 } 132 133 for( i = 0; i < rSize; i++) 134 { 135 if(!contains(r->get(i))) 136 { 137 newFields[size+numAdded] = r->copy(i); 138 numAdded++; 139 if(numAdded == numToAdd) 140 break; 141 } 142 } 143 144 releaseFields(); 145 delete [] fields; 146 size += numAdded; 147 fields = newFields; 148 } 149 } 150 } 151 152 // ------------------------------------------------------------------------- 153 ::rtl::OUString MacabHeader::getString(const sal_Int32 i) const 154 { 155 ::rtl::OUString nRet; 156 157 if(i < size) 158 { 159 if(fields[i] == NULL || fields[i]->value == NULL || CFGetTypeID(fields[i]->value) != CFStringGetTypeID()) 160 return ::rtl::OUString(); 161 try 162 { 163 nRet = CFStringToOUString( (CFStringRef) fields[i]->value); 164 } 165 catch(...){ } 166 } 167 168 return nRet; 169 } 170 171 // ------------------------------------------------------------------------- 172 void MacabHeader::sortRecord() 173 { 174 sortRecord(0,size); 175 } 176 177 // ------------------------------------------------------------------------- 178 macabfield **MacabHeader::sortRecord(const sal_Int32 _start, const sal_Int32 _length) 179 { 180 /* Sort using mergesort. Because it uses mergesort, it is recursive and 181 * not in place (so it creates a new array at every step of the 182 * recursion), so if you prefer to use a different sort, please feel 183 * free to implement it. 184 */ 185 macabfield** sorted = new macabfield *[_length]; 186 if(_length <= 2) 187 { 188 if(_length == 2) 189 { 190 if(compareFields(fields[_start], fields[_start+1]) > 0) 191 { 192 sorted[0] = get(_start+1); 193 sorted[1] = get(_start); 194 } 195 else 196 { 197 sorted[0] = get(_start); 198 sorted[1] = get(_start+1); 199 } 200 } 201 else if(_length == 1) 202 { 203 sorted[0] = get(_start); 204 } 205 } 206 else 207 { 208 sal_Int32 halfLength = floor(_length/2); 209 sal_Int32 fp = 0, lp = 0; 210 sal_Int32 i; 211 macabfield **firstHalf = new macabfield *[halfLength]; 212 macabfield **lastHalf = new macabfield *[_length - halfLength]; 213 214 firstHalf = sortRecord(_start, halfLength); 215 lastHalf = sortRecord(_start+halfLength, _length-halfLength); 216 for(i = 0; i < _length; i++) 217 { 218 if(compareFields(firstHalf[fp],lastHalf[lp]) < 0) 219 { 220 sorted[i] = firstHalf[fp++]; 221 if(fp == halfLength) 222 { 223 for( i++; i < _length; i++) 224 { 225 sorted[i] = lastHalf[lp++]; 226 } 227 break; 228 } 229 } 230 else 231 { 232 sorted[i] = lastHalf[lp++]; 233 if(lp == _length - halfLength) 234 { 235 for( i++; i < _length; i++) 236 { 237 sorted[i] = firstHalf[fp++]; 238 } 239 break; 240 } 241 } 242 } 243 if(_length == size) 244 { 245 fields = sorted; 246 } 247 } 248 return sorted; 249 } 250 251 sal_Int32 MacabHeader::compareFields(const macabfield *_field1, const macabfield *_field2) 252 { 253 /* Comparing two fields in a MacabHeader is different than comparing two 254 * fields in a MacabRecord. It starts in the same way (if one of the two 255 * fields is NULL, it belongs after the other, so it is considered 256 * "greater"). But, then, all headers are CFStrings, no matter what 257 * type they claim to be (since they actually hold the expected type for 258 * the records with that header). That being said, all we have to do is 259 * the built-in CFStringCompare. 260 */ 261 if(_field1 == _field2) 262 return 0; 263 if(_field1 == NULL) 264 return 1; 265 if(_field2 == NULL) 266 return -1; 267 268 CFComparisonResult result = CFStringCompare( 269 (CFStringRef) _field1->value, 270 (CFStringRef) _field2->value, 271 0); // 0 = no options (like ignore case) 272 273 return (sal_Int32) result; 274 } 275 276 // ------------------------------------------------------------------------- 277 sal_Int32 MacabHeader::getColumnNumber(const ::rtl::OUString s) const 278 { 279 sal_Int32 i; 280 for(i = 0; i < size; i++) 281 { 282 if(getString(i) == s) 283 break; 284 } 285 286 if(i == size) 287 i = -1; 288 289 return i; 290 } 291 292 // ------------------------------------------------------------------------- 293 MacabHeader *MacabHeader::begin() 294 { 295 return this; 296 } 297 298 // ------------------------------------------------------------------------- 299 MacabHeader::iterator::iterator () 300 { 301 } 302 303 // ------------------------------------------------------------------------- 304 MacabHeader::iterator::~iterator () 305 { 306 } 307 308 void MacabHeader::iterator::operator= (MacabHeader *_record) 309 { 310 id = 0; 311 record = _record; 312 } 313 314 // ------------------------------------------------------------------------- 315 void MacabHeader::iterator::operator++ () 316 { 317 id++; 318 } 319 320 // ------------------------------------------------------------------------- 321 sal_Bool MacabHeader::iterator::operator!= (const sal_Int32 i) const 322 { 323 return(id != i); 324 } 325 326 // ------------------------------------------------------------------------- 327 sal_Bool MacabHeader::iterator::operator== (const sal_Int32 i) const 328 { 329 return(id == i); 330 } 331 332 // ------------------------------------------------------------------------- 333 macabfield *MacabHeader::iterator::operator* () const 334 { 335 return record->get(id); 336 } 337 338 // ------------------------------------------------------------------------- 339 sal_Int32 MacabHeader::end() const 340 { 341 return size; 342 } 343 344