1 /*
2 * Copyright (c) 2023 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 "collection_option.h"
17 
18 #include <algorithm>
19 #include <cstring>
20 
21 #include "doc_errno.h"
22 #include "rd_json_object.h"
23 #include "rd_log_print.h"
24 
25 namespace DocumentDB {
26 namespace {
27 constexpr const char *OPT_MAX_DOC = "maxdoc";
28 constexpr const char *OPT_COLLECTION_MODE = "mode";
29 constexpr const char *KV_COLLECTION_MODE = "kv";
30 
CFG_IsValid(const JsonObject & config)31 int CFG_IsValid(const JsonObject &config)
32 {
33     JsonObject child = config.GetChild();
34     while (!child.IsNull()) {
35         std::string fieldName = child.GetItemField();
36         if (strcmp(OPT_COLLECTION_MODE, fieldName.c_str()) == 0) {
37             if (strcmp(child.GetItemValue().GetStringValue().c_str(), KV_COLLECTION_MODE) == 0) { // The value of mode
38                 return -E_NOT_SUPPORT;
39             } else {
40                 child = child.GetNext();
41                 continue;
42             }
43         }
44         if (strcmp(OPT_MAX_DOC, fieldName.c_str()) != 0) {
45             GLOGE("Invalid collection config.");
46             return -E_INVALID_CONFIG_VALUE;
47         }
48         child = child.GetNext();
49     }
50     return E_OK;
51 }
52 } // namespace
53 
ReadOption(const std::string & optStr,int & errCode)54 CollectionOption CollectionOption::ReadOption(const std::string &optStr, int &errCode)
55 {
56     if (optStr.empty()) {
57         return {};
58     }
59 
60     std::string lowerCaseOptStr = optStr;
61     std::transform(lowerCaseOptStr.begin(), lowerCaseOptStr.end(), lowerCaseOptStr.begin(), [](unsigned char c) {
62         return std::tolower(c);
63     });
64 
65     JsonObject collOpt = JsonObject::Parse(lowerCaseOptStr, errCode);
66     if (errCode != E_OK) {
67         GLOGE("Read collection option failed from str. %d", errCode);
68         return {};
69     }
70 
71     errCode = CFG_IsValid(collOpt);
72     if (errCode != E_OK) {
73         GLOGE("Check collection option, not support config item. %d", errCode);
74         return {};
75     }
76 
77     static const JsonFieldPath maxDocField = { OPT_MAX_DOC };
78     if (!collOpt.IsFieldExists(maxDocField)) {
79         return {};
80     }
81 
82     ValueObject maxDocValue = collOpt.GetObjectByPath(maxDocField, errCode);
83     if (errCode != E_OK) {
84         GLOGE("Read collection option failed. %d", errCode);
85         return {};
86     }
87 
88     if (maxDocValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) {
89         GLOGE("Check collection option failed, the field type of maxDoc is not NUMBER.");
90         errCode = -E_INVALID_CONFIG_VALUE;
91         return {};
92     }
93 
94     if (maxDocValue.GetIntValue() <= 0 || static_cast<uint64_t>(maxDocValue.GetIntValue()) > UINT32_MAX) {
95         GLOGE("Check collection option failed, invalid maxDoc value.");
96         errCode = -E_INVALID_CONFIG_VALUE;
97         return {};
98     }
99 
100     CollectionOption option;
101     option.maxDoc_ = static_cast<uint32_t>(maxDocValue.GetIntValue());
102     option.option_ = optStr;
103     return option;
104 }
105 } // namespace DocumentDB