From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- connectivity/source/drivers/macab/MacabHeader.cxx | 330 ++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 connectivity/source/drivers/macab/MacabHeader.cxx (limited to 'connectivity/source/drivers/macab/MacabHeader.cxx') diff --git a/connectivity/source/drivers/macab/MacabHeader.cxx b/connectivity/source/drivers/macab/MacabHeader.cxx new file mode 100644 index 000000000..da270dd05 --- /dev/null +++ b/connectivity/source/drivers/macab/MacabHeader.cxx @@ -0,0 +1,330 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "MacabHeader.hxx" +#include "MacabRecord.hxx" +#include "macabutilities.hxx" + +#include +#include +#include + +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 = std::make_unique(size); + for(i = 0; i < size; i++) + { + if(_fields[i] == nullptr) + { + fields[i] = nullptr; + } + 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 = nullptr; +} + + +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 = std::make_unique(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(); + size += numAdded; + fields.reset(newFields); + } + } +} + + +OUString MacabHeader::getString(const sal_Int32 i) const +{ + OUString nRet; + + if(i < size) + { + if(fields[i] == nullptr || fields[i]->value == nullptr || CFGetTypeID(fields[i]->value) != CFStringGetTypeID()) + return OUString(); + try + { + nRet = CFStringToOUString(static_cast(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 = sortRecord(_start, halfLength); + macabfield **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.reset(sorted); + } + delete firstHalf; + delete lastHalf; + } + 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 == nullptr) + return 1; + if(_field2 == nullptr) + return -1; + + CFComparisonResult result = CFStringCompare( + static_cast(_field1->value), + static_cast(_field2->value), + 0); // 0 = no options (like ignore case) + + return static_cast(result); +} + + +sal_Int32 MacabHeader::getColumnNumber(std::u16string_view 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& MacabHeader::iterator::operator= (MacabHeader *_record) +{ + id = 0; + record = _record; + return *this; +} + + +void MacabHeader::iterator::operator++ () +{ + id++; +} + + +bool MacabHeader::iterator::operator!= (const sal_Int32 i) const +{ + return(id != i); +} + + +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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3