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 #define MLOG_TAG "DisplayNameInfo"
16
17 #include "display_name_info.h"
18
19 #include <vector>
20 #include <regex>
21 #include <iomanip>
22
23 #include "userfile_manager_types.h"
24 #include "media_column.h"
25 #include "media_log.h"
26
27 namespace OHOS::Media {
28
29 // 处理重复displayName场景时,避免扩展的后缀长度超过255,截取超出的部分,保留最终总长为255
GetPrefixStrLength(std::string yearMonthDayStr,std::string hourMinuteSecondStr)30 int32_t DisplayNameInfo::GetPrefixStrLength(std::string yearMonthDayStr, std::string hourMinuteSecondStr)
31 {
32 int32_t extendLength = static_cast<int32_t>(yearMonthDayStr.size() + hourMinuteSecondStr.size()
33 + this->suffix.size());
34 return std::min<int32_t>(this->prefix.size(), static_cast<int32_t>(MAX_DISPLAY_NAME_LENGTH) - extendLength);
35 }
36
DisplayNameInfo(const PhotoAssetInfo & photoAssetInfo)37 DisplayNameInfo::DisplayNameInfo(const PhotoAssetInfo &photoAssetInfo)
38 {
39 ParseDisplayName(photoAssetInfo);
40 }
41
ToString()42 std::string DisplayNameInfo::ToString()
43 {
44 std::string yearMonthDayStr;
45 std::string hourMinuteSecondStr;
46 if (this->yearMonthDay != 0) {
47 std::ostringstream yearMonthDayStream;
48 yearMonthDayStream << std::setw(YEAR_MONTH_DAY_LENGTH) << std::setfill('0') << this->yearMonthDay;
49 std::ostringstream hourMinuteSecondStream;
50 hourMinuteSecondStream << std::setw(HOUR_MINUTE_SECOND_LENGTH) << std::setfill('0') << this->hourMinuteSecond;
51 yearMonthDayStr = "_" + yearMonthDayStream.str();
52 hourMinuteSecondStr = "_" + hourMinuteSecondStream.str();
53 } else {
54 yearMonthDayStr = this->yearMonthDay == 0 ? "" : "_" + std::to_string(this->yearMonthDay);
55 hourMinuteSecondStr = this->hourMinuteSecond == 0 ? "" : "_" + std::to_string(this->hourMinuteSecond);
56 }
57
58 return this->prefix.substr(0, GetPrefixStrLength(yearMonthDayStr, hourMinuteSecondStr))
59 + yearMonthDayStr + hourMinuteSecondStr + this->suffix;
60 }
61
Next()62 std::string DisplayNameInfo::Next()
63 {
64 this->hourMinuteSecond++;
65 return this->ToString();
66 }
67
ParseDisplayName(const PhotoAssetInfo & photoAssetInfo)68 void DisplayNameInfo::ParseDisplayName(const PhotoAssetInfo &photoAssetInfo)
69 {
70 if (photoAssetInfo.subtype == static_cast<int32_t>(PhotoSubType::BURST)) {
71 ParseBurstDisplayName(photoAssetInfo);
72 return;
73 }
74 ParseNormalDisplayName(photoAssetInfo);
75 return;
76 }
77
ParseBurstDisplayName(const PhotoAssetInfo & photoAssetInfo)78 void DisplayNameInfo::ParseBurstDisplayName(const PhotoAssetInfo &photoAssetInfo)
79 {
80 bool isValid = photoAssetInfo.subtype == static_cast<int32_t>(PhotoSubType::BURST);
81 isValid = isValid && photoAssetInfo.displayName.size() > BURST_DISPLAY_NAME_MIN_LENGTH;
82 if (!isValid) {
83 return ParseNormalDisplayName(photoAssetInfo);
84 }
85 std::string displayName = photoAssetInfo.displayName;
86 std::regex pattern(R"(IMG_\d{8}_\d{6}_)", std::regex_constants::icase);
87 std::smatch match;
88 if (!std::regex_search(displayName, match, pattern)) {
89 return ParseNormalDisplayName(photoAssetInfo);
90 }
91 std::vector<std::string> parts;
92 std::istringstream iss(displayName);
93 std::string part;
94 while (std::getline(iss, part, '_')) {
95 parts.push_back(part);
96 }
97 if (parts.size() >= BURST_DISPLAY_NAME_MIN_SUBLINE_COUNT) {
98 this->prefix = parts[0];
99 this->yearMonthDay = this->ToNumber(parts[BURST_DISPLAY_NAME_YEAR_INDEX]);
100 this->hourMinuteSecond = this->ToNumber(parts[BURST_DISPLAY_NAME_HOUR_INDEX]);
101 this->suffix = displayName.substr(BURST_DISPLAY_NAME_MIN_LENGTH - 1);
102 }
103 MEDIA_INFO_LOG("ParseBurstDisplayName Original display name: %{public}s, BurstDisplayNameInfo: %{public}s",
104 displayName.c_str(),
105 this->ToString().c_str());
106 }
107
ToNumber(const std::string & str)108 int32_t DisplayNameInfo::ToNumber(const std::string &str)
109 {
110 char *end;
111 long number = std::strtol(str.c_str(), &end, 10);
112
113 if (*end != '\0') {
114 MEDIA_ERR_LOG("ToNumber failed, has invalid char. str: %{public}s", str.c_str());
115 return 0;
116 } else if (number < INT_MIN || number > INT_MAX) {
117 MEDIA_ERR_LOG("ToNumber failed, number overflow. str: %{public}s", str.c_str());
118 return 0;
119 }
120 return static_cast<int32_t>(number);
121 }
122
ParseNormalDisplayName(const PhotoAssetInfo & photoAssetInfo)123 void DisplayNameInfo::ParseNormalDisplayName(const PhotoAssetInfo &photoAssetInfo)
124 {
125 std::string displayName = photoAssetInfo.displayName;
126 size_t dotPos = displayName.rfind('.');
127 if (dotPos != std::string::npos) {
128 this->prefix = displayName.substr(0, dotPos);
129 this->suffix = displayName.substr(dotPos); // include dot, e.g. ".jpg"
130 }
131 MEDIA_INFO_LOG("ParseNormalDisplayName Original display name: %{public}s, BurstDisplayNameInfo: %{public}s",
132 displayName.c_str(),
133 this->ToString().c_str());
134 }
135 } // namespace OHOS::Media