1/*
2 * Copyright (c) 2021-2022 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 "skills.h"
17using namespace OHOS;
18using namespace OHOS::AppExecFwk;
19namespace OHOS {
20namespace AAFwk {
21namespace {
22const size_t LENGTH_FOR_FINDMINETYPE = 3;
23constexpr int CYCLE_LIMIT = 1000;
24}
25/**
26 * @brief Default constructor used to create a Skills instance.
27 */
28Skills::Skills()
29{}
30
31/**
32 * @brief A parameterized constructor used to create a Skills instance.
33 *
34 * @param skills Indicates skills used to create a Skills instance.
35 */
36Skills::Skills(const Skills &skills)
37{
38    // entities_
39    entities_ = skills.entities_;
40    // actions_
41    actions_ = skills.actions_;
42    // authorities_
43    authorities_ = skills.authorities_;
44    // schemes_
45    schemes_ = skills.schemes_;
46
47    // paths_
48    paths_ = skills.paths_;
49    // schemeSpecificParts_
50    schemeSpecificParts_ = skills.schemeSpecificParts_;
51    // types_
52    types_ = skills.types_;
53}
54
55Skills::~Skills()
56{
57    entities_.clear();
58    actions_.clear();
59    authorities_.clear();
60    schemes_.clear();
61
62    paths_.clear();
63    schemeSpecificParts_.clear();
64    types_.clear();
65}
66
67/**
68 * @brief Obtains the list of entities.
69 *
70 * @return vector of Entities.
71 */
72std::vector<std::string> Skills::GetEntities() const
73{
74    return entities_;
75}
76
77/**
78 * @brief Obtains the specified entity.
79 *
80 * @param entity Id of the specified entity.
81 */
82std::string Skills::GetEntity(int index) const
83{
84    if (index < 0 || entities_.empty() || std::size_t(index) >= entities_.size()) {
85        return std::string();
86    }
87    return entities_.at(index);
88}
89
90/**
91 * @brief Adds an entity to this Skills object.
92 *
93 * @param entity Indicates the entity to add.
94 */
95void Skills::AddEntity(const std::string &entity)
96{
97    auto it = std::find(entities_.begin(), entities_.end(), entity);
98    if (it == entities_.end()) {
99        entities_.emplace_back(entity);
100    }
101}
102
103/**
104 * @brief Checks whether the specified entity is exist.
105 *
106 * @param entity Name of the specified entity.
107 */
108bool Skills::HasEntity(const std::string &entity)
109{
110    return std::find(entities_.begin(), entities_.end(), entity) != entities_.end();
111}
112
113/**
114 * @brief Remove the specified entity.
115 *
116 * @param entity Name of the specified entity.
117 */
118void Skills::RemoveEntity(const std::string &entity)
119{
120    if (!entities_.empty()) {
121        auto it = std::find(entities_.begin(), entities_.end(), entity);
122        if (it != entities_.end()) {
123            entities_.erase(it);
124        }
125    }
126}
127
128/**
129 * @brief Obtains the count of entities.
130 *
131 */
132int Skills::CountEntities() const
133{
134    return entities_.empty() ? 0 : entities_.size();
135}
136
137/**
138 * @brief Obtains the specified action.
139 *
140 * @param actionId Id of the specified action.
141 */
142std::string Skills::GetAction(int index) const
143{
144    if (index < 0 || actions_.empty() || std::size_t(index) >= actions_.size()) {
145        return std::string();
146    } else {
147        return actions_.at(index);
148    }
149}
150
151/**
152 * @brief Adds an action to this Skills object.
153 *
154 * @param action Indicates the action to add.
155 */
156void Skills::AddAction(const std::string &action)
157{
158    auto it = std::find(actions_.begin(), actions_.end(), action);
159    if (it == actions_.end()) {
160        actions_.emplace_back(action);
161    }
162}
163
164/**
165 * @brief Checks whether the specified action is exist.
166 *
167 * @param action Name of the specified action.
168 */
169bool Skills::HasAction(const std::string &action)
170{
171    return std::find(actions_.begin(), actions_.end(), action) != actions_.end();
172}
173
174/**
175 * @brief Remove the specified action.
176 *
177 * @param action Name of the specified action.
178 */
179void Skills::RemoveAction(const std::string &action)
180{
181    if (!actions_.empty()) {
182        auto it = std::find(actions_.begin(), actions_.end(), action);
183        if (it != actions_.end()) {
184            actions_.erase(it);
185        }
186    }
187}
188
189/**
190 * @brief Obtains the count of actions.
191 *
192 */
193int Skills::CountActions() const
194{
195    return actions_.empty() ? 0 : actions_.size();
196}
197
198/**
199 * @brief Obtains the iterator of Actions.
200 *
201 * @return iterator of Actions.
202 */
203std::vector<std::string>::iterator Skills::ActionsIterator()
204{
205    return actions_.begin();
206}
207
208/**
209 * @brief Obtains the specified authority.
210 *
211 * @param authorityId Id of the specified authority.
212 */
213std::string Skills::GetAuthority(int index) const
214{
215    if (index < 0 || authorities_.empty() || std::size_t(index) >= authorities_.size()) {
216        return std::string();
217    } else {
218        return authorities_.at(index);
219    }
220}
221
222/**
223 * @brief Adds an authority to this Skills object.
224 *
225 * @param authority Indicates the authority to add.
226 */
227void Skills::AddAuthority(const std::string &authority)
228{
229    auto it = std::find(authorities_.begin(), authorities_.end(), authority);
230    if (it == authorities_.end()) {
231        authorities_.emplace_back(authority);
232    }
233}
234
235/**
236 * @brief Checks whether the specified authority is exist.
237 *
238 * @param action Name of the specified authority.
239 */
240bool Skills::HasAuthority(const std::string &authority)
241{
242    return std::find(authorities_.begin(), authorities_.end(), authority) != authorities_.end();
243}
244
245/**
246 * @brief Remove the specified authority.
247 *
248 * @param authority Name of the specified authority.
249 */
250void Skills::RemoveAuthority(const std::string &authority)
251{
252    if (!authorities_.empty()) {
253        auto it = std::find(authorities_.begin(), authorities_.end(), authority);
254        if (it != authorities_.end()) {
255            authorities_.erase(it);
256        }
257    }
258}
259
260/**
261 * @brief Obtains the count of authorities.
262 *
263 */
264int Skills::CountAuthorities() const
265{
266    return authorities_.empty() ? 0 : authorities_.size();
267}
268
269/**
270 * @brief Obtains the specified path.
271 *
272 * @param pathId Id of the specified path.
273 */
274std::string Skills::GetPath(int index) const
275{
276    if (index < 0 || paths_.empty() || std::size_t(index) >= paths_.size()) {
277        return std::string();
278    }
279    return paths_.at(index).GetPattern();
280}
281
282/**
283 * @brief Adds a path to this Skills object.
284 *
285 * @param path Indicates the path to add.
286 */
287void Skills::AddPath(const std::string &path)
288{
289    PatternsMatcher pm(path, MatchType::DEFAULT);
290    AddPath(pm);
291}
292
293/**
294 * @brief Adds a path to this Skills object.
295 *
296 * @param path Indicates the path to add.
297 */
298void Skills::AddPath(const PatternsMatcher &patternsMatcher)
299{
300    auto hasPath = std::find_if(paths_.begin(), paths_.end(), [&patternsMatcher](const PatternsMatcher pm) {
301        return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType());
302    });
303    if (hasPath == paths_.end()) {
304        paths_.emplace_back(patternsMatcher);
305    }
306}
307
308/**
309 * @brief Adds a path to this Skills object.
310 *
311 * @param path Indicates the path to add.
312 * @param matchType the specified match type.
313 */
314void Skills::AddPath(const std::string &path, const MatchType &matchType)
315{
316    PatternsMatcher pm(path, matchType);
317    AddPath(pm);
318}
319
320/**
321 * @brief Checks whether the specified path is exist.
322 *
323 * @param path Name of the specified path.
324 */
325bool Skills::HasPath(const std::string &path)
326{
327    auto hasPath = std::find_if(
328        paths_.begin(), paths_.end(), [&path](const PatternsMatcher pm) { return pm.GetPattern() == path; });
329    return hasPath != paths_.end();
330}
331
332/**
333 * @brief Remove the specified path.
334 *
335 * @param path Name of the specified path.
336 */
337void Skills::RemovePath(const std::string &path)
338{
339    auto hasPath = std::find_if(
340        paths_.begin(), paths_.end(), [&path](const PatternsMatcher pm) { return pm.GetPattern() == path; });
341    if (hasPath != paths_.end()) {
342        paths_.erase(hasPath);
343    }
344}
345
346/**
347 * @brief Remove the specified path.
348 *
349 * @param path The path to be added.
350 */
351void Skills::RemovePath(const PatternsMatcher &patternsMatcher)
352{
353    auto hasPath = std::find_if(paths_.begin(), paths_.end(), [&patternsMatcher](const PatternsMatcher pm) {
354        return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType());
355    });
356    if (hasPath != paths_.end()) {
357        paths_.erase(hasPath);
358    }
359}
360
361/**
362 * @brief Remove the specified path.
363 *
364 * @param path Name of the specified path.
365 * @param matchType the specified match type.
366 */
367void Skills::RemovePath(const std::string &path, const MatchType &matchType)
368{
369    PatternsMatcher pm(path, matchType);
370    RemovePath(pm);
371}
372
373/**
374 * @brief Obtains the count of paths.
375 *
376 */
377int Skills::CountPaths() const
378{
379    return paths_.empty() ? 0 : paths_.size();
380}
381
382/**
383 * @brief Obtains the specified scheme.
384 *
385 * @param schemeId Id of the specified scheme.
386 */
387std::string Skills::GetScheme(int index) const
388{
389    if (index < 0 || schemes_.empty() || std::size_t(index) >= schemes_.size()) {
390        return std::string();
391    }
392    return schemes_.at(index);
393}
394
395/**
396 * @brief Adds an scheme to this Skills object.
397 *
398 * @param scheme Indicates the scheme to add.
399 */
400void Skills::AddScheme(const std::string &scheme)
401{
402    auto it = std::find(schemes_.begin(), schemes_.end(), scheme);
403    if (it == schemes_.end()) {
404        schemes_.emplace_back(scheme);
405    }
406}
407
408/**
409 * @brief Checks whether the specified scheme is exist.
410 *
411 * @param scheme Name of the specified scheme.
412 */
413bool Skills::HasScheme(const std::string &scheme)
414{
415    return std::find(schemes_.begin(), schemes_.end(), scheme) != schemes_.end();
416}
417
418/**
419 * @brief Remove the specified scheme.
420 *
421 * @param scheme Name of the specified scheme.
422 */
423void Skills::RemoveScheme(const std::string &scheme)
424{
425    if (!schemes_.empty()) {
426        auto it = std::find(schemes_.begin(), schemes_.end(), scheme);
427        if (it != schemes_.end()) {
428            schemes_.erase(it);
429        }
430    }
431}
432
433/**
434 * @brief Obtains the count of schemes.
435 *
436 */
437int Skills::CountSchemes() const
438{
439    return schemes_.empty() ? 0 : schemes_.size();
440}
441
442/**
443 * @brief Obtains the specified scheme part.
444 *
445 * @param schemeId Id of the specified scheme part.
446 */
447std::string Skills::GetSchemeSpecificPart(int index) const
448{
449    if (index < 0 || schemeSpecificParts_.empty() || std::size_t(index) >= schemeSpecificParts_.size()) {
450        return std::string();
451    }
452    return schemeSpecificParts_.at(index).GetPattern();
453}
454
455/**
456 * @brief Adds an scheme to this Skills object.
457 *
458 * @param scheme Indicates the scheme to add.
459 */
460void Skills::AddSchemeSpecificPart(const std::string &schemeSpecificPart)
461{
462    PatternsMatcher patternsMatcher(schemeSpecificPart, MatchType::DEFAULT);
463    auto it = std::find_if(
464        schemeSpecificParts_.begin(), schemeSpecificParts_.end(), [&patternsMatcher](const PatternsMatcher pm) {
465            return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType());
466        });
467    if (it == schemeSpecificParts_.end()) {
468        schemeSpecificParts_.emplace_back(patternsMatcher);
469    }
470}
471
472/**
473 * @brief Checks whether the specified scheme part is exist.
474 *
475 * @param scheme Name of the specified scheme part.
476 */
477bool Skills::HasSchemeSpecificPart(const std::string &schemeSpecificPart)
478{
479    auto it = std::find_if(schemeSpecificParts_.begin(),
480        schemeSpecificParts_.end(),
481        [&schemeSpecificPart](const PatternsMatcher pm) { return pm.GetPattern() == schemeSpecificPart; });
482    return it != schemeSpecificParts_.end();
483}
484
485/**
486 * @brief Remove the specified scheme part.
487 *
488 * @param scheme Name of the specified scheme part.
489 */
490void Skills::RemoveSchemeSpecificPart(const std::string &schemeSpecificPart)
491{
492    auto it = std::find_if(schemeSpecificParts_.begin(),
493        schemeSpecificParts_.end(),
494        [&schemeSpecificPart](const PatternsMatcher pm) { return pm.GetPattern() == schemeSpecificPart; });
495    if (it != schemeSpecificParts_.end()) {
496        schemeSpecificParts_.erase(it);
497    }
498}
499
500/**
501 * @brief Obtains the count of scheme parts.
502 *
503 */
504int Skills::CountSchemeSpecificParts() const
505{
506    return schemeSpecificParts_.empty() ? 0 : schemeSpecificParts_.size();
507}
508
509/**
510 * @brief Obtains the specified type.
511 *
512 * @param typeId Id of the specified type.
513 */
514std::string Skills::GetType(int index) const
515{
516    if (index < 0 || types_.empty() || std::size_t(index) >= types_.size()) {
517        return std::string();
518    }
519    return types_.at(index).GetPattern();
520}
521
522/**
523 * @brief Adds a type to this Skills object.
524 *
525 * @param type Indicates the type to add.
526 */
527void Skills::AddType(const std::string &type)
528{
529    PatternsMatcher pm(type, MatchType::DEFAULT);
530    AddType(pm);
531}
532
533/**
534 * @brief Adds a type to this Skills object.
535 *
536 * @param type Indicates the type to add.
537 * @param matchType the specified match type.
538 */
539void Skills::AddType(const std::string &type, const MatchType &matchType)
540{
541    PatternsMatcher pm(type, matchType);
542    AddType(pm);
543}
544
545/**
546 * @brief Adds a type to this Skills object.
547 *
548 * @param type Indicates the type to add.
549 */
550void Skills::AddType(const PatternsMatcher &patternsMatcher)
551{
552    const size_t posNext = 1;
553    const size_t posOffset = 2;
554    std::string type = patternsMatcher.GetPattern();
555    size_t slashpos = type.find('/');
556    size_t typelen = type.length();
557    if (slashpos != std::string::npos && typelen >= slashpos + posOffset) {
558        if (typelen == slashpos + posOffset && type.at(slashpos + posNext) == '*') {
559            PatternsMatcher pm(type.substr(0, slashpos), patternsMatcher.GetType());
560            auto it = std::find_if(types_.begin(),
561                types_.end(),
562                [type = pm.GetPattern(), matchType = pm.GetType()](
563                    const PatternsMatcher pm) { return (pm.GetPattern() == type) && (pm.GetType() == matchType); });
564            if (it == types_.end()) {
565                types_.emplace_back(pm);
566            }
567            hasPartialTypes_ = true;
568        } else {
569            PatternsMatcher pm(patternsMatcher);
570            auto it = std::find_if(types_.begin(),
571                types_.end(),
572                [type = pm.GetPattern(), matchType = pm.GetType()](
573                    const PatternsMatcher pm) { return (pm.GetPattern() == type) && (pm.GetType() == matchType); });
574            if (it == types_.end()) {
575                types_.emplace_back(pm);
576            }
577        }
578    }
579}
580
581/**
582 * @brief Checks whether the specified type is exist.
583 *
584 * @param type Name of the specified type.
585 */
586bool Skills::HasType(const std::string &type)
587{
588    auto it = std::find_if(
589        types_.begin(), types_.end(), [&type](const PatternsMatcher pm) { return pm.GetPattern() == type; });
590    return it != types_.end();
591}
592
593/**
594 * @brief Remove the specified type.
595 *
596 * @param type Name of the specified type.
597 */
598void Skills::RemoveType(const std::string &type)
599{
600    auto it = std::find_if(
601        types_.begin(), types_.end(), [&type](const PatternsMatcher pm) { return pm.GetPattern() == type; });
602    if (it != types_.end()) {
603        types_.erase(it);
604    }
605}
606
607/**
608 * @brief Remove the specified scheme type.
609 *
610 * @param patternsMatcher The type to be added.
611 */
612void Skills::RemoveType(const PatternsMatcher &patternsMatcher)
613{
614    auto it = std::find_if(types_.begin(), types_.end(), [&patternsMatcher](const PatternsMatcher pm) {
615        return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType());
616    });
617    if (it != types_.end()) {
618        types_.erase(it);
619    }
620}
621
622/**
623 * @brief Remove the specified scheme type.
624 *
625 * @param type Name of the specified type.
626 * @param matchType the specified match type.
627 */
628void Skills::RemoveType(const std::string &type, const MatchType &matchType)
629{
630    PatternsMatcher pm(type, matchType);
631    RemoveType(pm);
632}
633
634/**
635 * @brief Obtains the count of types.
636 *
637 */
638int Skills::CountTypes() const
639{
640    return types_.empty() ? 0 : types_.size();
641}
642
643/**
644 * @brief Match this skill against a Want's data.
645 *
646 * @param want The desired want data to match for.
647 */
648bool Skills::Match(const Want &want)
649{
650    if (!MatchAction(want.GetAction())) {
651        return false;
652    }
653
654    int dataMatch = MatchData(want.GetType(), want.GetScheme(), want.GetUri());
655    if (dataMatch < 0) {
656        return false;
657    }
658
659    std::string entityMismatch = MatchEntities(want.GetEntities());
660    if (entityMismatch == std::string()) {
661        return false;
662    }
663
664    return true;
665}
666
667/**
668 * @brief Match this skills against a Want's entities.  Each entity in
669 * the Want must be specified by the skills; if any are not in the
670 * skills, the match fails.
671 *
672 * @param entities The entities included in the want, as returned by
673 *                   Want.getEntities().
674 *
675 * @return If all entities match (success), null; else the name of the
676 *         first entity that didn't match.
677 */
678std::string Skills::MatchEntities(const std::vector<std::string> &entities)
679{
680    if (!entities.empty()) {
681        size_t size = entities.size();
682        for (size_t i = 0; i < size; i++) {
683            auto it = std::find(entities_.begin(), entities_.end(), entities[i]);
684            if (it != entities_.end()) {
685                return entities[i];
686            }
687        }
688    }
689
690    return std::string();
691}
692
693/**
694 * @brief Match this skills against a Want's action.  If the skills does not
695 * specify any actions, the match will always fail.
696 *
697 * @param action The desired action to look for.
698 *
699 * @return True if the action is listed in the skills.
700 */
701bool Skills::MatchAction(const std::string &action)
702{
703    return (action.empty() && actions_.empty()) || HasAction(action);
704}
705
706/**
707 * @brief Match this skills against a Want's data (type, scheme and path).
708 *
709 * @param type The desired data type to look for.
710 * @param scheme The desired data scheme to look for.
711 * @param data The full data string to match against.
712 *
713 * @return Returns either a valid match constant.
714 */
715int Skills::MatchData(const std::string &type, const std::string &scheme, Uri data)
716{
717    std::vector<std::string> types;
718    for (auto it = types_.begin(); it != types_.end(); it++) {
719        types.emplace_back(it->GetPattern());
720    }
721    std::vector<std::string> schemes = schemes_;
722
723    int match = RESULT_EMPTY;
724
725    if (types.empty() && schemes.empty()) {
726        return (type == std::string() ? (RESULT_EMPTY + RESULT_NORMAL) : DISMATCH_DATA);
727    }
728
729    if (!schemes.empty()) {
730        auto it = std::find(schemes.begin(), schemes.end(), scheme);
731        if (it != schemes.end()) {
732            match = RESULT_SCHEME;
733        } else {
734            return DISMATCH_DATA;
735        }
736
737        std::vector<PatternsMatcher> schemeSpecificParts = schemeSpecificParts_;
738        if (schemeSpecificParts.size() >= 0) {
739            match = HasSchemeSpecificPart(data.GetSchemeSpecificPart()) ? RESULT_SCHEME_SPECIFIC_PART : DISMATCH_DATA;
740        }
741        if (match != RESULT_SCHEME_SPECIFIC_PART) {
742            std::vector<std::string> authorities = authorities_;
743            if (authorities.size() >= 0) {
744                bool authMatch = HasAuthority(data.GetAuthority());
745                if (authMatch == false) {
746                    return DISMATCH_DATA;
747                }
748                std::vector<PatternsMatcher> paths = paths_;
749                if (paths.size() <= 0) {
750                    match = authMatch;
751                } else if (HasPath(data.GetPath())) {
752                    match = RESULT_PATH;
753                } else {
754                    return DISMATCH_DATA;
755                }
756            }
757        }
758        if (match == DISMATCH_DATA) {
759            return DISMATCH_DATA;
760        }
761    } else {
762        if (scheme != std::string() && scheme != "content" && scheme != "file") {
763            return DISMATCH_DATA;
764        }
765    }
766
767    if (!types.empty()) {
768        if (FindMimeType(type)) {
769            match = RESULT_TYPE;
770        } else {
771            return DISMATCH_TYPE;
772        }
773    } else {
774        if (type != std::string()) {
775            return DISMATCH_TYPE;
776        }
777    }
778
779    return match + RESULT_NORMAL;
780}
781
782bool Skills::FindMimeType(const std::string &type)
783{
784    const int posNext = 1;
785    const int posOffset = 2;
786    std::vector<PatternsMatcher> types = types_;
787
788    if (type == std::string()) {
789        return false;
790    }
791    auto it = types.begin();
792    for (; it != types.end(); it++) {
793        if (it->GetPattern() == type) {
794            break;
795        }
796    }
797    if (it != types.end()) {
798        return true;
799    }
800
801    size_t typeLength = type.length();
802    if (typeLength == LENGTH_FOR_FINDMINETYPE && type == "*/*") {
803        return !types.empty();
804    }
805
806    auto hasType =
807        std::find_if(types.begin(), types.end(), [](const PatternsMatcher pm) { return pm.GetPattern() == "*"; });
808    if (hasPartialTypes_ && hasType != types.end()) {
809        return true;
810    }
811
812    auto typeIt = type.find(0, 1, '/');
813    size_t slashpos = type.size() - typeIt;
814    if (slashpos <= 0) {
815        return false;
816    }
817
818    std::string typeSubstr = type.substr(0, slashpos);
819
820    hasType = std::find_if(types.begin(), types.end(), [&typeSubstr](const PatternsMatcher pm) {
821        return pm.GetPattern() == typeSubstr;
822    });
823    if (hasPartialTypes_ && hasType != types.end()) {
824        return true;
825    }
826
827    if (typeLength == slashpos + posOffset && type.at(slashpos + posNext) == '*') {
828        size_t numTypes = types.size();
829        for (size_t i = 0; i < numTypes; i++) {
830            std::string value = types.at(i).GetPattern();
831            if (RegionMatches(type, 0, value, 0, slashpos + posNext)) {
832                return true;
833            }
834        }
835    }
836
837    return false;
838}
839
840bool Skills::RegionMatches(const std::string &type, int toffset, const std::string &other, int ooffset, int len)
841{
842    int to = toffset;
843    int po = ooffset;
844    // Note: toffset, ooffset, or len might be near -1>>>1.
845    if ((ooffset < 0) || (toffset < 0) || (toffset > (long)type.size() - len) ||
846        (ooffset > (long)other.length() - len)) {
847        return false;
848    }
849    while (len-- > 0) {
850        if (type.at(to++) != other.at(po++)) {
851            return false;
852        }
853    }
854    return true;
855}
856
857/**
858 * @brief Obtains the want params data.
859 *
860 * @return the WantParams object.
861 */
862const WantParams &Skills::GetWantParams() const
863{
864    return wantParams_;
865}
866
867/**
868 * @brief Sets a WantParams object in this MatchingSkills object.
869 *
870 * @param wantParams Indicates the WantParams object.
871 */
872void Skills::SetWantParams(const WantParams &wantParams)
873{
874    wantParams_ = wantParams;
875}
876
877/**
878 * @brief Marshals this Sequenceable object into a Parcel.
879 *
880 * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled.
881 */
882bool Skills::Marshalling(Parcel &parcel) const
883{
884    // entities​_
885    WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, entities_);
886    // actions_
887    WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, actions_);
888    // authorities_
889    WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, authorities_);
890    // schemes_
891    WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, schemes_);
892    // paths_
893    if (paths_.empty()) {
894        WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL);
895    } else {
896        if (!parcel.WriteInt32(VALUE_OBJECT)) {
897            return false;
898        }
899        WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, paths_.size());
900        for (auto path : paths_) {
901            if (!parcel.WriteParcelable(&path)) {
902                return false;
903            }
904        }
905    }
906    // schemeSpecificParts_
907    if (schemeSpecificParts_.empty()) {
908        WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL);
909    } else {
910        if (!parcel.WriteInt32(VALUE_OBJECT)) {
911            return false;
912        }
913        WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, schemeSpecificParts_.size());
914        for (auto schemeSpecificPart : schemeSpecificParts_) {
915            if (!parcel.WriteParcelable(&schemeSpecificPart)) {
916                return false;
917            }
918        }
919    }
920    // types_
921    if (types_.empty()) {
922        WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL);
923    } else {
924        if (!parcel.WriteInt32(VALUE_OBJECT)) {
925            return false;
926        }
927        WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, types_.size());
928        for (auto type : types_) {
929            if (!parcel.WriteParcelable(&type)) {
930                return false;
931            }
932        }
933    }
934
935    // parameters_
936    if (wantParams_.GetParams().empty()) {
937        WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL);
938    } else {
939        if (!parcel.WriteInt32(VALUE_OBJECT)) {
940            return false;
941        }
942        if (!parcel.WriteParcelable(&wantParams_)) {
943            return false;
944        }
945    }
946    return true;
947}
948
949/**
950 * @brief Unmarshals this Sequenceable object from a Parcel.
951 *
952 * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled.
953 */
954Skills *Skills::Unmarshalling(Parcel &parcel)
955{
956    Skills *skills = new (std::nothrow) Skills();
957    if (skills != nullptr) {
958        if (!skills->ReadFromParcel(parcel)) {
959            delete skills;
960            skills = nullptr;
961        }
962    }
963    return skills;
964}
965
966bool Skills::ReadFromParcel(Parcel &parcel)
967{
968    int32_t empty;
969    int32_t size = 0;
970    PatternsMatcher *pm = nullptr;
971
972    // entities​_
973    READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &entities_);
974    // actions_
975    READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &actions_);
976    // authorities_
977    READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &authorities_);
978    // schemes_
979    READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &schemes_);
980    // paths_
981    empty = VALUE_NULL;
982    if (!parcel.ReadInt32(empty)) {
983        return false;
984    }
985
986    if (empty == VALUE_OBJECT) {
987        READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size);
988        if (size > CYCLE_LIMIT) {
989            return false;
990        }
991        for (int i = 0; i < size; i++) {
992            pm = parcel.ReadParcelable<PatternsMatcher>();
993            if (pm == nullptr) {
994                return false;
995            } else {
996                paths_.emplace_back(*pm);
997                delete pm;
998                pm = nullptr;
999            }
1000        }
1001    }
1002
1003    // schemeSpecificParts_
1004    empty = VALUE_NULL;
1005    if (!parcel.ReadInt32(empty)) {
1006        return false;
1007    }
1008
1009    if (empty == VALUE_OBJECT) {
1010        READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size);
1011        if (size > CYCLE_LIMIT) {
1012            return false;
1013        }
1014        for (int i = 0; i < size; i++) {
1015            pm = parcel.ReadParcelable<PatternsMatcher>();
1016            if (pm == nullptr) {
1017                return false;
1018            } else {
1019                schemeSpecificParts_.emplace_back(*pm);
1020                delete pm;
1021                pm = nullptr;
1022            }
1023        }
1024    }
1025
1026    // types_
1027    empty = VALUE_NULL;
1028    if (!parcel.ReadInt32(empty)) {
1029        return false;
1030    }
1031
1032    if (empty == VALUE_OBJECT) {
1033        READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size);
1034        if (size > CYCLE_LIMIT) {
1035            return false;
1036        }
1037        for (int i = 0; i < size; i++) {
1038            pm = parcel.ReadParcelable<PatternsMatcher>();
1039            if (pm == nullptr) {
1040                return false;
1041            } else {
1042                types_.emplace_back(*pm);
1043                delete pm;
1044                pm = nullptr;
1045            }
1046        }
1047    }
1048
1049    // parameters_
1050    empty = VALUE_NULL;
1051    if (!parcel.ReadInt32(empty)) {
1052        return false;
1053    }
1054
1055    if (empty == VALUE_OBJECT) {
1056        auto params = parcel.ReadParcelable<WantParams>();
1057        if (params != nullptr) {
1058            wantParams_ = *params;
1059            delete params;
1060            params = nullptr;
1061        } else {
1062            return false;
1063        }
1064    }
1065
1066    return true;
1067}
1068}  // namespace AAFwk
1069}  // namespace OHOS