| // Copyright 2016 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "starboard/shared/starboard/media/mime_type.h" |
| |
| #include "starboard/character.h" |
| #include "starboard/log.h" |
| #include "starboard/string.h" |
| |
| namespace starboard { |
| namespace shared { |
| namespace starboard { |
| namespace media { |
| |
| namespace { |
| |
| typedef std::vector<std::string> Strings; |
| |
| MimeType::ParamType GetParamTypeByValue(const std::string& value) { |
| int count; |
| int i; |
| if (SbStringScanF(value.c_str(), "%d%n", &i, &count) == 1 && |
| count == value.size()) { |
| return MimeType::kParamTypeInteger; |
| } |
| float f; |
| if (SbStringScanF(value.c_str(), "%g%n", &f, &count) == 1 && |
| count == value.size()) { |
| return MimeType::kParamTypeFloat; |
| } |
| return MimeType::kParamTypeString; |
| } |
| |
| bool ContainsSpace(const std::string& str) { |
| for (size_t i = 0; i < str.size(); ++i) { |
| if (SbCharacterIsSpace(str[i])) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| void Trim(std::string* str) { |
| while (!str->empty() && SbCharacterIsSpace(*str->begin())) { |
| str->erase(str->begin()); |
| } |
| while (!str->empty() && SbCharacterIsSpace(*str->rbegin())) { |
| str->resize(str->size() - 1); |
| } |
| } |
| |
| Strings SplitAndTrim(const std::string& str, char ch) { |
| Strings result; |
| size_t pos = 0; |
| |
| for (;;) { |
| size_t next = str.find(ch, pos); |
| result.push_back(str.substr(pos, next - pos)); |
| Trim(&result.back()); |
| if (next == str.npos) { |
| break; |
| } |
| pos = next + 1; |
| } |
| |
| return result; |
| } |
| |
| } // namespace |
| |
| const int MimeType::kInvalidParamIndex = -1; |
| |
| MimeType::MimeType(const std::string& content_type) : is_valid_(false) { |
| Strings components = SplitAndTrim(content_type, ';'); |
| |
| SB_DCHECK(!components.empty()); |
| |
| // 1. Verify if there is a valid type/subtype in the very beginning. |
| if (ContainsSpace(components.front())) { |
| return; |
| } |
| |
| std::vector<std::string> type_and_container = |
| SplitAndTrim(components.front(), '/'); |
| if (type_and_container.size() != 2 || type_and_container[0].empty() || |
| type_and_container[1].empty()) { |
| return; |
| } |
| type_ = type_and_container[0]; |
| subtype_ = type_and_container[1]; |
| components.erase(components.begin()); |
| |
| // 2. Verify the parameters have valid formats, we want to be strict here. |
| for (Strings::iterator iter = components.begin(); iter != components.end(); |
| ++iter) { |
| std::vector<std::string> name_and_value = SplitAndTrim(*iter, '='); |
| if (name_and_value.size() != 2 || name_and_value[0].empty() || |
| name_and_value[1].empty()) { |
| return; |
| } |
| Param param; |
| if (name_and_value[1].size() > 2 && name_and_value[1][0] == '\"' && |
| *name_and_value[1].rbegin() == '\"') { |
| param.type = kParamTypeString; |
| param.value = name_and_value[1].substr(1, name_and_value[1].size() - 2); |
| } else { |
| param.type = GetParamTypeByValue(name_and_value[1]); |
| param.value = name_and_value[1]; |
| } |
| param.name = name_and_value[0]; |
| params_.push_back(param); |
| } |
| |
| is_valid_ = true; |
| } |
| |
| int MimeType::GetParamCount() const { |
| SB_DCHECK(is_valid()); |
| |
| return static_cast<int>(params_.size()); |
| } |
| |
| MimeType::ParamType MimeType::GetParamType(int index) const { |
| SB_DCHECK(is_valid()); |
| SB_DCHECK(index < GetParamCount()); |
| |
| return params_[index].type; |
| } |
| |
| const std::string& MimeType::GetParamName(int index) const { |
| SB_DCHECK(is_valid()); |
| SB_DCHECK(index < GetParamCount()); |
| |
| return params_[index].name; |
| } |
| |
| int MimeType::GetParamIntValue(int index) const { |
| SB_DCHECK(is_valid()); |
| SB_DCHECK(index < GetParamCount()); |
| SB_DCHECK(GetParamType(index) == kParamTypeInteger); |
| |
| int i; |
| SbStringScanF(params_[index].value.c_str(), "%d", &i); |
| return i; |
| } |
| |
| float MimeType::GetParamFloatValue(int index) const { |
| SB_DCHECK(is_valid()); |
| SB_DCHECK(index < GetParamCount()); |
| SB_DCHECK(GetParamType(index) == kParamTypeInteger || |
| GetParamType(index) == kParamTypeFloat); |
| |
| float f; |
| SbStringScanF(params_[index].value.c_str(), "%g", &f); |
| |
| return f; |
| } |
| |
| const std::string& MimeType::GetParamStringValue(int index) const { |
| SB_DCHECK(is_valid()); |
| SB_DCHECK(index < GetParamCount()); |
| |
| return params_[index].value; |
| } |
| |
| int MimeType::GetParamIntValue(const char* name, int default_value) const { |
| int index = GetParamIndexByName(name); |
| if (index != kInvalidParamIndex) { |
| return GetParamIntValue(index); |
| } |
| return default_value; |
| } |
| |
| float MimeType::GetParamFloatValue(const char* name, |
| float default_value) const { |
| int index = GetParamIndexByName(name); |
| if (index != kInvalidParamIndex) { |
| return GetParamFloatValue(index); |
| } |
| return default_value; |
| } |
| |
| const std::string& MimeType::GetParamStringValue( |
| const char* name, |
| const std::string& default_value) const { |
| int index = GetParamIndexByName(name); |
| if (index != kInvalidParamIndex) { |
| return GetParamStringValue(index); |
| } |
| return default_value; |
| } |
| |
| int MimeType::GetParamIndexByName(const char* name) const { |
| for (size_t i = 0; i < params_.size(); ++i) { |
| if (SbStringCompareNoCase(params_[i].name.c_str(), name) == 0) { |
| return static_cast<int>(i); |
| } |
| } |
| return kInvalidParamIndex; |
| } |
| |
| } // namespace media |
| } // namespace starboard |
| } // namespace shared |
| } // namespace starboard |