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