1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "securec.h"
17 #include "contacts_utils.h"
18
19 using namespace OHOS;
20 using namespace OHOS::ContactsFfi;
21 using namespace OHOS::DataShare;
22
23 namespace OHOS {
24 namespace ContactsFfi {
25
26 // return true if succeeded; after it b is fully allocated or completely empty with errCode set
allocBucket(ValuesBucket * b,size_t total,int32_t * errCode)27 bool allocBucket(ValuesBucket* b, size_t total, int32_t *errCode)
28 {
29 if (*errCode != SUCCESS) {
30 return false;
31 }
32 if (total > 0) {
33 b->size = total;
34 b->key = (char**) malloc(total * sizeof(char*));
35 if (b->key == nullptr) {
36 *errCode = ERROR;
37 b->freeContent(); // actually. there is nothing to free, just set size to 0
38 return false;
39 }
40 b->value = (struct CValueType*) malloc(total * sizeof(struct CValueType));
41 if (b->value == nullptr) {
42 *errCode = ERROR;
43 b->freeContent();
44 return false;
45 } else {
46 b->value->tag = static_cast<int>(DataType::TYPE_NULL);
47 b->value->string = nullptr;
48 }
49 }
50 return true;
51 }
52
convertToDataShareVB(ValuesBucket vb)53 DataShareValuesBucket convertToDataShareVB(ValuesBucket vb)
54 {
55 uint64_t size = vb.size;
56 DataShareValuesBucket dsvb = DataShareValuesBucket();
57 for (uint64_t i = 0; i < size; i++) {
58 switch (vb.value[i].tag) {
59 case DataShareValueObjectType::TYPE_STRING: {
60 DataShareValueObject valueObject = DataShareValueObject(std::string(vb.value[i].string));
61 std::string keyStr = vb.key[i];
62 dsvb.Put(keyStr, valueObject);
63 break;
64 }
65 case DataShareValueObjectType::TYPE_INT: {
66 DataShareValueObject valueObject = DataShareValueObject(vb.value[i].integer);
67 std::string keyStr = vb.key[i];
68 dsvb.Put(keyStr, valueObject);
69 break;
70 }
71 default: { // should not reach here
72 std::string keyStr = vb.key[i];
73 HILOG_ERROR("VB unsupported value type is %{public}d for key = %{public}s",
74 vb.value[i].tag, keyStr.c_str());
75 dsvb.Put(vb.key[i], DataShareValueObject());
76 break;
77 }
78 }
79 }
80 return dsvb;
81 }
82
PutQuickSearchKey(std::shared_ptr<DataShareResultSet> & resultSet,std::map<int,std::string> & quickSearchMap,int contactIdValue)83 void PutQuickSearchKey(std::shared_ptr<DataShareResultSet> &resultSet,
84 std::map<int, std::string> &quickSearchMap, int contactIdValue)
85 {
86 std::string quickSearchValue = "";
87 std::string quickSearchKey = "quick_search_key";
88 int columnIndex = 0;
89 resultSet->GetColumnIndex(quickSearchKey, columnIndex);
90 resultSet->GetString(columnIndex, quickSearchValue);
91 if (quickSearchMap.count(contactIdValue) <= 0) {
92 quickSearchMap.insert(std::pair<int, std::string>(contactIdValue, quickSearchValue));
93 }
94 }
95
GetResultMapValue(std::map<int,std::vector<ValuesBucket>> & resultSetMap,int contactId)96 std::vector<ValuesBucket>& GetResultMapValue(std::map<int, std::vector<ValuesBucket>> &resultSetMap, int contactId)
97 {
98 std::map<int, std::vector<ValuesBucket>>::iterator it = resultSetMap.find(contactId);
99 if (it == resultSetMap.end()) {
100 std::vector<ValuesBucket> contactData = std::vector<ValuesBucket>();
101 resultSetMap.insert(std::pair<int, std::vector<ValuesBucket>>(contactId, contactData));
102 it = resultSetMap.find(contactId);
103 }
104 return it->second;
105 }
106
copyBucket(ValuesBucket * dst,int dstIdx,ValuesBucket & src)107 void copyBucket(ValuesBucket* dst, int dstIdx, ValuesBucket &src)
108 {
109 dst[dstIdx].key = src.key;
110 dst[dstIdx].value = src.value;
111 dst[dstIdx].size = src.size;
112 }
113
TransformFromString(std::string & str,int32_t * errCode)114 char* TransformFromString(std::string &str, int32_t* errCode)
115 {
116 size_t len = str.size() + 1;
117 char* retValue = static_cast<char *>(malloc(len));
118 if (retValue == nullptr) {
119 *errCode = ERROR;
120 return nullptr;
121 }
122 *errCode = memcpy_s(retValue, len, str.c_str(), len);
123 if (*errCode != SUCCESS) {
124 free(retValue);
125 retValue = nullptr;
126 }
127 return retValue;
128 }
129
allocBucketData(std::vector<KeyWithValueType> & bucketData,int32_t * errCode)130 ValuesBucket allocBucketData(std::vector<KeyWithValueType> &bucketData, int32_t *errCode)
131 {
132 struct ValuesBucket b;
133 size_t total = bucketData.size();
134 if (total > 0) {
135 if (!allocBucket(&b, total, errCode)) {
136 return b;
137 }
138 // Let's increment b.size one by one for b.freeContent() call in case of error
139 b.size = 0;
140 for (size_t i = 0; i < total; i++) {
141 bucketData[i].allocToBucket(&b, 0, i, errCode);
142 if (*errCode != SUCCESS) {
143 b.freeContent();
144 return b;
145 } else {
146 b.size = b.size + 1; // b.size is incremented one by one for b.freeContent() call in case of error
147 }
148 }
149 }
150 return b;
151 }
152
singleStringAsValueBucket(std::string contentType,std::string value,int32_t * errCode)153 ValuesBucket singleStringAsValueBucket(std::string contentType, std::string value, int32_t *errCode)
154 {
155 std::vector<KeyWithValueType> bucketData;
156 bucketData.push_back(KeyWithValueType("content_type", contentType));
157 bucketData.push_back(KeyWithValueType("detail_info", value));
158 return allocBucketData(bucketData, errCode);
159 }
160
PutResultValue(std::vector<KeyWithValueType> & bucket,std::string contentStoreKey,std::shared_ptr<DataShareResultSet> & resultSet,std::string contentLoadKey)161 void PutResultValue(std::vector<KeyWithValueType> &bucket, std::string contentStoreKey,
162 std::shared_ptr<DataShareResultSet> &resultSet, std::string contentLoadKey)
163 {
164 int columnIndex = 0;
165 resultSet->GetColumnIndex(contentLoadKey, columnIndex);
166 DataType columnType;
167 resultSet->GetDataType(columnIndex, columnType);
168
169 // NULL and BLOB are ignored here
170 if (columnType == DataType::TYPE_STRING) {
171 std::string stringValue;
172 resultSet->GetString(columnIndex, stringValue);
173 bucket.push_back(KeyWithValueType(contentStoreKey, stringValue));
174 } else if (columnType == DataType::TYPE_INTEGER) {
175 int intValue = 0;
176 resultSet->GetInt(columnIndex, intValue);
177 bucket.push_back(KeyWithValueType(contentStoreKey, (int64_t) intValue));
178 } else if (columnType == DataType::TYPE_FLOAT) {
179 double doubleValue = 0;
180 resultSet->GetDouble(columnIndex, doubleValue);
181 bucket.push_back(KeyWithValueType(contentStoreKey, doubleValue));
182 } else if (columnType != DataType::TYPE_NULL) { // TYPE_NULL is just ignored
183 HILOG_ERROR("PutResultValue unsupported columnType for key %{public}s is %{public}d",
184 contentLoadKey.c_str(), columnType);
185 }
186 }
187
PutResultValue(std::vector<KeyWithValueType> & bucket,std::shared_ptr<DataShareResultSet> & resultSet,std::string contentKey)188 void PutResultValue(std::vector<KeyWithValueType> &bucket,
189 std::shared_ptr<DataShareResultSet> &resultSet, std::string contentKey)
190 {
191 PutResultValue(bucket, contentKey, resultSet, contentKey);
192 }
193
194 /**
195 * @brief Converting resultset of a query to Email data ValuesBucket
196 */
resultSetAsEmail(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)197 ValuesBucket resultSetAsEmail(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
198 {
199 std::vector<KeyWithValueType> bucketData;
200 bucketData.push_back(KeyWithValueType("content_type", "email"));
201 PutResultValue(bucketData, resultSet, "detail_info");
202 PutResultValue(bucketData, resultSet, "alias_detail_info");
203 PutResultValue(bucketData, resultSet, "custom_data");
204 PutResultValue(bucketData, resultSet, "extend7");
205 return allocBucketData(bucketData, errCode);
206 }
207
208 /**
209 * @brief Converting resultset of a query to Name data ValuesBucket
210 */
resultSetAsName(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)211 ValuesBucket resultSetAsName(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
212 {
213 std::vector<KeyWithValueType> bucketData;
214 bucketData.push_back(KeyWithValueType("content_type", "name"));
215 PutResultValue(bucketData, resultSet, "detail_info");
216 PutResultValue(bucketData, resultSet, "alpha_name");
217 PutResultValue(bucketData, resultSet, "other_lan_last_name");
218 PutResultValue(bucketData, resultSet, "other_lan_first_name");
219 PutResultValue(bucketData, resultSet, "family_name");
220 PutResultValue(bucketData, resultSet, "middle_name_phonetic");
221 PutResultValue(bucketData, resultSet, "given_name");
222 PutResultValue(bucketData, resultSet, "given_name_phonetic");
223 PutResultValue(bucketData, resultSet, "phonetic_name");
224 return allocBucketData(bucketData, errCode);
225 }
226
227 /**
228 * @brief Converting resultset of a query to Portrait data ValuesBucket
229 */
resultSetAsPortrait(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)230 ValuesBucket resultSetAsPortrait(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
231 {
232 std::vector<KeyWithValueType> bucketData;
233 bucketData.push_back(KeyWithValueType("content_type", "photo"));
234 PutResultValue(bucketData, resultSet, "detail_info");
235 return allocBucketData(bucketData, errCode);
236 }
237
238 /**
239 * @brief Converting resultset of a query to Event data ValuesBucket
240 */
resultSetAsEvent(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)241 ValuesBucket resultSetAsEvent(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
242 {
243 std::vector<KeyWithValueType> bucketData;
244 bucketData.push_back(KeyWithValueType("content_type", "contact_event"));
245
246 PutResultValue(bucketData, resultSet, "detail_info");
247 PutResultValue(bucketData, resultSet, "custom_data");
248 PutResultValue(bucketData, resultSet, "extend7");
249
250 return allocBucketData(bucketData, errCode);
251 }
252
253 /**
254 * @brief Converting resultset of a query to Group data ValuesBucket
255 */
resultSetAsGroup(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)256 ValuesBucket resultSetAsGroup(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
257 {
258 std::vector<KeyWithValueType> bucketData;
259 bucketData.push_back(KeyWithValueType("content_type", "group_membership"));
260 PutResultValue(bucketData, resultSet, "detail_info");
261 PutResultValue(bucketData, resultSet, "group_name");
262
263 return allocBucketData(bucketData, errCode);
264 }
265
266 /**
267 * @brief Converting resultset of a query to ImAddress data ValuesBucket
268 */
resultSetAsImAddress(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)269 ValuesBucket resultSetAsImAddress(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
270 {
271 std::vector<KeyWithValueType> bucketData;
272 bucketData.push_back(KeyWithValueType("content_type", "im"));
273 PutResultValue(bucketData, resultSet, "detail_info");
274 PutResultValue(bucketData, resultSet, "custom_data");
275 PutResultValue(bucketData, resultSet, "extend7");
276
277 return allocBucketData(bucketData, errCode);
278 }
279
280 /**
281 * @brief Converting resultset of a query to PhoneNumber data ValuesBucket
282 */
resultSetAsPhone(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)283 ValuesBucket resultSetAsPhone(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
284 {
285 std::vector<KeyWithValueType> bucketData;
286 bucketData.push_back(KeyWithValueType("content_type", "phone"));
287 PutResultValue(bucketData, resultSet, "detail_info");
288 PutResultValue(bucketData, resultSet, "custom_data");
289 PutResultValue(bucketData, resultSet, "extend7");
290
291 return allocBucketData(bucketData, errCode);
292 }
293
294 /**
295 * @brief Converting resultset of a query to PostalAddress data ValuesBucket
296 */
resultSetAsPostAddress(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)297 ValuesBucket resultSetAsPostAddress(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
298 {
299 std::vector<KeyWithValueType> bucketData;
300 bucketData.push_back(KeyWithValueType("content_type", "postal_address"));
301 PutResultValue(bucketData, resultSet, "detail_info");
302 PutResultValue(bucketData, resultSet, "neighborhood");
303 PutResultValue(bucketData, resultSet, "pobox");
304 PutResultValue(bucketData, resultSet, "postcode");
305 PutResultValue(bucketData, resultSet, "region");
306 PutResultValue(bucketData, resultSet, "street");
307 PutResultValue(bucketData, resultSet, "city");
308 PutResultValue(bucketData, resultSet, "country");
309 PutResultValue(bucketData, resultSet, "custom_data");
310 PutResultValue(bucketData, resultSet, "extend7");
311
312 return allocBucketData(bucketData, errCode);
313 }
314
315 /**
316 * @brief Converting resultset of a query to Relation data ValuesBucket
317 */
resultSetAsRelation(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)318 ValuesBucket resultSetAsRelation(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
319 {
320 std::vector<KeyWithValueType> bucketData;
321 bucketData.push_back(KeyWithValueType("content_type", "relation"));
322 PutResultValue(bucketData, resultSet, "detail_info");
323 PutResultValue(bucketData, resultSet, "custom_data");
324 PutResultValue(bucketData, resultSet, "extend7");
325
326 return allocBucketData(bucketData, errCode);
327 }
328
329 /**
330 * @brief Converting resultset of a query to SipAddress data ValuesBucket
331 */
resultSetAsSipAddress(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)332 ValuesBucket resultSetAsSipAddress(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
333 {
334 std::vector<KeyWithValueType> bucketData;
335 bucketData.push_back(KeyWithValueType("content_type", "sip_address"));
336 PutResultValue(bucketData, resultSet, "detail_info");
337 PutResultValue(bucketData, resultSet, "custom_data");
338 PutResultValue(bucketData, resultSet, "extend7");
339
340 return allocBucketData(bucketData, errCode);
341 }
342
343 /**
344 * @brief Converting resultset of a query to Website data ValuesBucket
345 */
resultSetAsWebsite(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)346 ValuesBucket resultSetAsWebsite(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
347 {
348 std::vector<KeyWithValueType> bucketData;
349 bucketData.push_back(KeyWithValueType("content_type", "website"));
350 PutResultValue(bucketData, resultSet, "detail_info");
351
352 return allocBucketData(bucketData, errCode);
353 }
354
355 /**
356 * @brief Converting resultset of a query to Nickname data ValuesBucket
357 */
resultSetAsNickname(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)358 ValuesBucket resultSetAsNickname(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
359 {
360 std::vector<KeyWithValueType> bucketData;
361 bucketData.push_back(KeyWithValueType("content_type", "nickname"));
362 PutResultValue(bucketData, resultSet, "detail_info");
363
364 return allocBucketData(bucketData, errCode);
365 }
366
367 /**
368 * @brief Converting resultset of a query to Note data ValuesBucket
369 */
resultSetAsNote(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)370 ValuesBucket resultSetAsNote(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
371 {
372 std::vector<KeyWithValueType> bucketData;
373 bucketData.push_back(KeyWithValueType("content_type", "note"));
374 PutResultValue(bucketData, resultSet, "detail_info");
375
376 return allocBucketData(bucketData, errCode);
377 }
378
379 /**
380 * @brief Converting resultset of a query to Organization data ValuesBucket
381 */
resultSetAsOrganization(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)382 ValuesBucket resultSetAsOrganization(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
383 {
384 std::vector<KeyWithValueType> bucketData;
385 bucketData.push_back(KeyWithValueType("content_type", "organization"));
386 PutResultValue(bucketData, resultSet, "detail_info");
387 PutResultValue(bucketData, resultSet, "position");
388
389 return allocBucketData(bucketData, errCode);
390 }
391
392 /**
393 * @brief Converting resultset of a query to one of contact's ValuesBucket
394 */
addResultSetAsValuesBucket(std::vector<ValuesBucket> & contactData,std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)395 void addResultSetAsValuesBucket(std::vector<ValuesBucket> &contactData,
396 std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
397 {
398 int typeIdValue = 0;
399 std::string typeId = "type_id";
400 int columnIndexType = 0;
401 resultSet->GetColumnIndex(typeId, columnIndexType);
402 resultSet->GetInt(columnIndexType, typeIdValue);
403 switch (typeIdValue) {
404 case EMAIL: contactData.push_back(resultSetAsEmail(resultSet, errCode)); return;
405 case NAME: contactData.push_back(resultSetAsName(resultSet, errCode)); return;
406 case PHOTO: contactData.push_back(resultSetAsPortrait(resultSet, errCode)); return;
407 case CONTACT_EVENT: contactData.push_back(resultSetAsEvent(resultSet, errCode)); return;
408 case GROUP_MEMBERSHIP: contactData.push_back(resultSetAsGroup(resultSet, errCode)); return;
409 case IM: contactData.push_back(resultSetAsImAddress(resultSet, errCode)); return;
410 case PHONE: contactData.push_back(resultSetAsPhone(resultSet, errCode)); return;
411 case POSTAL_ADDRESS: contactData.push_back(resultSetAsPostAddress(resultSet, errCode)); return;
412 case RELATION: contactData.push_back(resultSetAsRelation(resultSet, errCode)); return;
413 case SIP_ADDRESS: contactData.push_back(resultSetAsSipAddress(resultSet, errCode)); return;
414 case WEBSITE: contactData.push_back(resultSetAsWebsite(resultSet, errCode)); return;
415 case NICKNAME: contactData.push_back(resultSetAsNickname(resultSet, errCode)); return;
416 case NOTE: contactData.push_back(resultSetAsNote(resultSet, errCode)); return;
417 case ORGANIZATION: contactData.push_back(resultSetAsOrganization(resultSet, errCode)); return;
418 default: return;
419 }
420 }
421
422 // returns false when mem allocation failed
allocateDataForContact(ContactsData * allContacts,int contactIndex,int contactId,std::string searchKey,std::vector<ValuesBucket> contactDataVector,int32_t * errCode)423 bool allocateDataForContact(ContactsData* allContacts, int contactIndex, int contactId, std::string searchKey,
424 std::vector<ValuesBucket> contactDataVector, int32_t *errCode)
425 {
426 int bucketIndex = 0;
427 // consider passing contactId as integer value
428 ValuesBucket idBucket = singleStringAsValueBucket("id", std::to_string(contactId), errCode);
429 if (*errCode != SUCCESS) {
430 free(allContacts->contactsData[contactIndex].data);
431 allContacts->contactsData[contactIndex].bucketCount = 0;
432 allContacts->contactsData[contactIndex].data = nullptr;
433 return false;
434 }
435 ValuesBucket searchKeyBucket = singleStringAsValueBucket("key", searchKey, errCode);
436 if (*errCode != SUCCESS) {
437 idBucket.freeContent();
438 free(allContacts->contactsData[contactIndex].data);
439 allContacts->contactsData[contactIndex].bucketCount = 0;
440 allContacts->contactsData[contactIndex].data = nullptr;
441 return false;
442 }
443
444 copyBucket(allContacts->contactsData[contactIndex].data, bucketIndex, idBucket);
445 bucketIndex++;
446 copyBucket(allContacts->contactsData[contactIndex].data, bucketIndex, searchKeyBucket);
447 bucketIndex++;
448
449 // copy bucket pointers from vector
450 for (std::vector<ValuesBucket>::size_type i = 0; i < contactDataVector.size(); i++, bucketIndex++) {
451 copyBucket(allContacts->contactsData[contactIndex].data, bucketIndex, contactDataVector[i]);
452 }
453
454 return true;
455 }
456
releaseRresultSetMapBuckets(std::map<int,std::vector<ValuesBucket>> resultSetMap)457 void releaseRresultSetMapBuckets(std::map<int, std::vector<ValuesBucket>> resultSetMap)
458 {
459 std::map<int, std::vector<ValuesBucket>>::iterator it;
460 for (it = resultSetMap.begin(); it != resultSetMap.end(); it++) {
461 std::vector<ValuesBucket> contactDataVector = it->second;
462 for (std::vector<ValuesBucket>::size_type i = 0; i < contactDataVector.size(); i++) {
463 ValuesBucket bucket = contactDataVector[i];
464 bucket.freeContent();
465 }
466 }
467 }
468
allocCollectedContacts(std::map<int,std::vector<ValuesBucket>> & resultSetMap,std::map<int,std::string> & quickSearchMap,int32_t * errCode)469 ContactsData* allocCollectedContacts(std::map<int, std::vector<ValuesBucket>> &resultSetMap,
470 std::map<int, std::string> &quickSearchMap, int32_t *errCode)
471 {
472 ContactsData* allContacts = (struct ContactsData*) malloc(sizeof(struct ContactsData));
473 if (allContacts == nullptr) {
474 HILOG_ERROR("ContactUtils::allocCollectedContacts fail to mem alloc");
475 *errCode = ERROR;
476 return nullptr;
477 }
478
479 size_t totalContacts = resultSetMap.size();
480 if (totalContacts == 0 || totalContacts > MAX_CONTACTS) {
481 free(allContacts);
482 return nullptr;
483 }
484
485 allContacts->contactsData = (ContactData*) malloc(totalContacts * sizeof(ContactData));
486 if (allContacts->contactsData == nullptr) {
487 free(allContacts);
488 HILOG_ERROR("ContactUtils::allocCollectedContacts fail to mem alloc");
489 *errCode = ERROR;
490 return nullptr;
491 }
492 allContacts->contactsCount = totalContacts;
493
494 int contactIndex = 0;
495 std::map<int, std::vector<ValuesBucket>>::iterator it;
496 for (it = resultSetMap.begin(); it != resultSetMap.end(); it++, contactIndex++) {
497 int contactId = it->first;
498 std::vector<ValuesBucket> contactDataVector = it->second;
499 std::string searchKey = quickSearchMap.find(contactId)->second;
500
501 if (*errCode != SUCCESS) {
502 allContacts->contactsData[contactIndex].bucketCount = 0;
503 allContacts->contactsData[contactIndex].data = nullptr;
504 continue;
505 }
506 size_t totalBuckets = 2 + contactDataVector.size(); // 2 more for contactId and searchKey buckets
507 allContacts->contactsData[contactIndex].bucketCount = totalBuckets;
508 allContacts->contactsData[contactIndex].data =
509 (struct ValuesBucket*) malloc(totalBuckets * sizeof(struct ValuesBucket));
510 if (allContacts->contactsData[contactIndex].data == nullptr) {
511 *errCode = ERROR;
512 continue;
513 }
514
515 allocateDataForContact(allContacts, contactIndex, contactId, searchKey, contactDataVector, errCode);
516 }
517
518 if (*errCode == SUCCESS) {
519 return allContacts;
520 }
521
522 allContacts->freeContent();
523 free(allContacts);
524 allContacts = nullptr;
525 releaseRresultSetMapBuckets(resultSetMap);
526
527 return nullptr;
528 }
529
530 // it closes resultSet after parse
parseResultSetForContacts(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)531 ContactsData* parseResultSetForContacts(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
532 {
533 if (resultSet == nullptr) {
534 HILOG_ERROR("ContactUtils::parseResultSetForContacts resultSet is nullptr");
535 return nullptr;
536 }
537 int rowCount = 0;
538 resultSet->GetRowCount(rowCount);
539 HILOG_INFO("parseResultSetForContacts GetRowCount is %{public}d", rowCount);
540 if (rowCount == 0) {
541 resultSet->Close();
542 return nullptr;
543 }
544 std::map<int, std::vector<ValuesBucket>> resultSetMap; // factored by contactId
545 std::map<int, std::string> quickSearchMap;
546 int resultSetNum = resultSet->GoToFirstRow();
547 while (resultSetNum == 0) {
548 int contactIdValue = 0;
549 std::string contactIdKey = "contact_id";
550 int contactIndex = 0;
551 resultSet->GetColumnIndex(contactIdKey, contactIndex);
552 resultSet->GetInt(contactIndex, contactIdValue);
553 std::vector<ValuesBucket>& contactData = GetResultMapValue(resultSetMap, contactIdValue);
554 PutQuickSearchKey(resultSet, quickSearchMap, contactIdValue);
555 addResultSetAsValuesBucket(contactData, resultSet, errCode);
556 if (*errCode != SUCCESS) {
557 HILOG_ERROR("ContactUtils::parseResultSetForContacts fail to mem alloc");
558 break;
559 }
560 resultSetNum = resultSet->GoToNextRow();
561 }
562 resultSet->Close();
563
564 if (*errCode != SUCCESS) {
565 std::map<int, std::vector<ValuesBucket>>::iterator it;
566 for (it = resultSetMap.begin(); it != resultSetMap.end(); it++) {
567 std::vector<ValuesBucket> contactDataVector = it->second;
568 for (std::vector<ValuesBucket>::size_type i = 0; i < contactDataVector.size(); i++) {
569 ValuesBucket bucket = contactDataVector[i];
570 bucket.freeContent();
571 }
572 }
573 return nullptr;
574 }
575 return allocCollectedContacts(resultSetMap, quickSearchMap, errCode);
576 }
577
578 /**
579 * @brief Converting resultset of a query to Group data ValuesBucket
580 */
resultSetAsGroup(ValuesBucket * groups,int idx,std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)581 void resultSetAsGroup(ValuesBucket* groups, int idx, std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
582 {
583 std::vector<KeyWithValueType> bucketData;
584 // content_type for group is redundant
585 PutResultValue(bucketData, "detail_info", resultSet, "id");
586 PutResultValue(bucketData, "group_name", resultSet, "group_name");
587
588 ValuesBucket bucket = allocBucketData(bucketData, errCode);
589 if (*errCode != SUCCESS) {
590 HILOG_ERROR("ContactUtils::resultSetAsGroup fail to mem alloc");
591 } else {
592 copyBucket(groups, idx, bucket);
593 }
594 }
595
596 /**
597 * @brief Converting resultset of a query to Holder data ValuesBucket
598 */
resultSetAsHolder(ValuesBucket * holders,int idx,std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)599 void resultSetAsHolder(ValuesBucket* holders, int idx, std::shared_ptr<DataShareResultSet> &resultSet,
600 int32_t *errCode)
601 {
602 std::vector<KeyWithValueType> bucketData;
603 // content_type for holder is redundant
604 PutResultValue(bucketData, "detail_info", resultSet, "account_name");
605 PutResultValue(bucketData, "custom_data", resultSet, "account_type");
606 PutResultValue(bucketData, "extend7", resultSet, "id");
607
608 ValuesBucket bucket = allocBucketData(bucketData, errCode);
609 if (*errCode != SUCCESS) {
610 HILOG_ERROR("ContactUtils::resultSetAsHolder fail to mem alloc");
611 } else {
612 copyBucket(holders, idx, bucket);
613 }
614 }
615
616 // it closes resultSet after parse
parseResultSetForGroups(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)617 GroupsData* parseResultSetForGroups(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
618 {
619 if (resultSet == nullptr) {
620 HILOG_ERROR("ContactUtils::parseResultSetForGroups resultSet is nullptr");
621 return nullptr;
622 }
623 int totalGroups = 0;
624 resultSet->GetRowCount(totalGroups);
625 HILOG_INFO("parseResultSetForGroups GetRowCount is %{public}d", totalGroups);
626 if (totalGroups <= 0) {
627 return nullptr;
628 }
629
630 GroupsData* allGroups = (GroupsData*) malloc(sizeof(GroupsData));
631 if (allGroups == nullptr) {
632 HILOG_ERROR("ContactUtils::parseResultSetForGroups fail to mem alloc");
633 *errCode = ERROR;
634 return nullptr;
635 }
636 allGroups->data = (struct ValuesBucket*) malloc(totalGroups * sizeof(struct ValuesBucket));
637 if (allGroups->data == nullptr) {
638 free(allGroups);
639 HILOG_ERROR("ContactUtils::parseResultSetForGroups fail to mem alloc");
640 *errCode = ERROR;
641 return NULL;
642 }
643 allGroups->bucketCount = static_cast<uint64_t>(totalGroups);
644
645 int resultSetNum = resultSet->GoToFirstRow();
646 int count = 0;
647 while (resultSetNum == 0) {
648 resultSetAsGroup(allGroups->data, count, resultSet, errCode);
649 if (*errCode != SUCCESS) {
650 break;
651 }
652 resultSetNum = resultSet->GoToNextRow();
653 count++;
654 }
655 resultSet->Close();
656
657 if (*errCode != SUCCESS) {
658 allGroups->freeContent();
659 free(allGroups);
660 allGroups = nullptr;
661 }
662
663 return allGroups;
664 }
665
666 // it closes resultSet after parse
parseResultSetForHolders(std::shared_ptr<DataShareResultSet> & resultSet,int32_t * errCode)667 HoldersData* parseResultSetForHolders(std::shared_ptr<DataShareResultSet> &resultSet, int32_t *errCode)
668 {
669 if (resultSet == nullptr) {
670 HILOG_ERROR("ContactUtils::parseResultSetForHolders resultSet is nullptr");
671 return nullptr;
672 }
673 int totalHolders = 0;
674 resultSet->GetRowCount(totalHolders);
675 HILOG_INFO("parseResultSetForHolders GetRowCount is %{public}d", totalHolders);
676 if (totalHolders <= 0) {
677 return nullptr;
678 }
679
680 HoldersData* allHolders = (HoldersData*) malloc(sizeof(HoldersData));
681 if (allHolders == nullptr) {
682 HILOG_ERROR("ContactUtils::parseResultSetForHolders fail to mem alloc");
683 *errCode = ERROR;
684 return nullptr;
685 }
686 allHolders->data = (struct ValuesBucket*) malloc(totalHolders * sizeof(struct ValuesBucket));
687 if (allHolders->data == nullptr) {
688 free(allHolders);
689 HILOG_ERROR("ContactUtils::parseResultSetForHolders fail to mem alloc");
690 *errCode = ERROR;
691 return nullptr;
692 }
693 allHolders->bucketCount = static_cast<uint64_t>(totalHolders);
694
695 int resultSetNum = resultSet->GoToFirstRow();
696 int count = 0;
697 while (resultSetNum == 0) {
698 resultSetAsHolder(allHolders->data, count, resultSet, errCode);
699 if (*errCode != SUCCESS) {
700 break;
701 }
702 resultSetNum = resultSet->GoToNextRow();
703 count++;
704 }
705 resultSet->Close();
706
707 if (*errCode != SUCCESS) {
708 allHolders->freeContent();
709 free(allHolders);
710 allHolders = nullptr;
711 }
712
713 return allHolders;
714 }
715
716 } // namespace ContactsFfi
717 } // namespace OHOS
718