diff options
Diffstat (limited to 'connectivity/source/drivers/macab/MacabHeader.cxx')
-rw-r--r-- | connectivity/source/drivers/macab/MacabHeader.cxx | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/connectivity/source/drivers/macab/MacabHeader.cxx b/connectivity/source/drivers/macab/MacabHeader.cxx new file mode 100644 index 000000000000..09772a9a9cbd --- /dev/null +++ b/connectivity/source/drivers/macab/MacabHeader.cxx @@ -0,0 +1,346 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: MacabHeader.cxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" + +#include "MacabHeader.hxx" +#include "MacabRecord.hxx" +#include "macabutilities.hxx" + +#include <math.h> +#include <com/sun/star/sdbc/DataType.hpp> +#include <connectivity/dbconversion.hxx> + +using namespace connectivity::macab; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::util; +using namespace ::dbtools; + +// ------------------------------------------------------------------------- +MacabHeader::MacabHeader(const sal_Int32 _size, macabfield **_fields) +{ + sal_Int32 i; + size = _size; + fields = new macabfield *[size]; + for(i = 0; i < size; i++) + { + if(_fields[i] == NULL) + { + fields[i] = NULL; + } + else + { + /* The constructor duplicates the macabfields it gets because they + * are either deleted later or used for other purposes. + */ + fields[i] = new macabfield; + fields[i]->type = _fields[i]->type; + fields[i]->value = _fields[i]->value; + if (fields[i]->value) + CFRetain(fields[i]->value); + } + } + +} + +// ------------------------------------------------------------------------- +MacabHeader::MacabHeader() +{ + size = 0; + fields = NULL; +} + +// ------------------------------------------------------------------------- +MacabHeader::~MacabHeader() +{ +} + +// ------------------------------------------------------------------------- +void MacabHeader::operator+= (const MacabHeader *r) +{ + /* Add one MacabHeader to another. Anything not already in the header is + * added to the end of it. + */ + sal_Int32 rSize = r->getSize(); + if(rSize != 0) // If the new header does actually have fields + { + /* If our header is currently empty, just copy all of the fields from + * the new header to this one. + */ + if(size == 0) + { + sal_Int32 i; + size = rSize; + fields = new macabfield *[size]; + for(i = 0; i < size; i++) + { + fields[i] = r->copy(i); + } + } + + /* Otherwise, only add the duplicates. We do this with a two-pass + * approach. First, find out how many fields to add, then reallocate + * the size of the fields array and add the old ones at the end. + * (More precisely, we create a _new_ fields array with the new length + * allocated to it, then get all of the fields from the current + * fields array to it, then copy the non-duplicates from the new + * header to the end.) + */ + else + { + sal_Int32 i; + sal_Int32 numToAdd = 0, numAdded = 0; + macabfield **newFields; + for( i = 0; i < rSize; i++) + { + if(!contains(r->get(i))) + { + numToAdd++; + } + } + + newFields = new macabfield *[size+numToAdd]; + for(i = 0; i < size; i++) + { + newFields[i] = copy(i); + } + + for( i = 0; i < rSize; i++) + { + if(!contains(r->get(i))) + { + newFields[size+numAdded] = r->copy(i); + numAdded++; + if(numAdded == numToAdd) + break; + } + } + + releaseFields(); + delete [] fields; + size += numAdded; + fields = newFields; + } + } +} + +// ------------------------------------------------------------------------- +::rtl::OUString MacabHeader::getString(const sal_Int32 i) const +{ + ::rtl::OUString nRet; + + if(i < size) + { + if(fields[i] == NULL || fields[i]->value == NULL || CFGetTypeID(fields[i]->value) != CFStringGetTypeID()) + return ::rtl::OUString(); + try + { + nRet = CFStringToOUString( (CFStringRef) fields[i]->value); + } + catch(...){ } + } + + return nRet; +} + +// ------------------------------------------------------------------------- +void MacabHeader::sortRecord() +{ + sortRecord(0,size); +} + +// ------------------------------------------------------------------------- +macabfield **MacabHeader::sortRecord(const sal_Int32 _start, const sal_Int32 _length) +{ + /* Sort using mergesort. Because it uses mergesort, it is recursive and + * not in place (so it creates a new array at every step of the + * recursion), so if you prefer to use a different sort, please feel + * free to implement it. + */ + macabfield** sorted = new macabfield *[_length]; + if(_length <= 2) + { + if(_length == 2) + { + if(compareFields(fields[_start], fields[_start+1]) > 0) + { + sorted[0] = get(_start+1); + sorted[1] = get(_start); + } + else + { + sorted[0] = get(_start); + sorted[1] = get(_start+1); + } + } + else if(_length == 1) + { + sorted[0] = get(_start); + } + } + else + { + sal_Int32 halfLength = floor(_length/2); + sal_Int32 fp = 0, lp = 0; + sal_Int32 i; + macabfield **firstHalf = new macabfield *[halfLength]; + macabfield **lastHalf = new macabfield *[_length - halfLength]; + + firstHalf = sortRecord(_start, halfLength); + lastHalf = sortRecord(_start+halfLength, _length-halfLength); + for(i = 0; i < _length; i++) + { + if(compareFields(firstHalf[fp],lastHalf[lp]) < 0) + { + sorted[i] = firstHalf[fp++]; + if(fp == halfLength) + { + for( i++; i < _length; i++) + { + sorted[i] = lastHalf[lp++]; + } + break; + } + } + else + { + sorted[i] = lastHalf[lp++]; + if(lp == _length - halfLength) + { + for( i++; i < _length; i++) + { + sorted[i] = firstHalf[fp++]; + } + break; + } + } + } + if(_length == size) + { + fields = sorted; + } + } + return sorted; +} + +sal_Int32 MacabHeader::compareFields(const macabfield *_field1, const macabfield *_field2) +{ + /* Comparing two fields in a MacabHeader is different than comparing two + * fields in a MacabRecord. It starts in the same way (if one of the two + * fields is NULL, it belongs after the other, so it is considered + * "greater"). But, then, all headers are CFStrings, no matter what + * type they claim to be (since they actually hold the expected type for + * the records with that header). That being said, all we have to do is + * the built-in CFStringCompare. + */ + if(_field1 == _field2) + return 0; + if(_field1 == NULL) + return 1; + if(_field2 == NULL) + return -1; + + CFComparisonResult result = CFStringCompare( + (CFStringRef) _field1->value, + (CFStringRef) _field2->value, + 0); // 0 = no options (like ignore case) + + return (sal_Int32) result; +} + +// ------------------------------------------------------------------------- +sal_Int32 MacabHeader::getColumnNumber(const ::rtl::OUString s) const +{ + sal_Int32 i; + for(i = 0; i < size; i++) + { + if(getString(i) == s) + break; + } + + if(i == size) + i = -1; + + return i; +} + +// ------------------------------------------------------------------------- +MacabHeader *MacabHeader::begin() +{ + return this; +} + +// ------------------------------------------------------------------------- +MacabHeader::iterator::iterator () +{ +} + +// ------------------------------------------------------------------------- +MacabHeader::iterator::~iterator () +{ +} + +void MacabHeader::iterator::operator= (MacabHeader *_record) +{ + id = 0; + record = _record; +} + +// ------------------------------------------------------------------------- +void MacabHeader::iterator::operator++ () +{ + id++; +} + +// ------------------------------------------------------------------------- +sal_Bool MacabHeader::iterator::operator!= (const sal_Int32 i) const +{ + return(id != i); +} + +// ------------------------------------------------------------------------- +sal_Bool MacabHeader::iterator::operator== (const sal_Int32 i) const +{ + return(id == i); +} + +// ------------------------------------------------------------------------- +macabfield *MacabHeader::iterator::operator* () const +{ + return record->get(id); +} + +// ------------------------------------------------------------------------- +sal_Int32 MacabHeader::end() const +{ + return size; +} + |