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