• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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