LibreOffice Module connectivity (master) 1
MacabRecord.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include "MacabRecord.hxx"
22#include "macabutilities.hxx"
23#include <com/sun/star/util/DateTime.hpp>
24
25#include <premac.h>
26#include <Carbon/Carbon.h>
27#include <AddressBook/ABAddressBookC.h>
28#include <postmac.h>
30
31using namespace connectivity::macab;
32using namespace com::sun::star::util;
33using namespace ::dbtools;
34
35
36MacabRecord::MacabRecord() : size(0)
37{
38}
39
40
41MacabRecord::MacabRecord(const sal_Int32 _size)
42 : size(_size),
43 fields(std::make_unique<macabfield *[]>(size))
44{
45 sal_Int32 i;
46 for(i = 0; i < size; i++)
47 fields[i] = nullptr;
48}
49
50
52{
53 if(size > 0)
54 {
56 int i;
57 for(i = 0; i < size; i++)
58 {
59 delete fields[i];
60 fields[i] = nullptr;
61 }
62 }
63}
64
65
66void MacabRecord::insertAtColumn (CFTypeRef _value, ABPropertyType _type, const sal_Int32 _column)
67{
68 if(_column < size)
69 {
70 if(fields[_column] == nullptr)
71 fields[_column] = new macabfield;
72
73 fields[_column]->value = _value;
74 if (fields[_column]->value)
75 CFRetain(fields[_column]->value);
76 fields[_column]->type = _type;
77 }
78}
79
80
81bool MacabRecord::contains (const macabfield *_field) const
82{
83 if(_field == nullptr)
84 return false;
85 else
86 return contains(_field->value);
87}
88
89
90bool MacabRecord::contains (const CFTypeRef _value) const
91{
92 sal_Int32 i;
93 for(i = 0; i < size; i++)
94 {
95 if(fields[i] != nullptr)
96 {
97 if(CFEqual(fields[i]->value, _value))
98 {
99 return true;
100 }
101 }
102 }
103
104 return false;
105}
106
107
108sal_Int32 MacabRecord::getSize() const
109{
110 return size;
111}
112
113
114macabfield *MacabRecord::copy(const sal_Int32 i) const
115{
116 /* Note: copy(i) creates a new macabfield identical to that at
117 * location i, whereas get(i) returns a pointer to the macabfield
118 * at location i.
119 */
120 if(i < size)
121 {
122 macabfield *_copy = new macabfield;
123 _copy->type = fields[i]->type;
124 _copy->value = fields[i]->value;
125 if (_copy->value)
126 CFRetain(_copy->value);
127 return _copy;
128 }
129
130 return nullptr;
131}
132
133
134macabfield *MacabRecord::get(const sal_Int32 i) const
135{
136 /* Note: copy(i) creates a new macabfield identical to that at
137 * location i, whereas get(i) returns a pointer to the macabfield
138 * at location i.
139 */
140 if(i < size)
141 {
142 return fields[i];
143 }
144
145 return nullptr;
146}
147
148
150{
151 /* This method is, at the moment, only used in MacabHeader.cxx, but
152 * the idea is simple: if you are not destroying this object but want
153 * to clear it of its macabfields, you should release each field's
154 * value.
155 */
156 sal_Int32 i;
157 for(i = 0; i < size; i++)
158 CFRelease(fields[i]->value);
159}
160
161
162sal_Int32 MacabRecord::compareFields(const macabfield *_field1, const macabfield *_field2)
163{
164
165 /* When comparing records, if either field is NULL (and the other is
166 * not), that field is considered "greater than" the other, so that it
167 * shows up later in the list when fields are ordered.
168 */
169 if(_field1 == _field2)
170 return 0;
171 if(_field1 == nullptr)
172 return 1;
173 if(_field2 == nullptr)
174 return -1;
175
176 /* If they aren't the same type, for now, return the one with
177 * the smaller type ID... I don't know of a better way to compare
178 * two different data types.
179 */
180 if(_field1->type != _field2->type)
181 return(_field1->type - _field2->type);
182
183 CFComparisonResult result;
184
185 /* Carbon has a unique compare function for each data type: */
186 switch(_field1->type)
187 {
188 case kABStringProperty:
189 result = CFStringCompare(
190 static_cast<CFStringRef>(_field1->value),
191 static_cast<CFStringRef>(_field2->value),
192 kCFCompareLocalized); // Specifies that the comparison should take into account differences related to locale, such as the thousands separator character.
193 break;
194
195 case kABDateProperty:
196 result = CFDateCompare(
197 static_cast<CFDateRef>(_field1->value),
198 static_cast<CFDateRef>(_field2->value),
199 nullptr); // NULL = unused variable
200 break;
201
202 case kABIntegerProperty:
203 case kABRealProperty:
204 result = CFNumberCompare(
205 static_cast<CFNumberRef>(_field1->value),
206 static_cast<CFNumberRef>(_field2->value),
207 nullptr); // NULL = unused variable
208 break;
209
210 default:
211 result = kCFCompareEqualTo; // can't compare
212 }
213
214 return static_cast<sal_Int32>(result);
215}
216
217
218/* Create a macabfield out of an OUString and type. Together with the
219 * method fieldToString() (below), it is possible to switch conveniently
220 * between an OUString and a macabfield (for use when creating and handling
221 * SQL statement).
222 */
223macabfield *MacabRecord::createMacabField(const OUString& _newFieldString, const ABPropertyType _abType)
224{
225 macabfield *newField = nullptr;
226 switch(_abType)
227 {
228 case kABStringProperty:
229 newField = new macabfield;
230 newField->value = OUStringToCFString(_newFieldString);
231 newField->type = _abType;
232 break;
233 case kABDateProperty:
234 {
235 DateTime aDateTime = DBTypeConversion::toDateTime(_newFieldString);
236
237 // bad format...
238 if(aDateTime.Year == 0 && aDateTime.Month == 0 && aDateTime.Day == 0)
239 {
240 }
241 else
242 {
244 nTime -= kCFAbsoluteTimeIntervalSince1970;
245 newField = new macabfield;
246 newField->value = CFDateCreate(nullptr, static_cast<CFAbsoluteTime>(nTime));
247 newField->type = _abType;
248 }
249 }
250 break;
251 case kABIntegerProperty:
252 try
253 {
254 sal_Int64 nVal = _newFieldString.toInt64();
255
256 newField = new macabfield;
257 newField->value = CFNumberCreate(nullptr,kCFNumberLongType, &nVal);
258 newField->type = _abType;
259 }
260 // bad format...
261 catch(...)
262 {
263 }
264 break;
265 case kABRealProperty:
266 try
267 {
268 double nVal = _newFieldString.toDouble();
269
270 newField = new macabfield;
271 newField->value = CFNumberCreate(nullptr,kCFNumberDoubleType, &nVal);
272 newField->type = _abType;
273 }
274 // bad format...
275 catch(...)
276 {
277 }
278 break;
279 default:
280 ;
281 }
282 return newField;
283}
284
285
286/* Create an OUString out of a macabfield. Together with the method
287 * createMacabField() (above), it is possible to switch conveniently
288 * between an OUString and a macabfield (for use when creating and handling
289 * SQL statement).
290 */
292{
293 if(_aField == nullptr)
294 return OUString();
295
296 OUString fieldString;
297
298 switch(_aField->type)
299 {
300 case kABStringProperty:
301 fieldString = CFStringToOUString(static_cast<CFStringRef>(_aField->value));
302 break;
303 case kABDateProperty:
304 {
305 DateTime aTime = CFDateToDateTime(static_cast<CFDateRef>(_aField->value));
306 fieldString = DBTypeConversion::toDateTimeString(aTime);
307 }
308 break;
309 case kABIntegerProperty:
310 {
311 CFNumberType numberType = CFNumberGetType( static_cast<CFNumberRef>(_aField->value) );
312 sal_Int64 nVal;
313 // Should we check for the wrong type here, e.g., a float?
314 bool m_bSuccess = !CFNumberGetValue(static_cast<CFNumberRef>(_aField->value), numberType, &nVal);
315 if(m_bSuccess)
316 fieldString = OUString::number(nVal);
317 }
318 break;
319 case kABRealProperty:
320 {
321 CFNumberType numberType = CFNumberGetType( static_cast<CFNumberRef>(_aField->value) );
322 double nVal;
323 // Should we check for the wrong type here, e.g., an int?
324 bool m_bSuccess = !CFNumberGetValue(static_cast<CFNumberRef>(_aField->value), numberType, &nVal);
325 if(m_bSuccess)
326 fieldString = OUString::number(nVal);
327 }
328 break;
329 default:
330 ;
331 }
332 return fieldString;
333
334}
335
336/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static double toDouble(std::string_view rString)
Definition: DTable.cxx:1635
std::unique_ptr< macabfield *[]> fields
Definition: MacabRecord.hxx:50
void insertAtColumn(CFTypeRef _value, ABPropertyType _type, const sal_Int32 _column)
Definition: MacabRecord.cxx:66
macabfield * get(const sal_Int32 i) const
static macabfield * createMacabField(const OUString &_newFieldString, const ABPropertyType _abtype)
static OUString fieldToString(const macabfield *_aField)
static sal_Int32 compareFields(const macabfield *_field1, const macabfield *_field2)
macabfield * copy(const sal_Int32 i) const
bool contains(const macabfield *_field) const
Definition: MacabRecord.cxx:81
Any value
size
CFStringRef OUStringToCFString(const OUString &aString)
css::util::DateTime CFDateToDateTime(const CFDateRef _cfDate)
OUString CFStringToOUString(const CFStringRef sOrig)
OOO_DLLPUBLIC_DBTOOLS css::util::Date const & getStandardDate()
OOO_DLLPUBLIC_DBTOOLS OUString toDateTimeString(const css::util::DateTime &_rDateTime)
OOO_DLLPUBLIC_DBTOOLS css::util::DateTime toDateTime(double dVal, const css::util::Date &_rNullDate=getStandardDate())
int i
Any result