blob: d77b2d541d5c959d91ecaffaaf48cda7f12e28be [file] [log] [blame]
// 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