1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "MacabRecord.hxx"
22 #include "macabutilities.hxx"
23 #include <com/sun/star/util/DateTime.hpp>
26 #include <Carbon/Carbon.h>
27 #include <AddressBook/ABAddressBookC.h>
29 #include <connectivity/dbconversion.hxx>
31 using namespace connectivity::macab
;
32 using namespace com::sun::star::util
;
33 using namespace ::dbtools
;
36 MacabRecord::MacabRecord() : size(0)
41 MacabRecord::MacabRecord(const sal_Int32 _size
)
43 fields(std::make_unique
<macabfield
*[]>(size
))
46 for(i
= 0; i
< size
; i
++)
51 MacabRecord::~MacabRecord()
57 for(i
= 0; i
< size
; i
++)
66 void MacabRecord::insertAtColumn (CFTypeRef _value
, ABPropertyType _type
, const sal_Int32 _column
)
70 if(fields
[_column
] == nullptr)
71 fields
[_column
] = new macabfield
;
73 fields
[_column
]->value
= _value
;
74 if (fields
[_column
]->value
)
75 CFRetain(fields
[_column
]->value
);
76 fields
[_column
]->type
= _type
;
81 bool MacabRecord::contains (const macabfield
*_field
) const
86 return contains(_field
->value
);
90 bool MacabRecord::contains (const CFTypeRef _value
) const
93 for(i
= 0; i
< size
; i
++)
95 if(fields
[i
] != nullptr)
97 if(CFEqual(fields
[i
]->value
, _value
))
108 sal_Int32
MacabRecord::getSize() const
114 macabfield
*MacabRecord::copy(const sal_Int32 i
) const
116 /* Note: copy(i) creates a new macabfield identical to that at
117 * location i, whereas get(i) returns a pointer to the macabfield
122 macabfield
*_copy
= new macabfield
;
123 _copy
->type
= fields
[i
]->type
;
124 _copy
->value
= fields
[i
]->value
;
126 CFRetain(_copy
->value
);
134 macabfield
*MacabRecord::get(const sal_Int32 i
) const
136 /* Note: copy(i) creates a new macabfield identical to that at
137 * location i, whereas get(i) returns a pointer to the macabfield
149 void MacabRecord::releaseFields()
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
157 for(i
= 0; i
< size
; i
++)
158 CFRelease(fields
[i
]->value
);
162 sal_Int32
MacabRecord::compareFields(const macabfield
*_field1
, const macabfield
*_field2
)
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.
169 if(_field1
== _field2
)
171 if(_field1
== nullptr)
173 if(_field2
== nullptr)
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.
180 if(_field1
->type
!= _field2
->type
)
181 return(_field1
->type
- _field2
->type
);
183 CFComparisonResult result
;
185 /* Carbon has a unique compare function for each data type: */
186 switch(_field1
->type
)
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.
195 case kABDateProperty
:
196 result
= CFDateCompare(
197 static_cast<CFDateRef
>(_field1
->value
),
198 static_cast<CFDateRef
>(_field2
->value
),
199 nullptr); // NULL = unused variable
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
211 result
= kCFCompareEqualTo
; // can't compare
214 return static_cast<sal_Int32
>(result
);
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
223 macabfield
*MacabRecord::createMacabField(const OUString
& _newFieldString
, const ABPropertyType _abType
)
225 macabfield
*newField
= nullptr;
228 case kABStringProperty
:
229 newField
= new macabfield
;
230 newField
->value
= OUStringToCFString(_newFieldString
);
231 newField
->type
= _abType
;
233 case kABDateProperty
:
235 DateTime aDateTime
= DBTypeConversion::toDateTime(_newFieldString
);
238 if(aDateTime
.Year
== 0 && aDateTime
.Month
== 0 && aDateTime
.Day
== 0)
243 double nTime
= DBTypeConversion::toDouble(aDateTime
, DBTypeConversion::getStandardDate());
244 nTime
-= kCFAbsoluteTimeIntervalSince1970
;
245 newField
= new macabfield
;
246 newField
->value
= CFDateCreate(nullptr, static_cast<CFAbsoluteTime
>(nTime
));
247 newField
->type
= _abType
;
251 case kABIntegerProperty
:
254 sal_Int64 nVal
= _newFieldString
.toInt64();
256 newField
= new macabfield
;
257 newField
->value
= CFNumberCreate(nullptr,kCFNumberLongType
, &nVal
);
258 newField
->type
= _abType
;
265 case kABRealProperty
:
268 double nVal
= _newFieldString
.toDouble();
270 newField
= new macabfield
;
271 newField
->value
= CFNumberCreate(nullptr,kCFNumberDoubleType
, &nVal
);
272 newField
->type
= _abType
;
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
291 OUString
MacabRecord::fieldToString(const macabfield
*_aField
)
293 if(_aField
== nullptr)
296 OUString fieldString
;
298 switch(_aField
->type
)
300 case kABStringProperty
:
301 fieldString
= CFStringToOUString(static_cast<CFStringRef
>(_aField
->value
));
303 case kABDateProperty
:
305 DateTime aTime
= CFDateToDateTime(static_cast<CFDateRef
>(_aField
->value
));
306 fieldString
= DBTypeConversion::toDateTimeString(aTime
);
309 case kABIntegerProperty
:
311 CFNumberType numberType
= CFNumberGetType( static_cast<CFNumberRef
>(_aField
->value
) );
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
);
316 fieldString
= OUString::number(nVal
);
319 case kABRealProperty
:
321 CFNumberType numberType
= CFNumberGetType( static_cast<CFNumberRef
>(_aField
->value
) );
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
);
326 fieldString
= OUString::number(nVal
);
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */