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