| /** |
| * Copyright 2010 Google Inc. |
| * |
| * 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. |
| */ |
| |
| // Copyright 2006 Google Inc. All Rights Reserved. |
| // Author: dpeng@google.com (Daniel Peng) |
| |
| #include "util/gtl/stl_util.h" |
| |
| #include "webutil/css/value.h" |
| |
| #include "base/logging.h" |
| #include "strings/memutil.h" |
| #include "webutil/css/fallthrough_intended.h" |
| #include "webutil/html/htmlcolor.h" |
| |
| namespace Css { |
| |
| // |
| // Static constants. |
| // |
| |
| const char* const Value::kDimensionUnitText[] = { |
| "em", "ex", "px", "cm", "mm", "in", "pt", "pc", |
| "deg", "rad", "grad", "ms", "s", "hz", "khz", "%", "OTHER", "" }; |
| |
| // |
| // Constructors. |
| // |
| |
| Value::Value(ValueType ty) |
| : type_(ty), |
| color_(0, 0, 0) { |
| DCHECK(ty == COMMA || ty == DEFAULT || ty == UNKNOWN); |
| } |
| |
| Value::Value(double num, const UnicodeText& unit) |
| : type_(NUMBER), |
| num_(num), |
| color_(0, 0, 0) { |
| unit_ = UnitFromText(unit.utf8_data(), unit.utf8_length()); |
| if (unit_ == OTHER) |
| str_ = unit; |
| } |
| |
| Value::Value(double num, Unit unit) |
| : type_(NUMBER), |
| num_(num), |
| unit_(unit), |
| color_(0, 0, 0) { |
| DCHECK_NE(unit, OTHER); |
| } |
| |
| Value::Value(ValueType ty, const UnicodeText& str) |
| : type_(ty), |
| str_(str), |
| color_(0, 0, 0) { |
| DCHECK(ty == STRING || ty == URI); |
| } |
| |
| Value::Value(const Identifier& identifier) |
| : type_(IDENT), |
| identifier_(identifier), |
| color_(0, 0, 0) { |
| } |
| |
| Value::Value(const Identifier::Ident ident) |
| : type_(IDENT), |
| identifier_(Identifier(ident)), |
| color_(0, 0, 0) { |
| } |
| |
| Value::Value(ValueType ty, FunctionParameters* params) |
| : type_(ty), |
| params_(params), |
| color_(0, 0, 0) { |
| DCHECK(params != NULL); |
| DCHECK(ty == RECT); |
| } |
| |
| Value::Value(const UnicodeText& func, FunctionParameters* params) |
| : type_(FUNCTION), |
| str_(func), |
| params_(params), |
| color_(0, 0, 0) { |
| DCHECK(params != NULL); |
| } |
| |
| Value::Value(HtmlColor c) |
| : type_(COLOR), |
| color_(c) { |
| } |
| |
| Value::Value(const Value& other) |
| : type_(other.type_), |
| num_(other.num_), |
| unit_(other.unit_), |
| identifier_(other.identifier_), |
| str_(other.str_), |
| params_(new FunctionParameters), |
| color_(other.color_), |
| bytes_in_original_buffer_(other.bytes_in_original_buffer_) { |
| if (other.params_.get() != NULL) { |
| params_->Copy(*other.params_); |
| } |
| } |
| |
| Value& Value::operator=(const Value& other) { |
| if (this == &other) return *this; |
| type_ = other.type_; |
| num_ = other.num_; |
| unit_ = other.unit_; |
| identifier_ = other.identifier_; |
| str_ = other.str_; |
| color_ = other.color_; |
| bytes_in_original_buffer_ = other.bytes_in_original_buffer_; |
| if (other.params_.get() != NULL) { |
| params_->Copy(*other.params_); |
| } else { |
| params_.reset(); |
| } |
| return *this; |
| } |
| |
| bool Value::Equals(const Value& other) const { |
| if (type_ != other.type_) return false; |
| switch (type_) { |
| case DEFAULT: |
| case UNKNOWN: |
| return true; |
| case NUMBER: |
| return unit_ == other.unit_ && num_ == other.num_; |
| case URI: |
| case STRING: |
| return str_ == other.str_; |
| case IDENT: |
| if (identifier_.ident() != other.identifier_.ident()) |
| return false; |
| if (identifier_.ident() == Identifier::OTHER) |
| return identifier_.ident_text() == other.identifier_.ident_text(); |
| return true; |
| case COLOR: |
| return color_.Equals(other.color_); |
| case FUNCTION: |
| if (str_ != other.str_) |
| return false; |
| FALLTHROUGH_INTENDED; |
| case RECT: |
| if (params_.get() == NULL) |
| return other.params_.get() == NULL; |
| return params_->Equals(*other.params_); |
| default: |
| LOG(FATAL) << "Unknown type:" << type_; |
| } |
| } |
| |
| // |
| // Static functions mapping between units and strings |
| // |
| |
| Value::Unit Value::UnitFromText(const char* str, int len) { |
| switch (len) { |
| case 0: |
| return NO_UNIT; |
| case 1: |
| switch (str[0]) { |
| case '%': return PERCENT; |
| case 's': case 'S': return S; |
| default: return OTHER; |
| } |
| case 2: |
| switch (str[0]) { |
| case 'e': case 'E': |
| switch (str[1]) { |
| case 'm': case 'M': return EM; |
| case 'x': case 'X': return EX; |
| default: return OTHER; |
| } |
| case 'p': case 'P': |
| switch (str[1]) { |
| case 'x': case 'X': return PX; |
| case 't': case 'T': return PT; |
| case 'c': case 'C': return PC; |
| default: return OTHER; |
| } |
| case 'c': case 'C': |
| switch (str[1]) { |
| case 'm': case 'M': return CM; |
| default: return OTHER; |
| } |
| case 'm': case 'M': |
| switch (str[1]) { |
| case 'm': case 'M': return MM; |
| case 's': case 'S': return MS; |
| default: return OTHER; |
| } |
| case 'i': case 'I': |
| switch (str[1]) { |
| case 'n': case 'N': return IN; |
| default: return OTHER; |
| } |
| case 'h': case 'H': |
| switch (str[1]) { |
| case 'z': case 'Z': return HZ; |
| default: return OTHER; |
| } |
| default: |
| return OTHER; |
| } |
| case 3: |
| if (memcasecmp(str, "deg", 3) == 0) return DEG; |
| if (memcasecmp(str, "rad", 3) == 0) return RAD; |
| if (memcasecmp(str, "khz", 3) == 0) return KHZ; |
| return OTHER; |
| case 4: |
| if (memcasecmp(str, "grad", 3) == 0) return GRAD; |
| return OTHER; |
| default: |
| return OTHER; |
| } |
| } |
| |
| const char* Value::TextFromUnit(Unit u) { |
| DCHECK_LT(u, NUM_UNITS); |
| COMPILE_ASSERT(arraysize(kDimensionUnitText) == NUM_UNITS, dimensionunitsize); |
| |
| return kDimensionUnitText[u]; |
| } |
| |
| // |
| // Accessors. |
| // |
| |
| Value::ValueType Value::GetLexicalUnitType() const { |
| return type_; |
| } |
| |
| string Value::GetDimensionUnitText() const { |
| DCHECK_EQ(type_, NUMBER); |
| if (unit_ == OTHER) |
| return string(str_.utf8_data(), str_.utf8_length()); |
| else |
| return TextFromUnit(unit_); |
| } |
| |
| Value::Unit Value::GetDimension() const { |
| DCHECK_EQ(type_, NUMBER); |
| return unit_; |
| } |
| |
| int Value::GetIntegerValue() const { |
| DCHECK_EQ(type_, NUMBER); |
| return static_cast<int>(num_); |
| } |
| |
| double Value::GetFloatValue() const { |
| DCHECK_EQ(type_, NUMBER); |
| return num_; |
| } |
| |
| const Values* Value::GetParameters() const { |
| DCHECK(type_ == FUNCTION || type_ == RECT); |
| return params_->values(); |
| } |
| |
| const FunctionParameters* Value::GetParametersWithSeparators() const { |
| DCHECK(type_ == FUNCTION || type_ == RECT); |
| return params_.get(); |
| } |
| |
| const UnicodeText& Value::GetFunctionName() const { |
| DCHECK_EQ(type_, FUNCTION); |
| return str_; |
| } |
| |
| const UnicodeText& Value::GetStringValue() const { |
| DCHECK(type_ == URI || type_ == STRING); |
| return str_; |
| } |
| |
| UnicodeText Value::GetIdentifierText() const { |
| DCHECK_EQ(type_, IDENT); |
| return identifier_.ident_text(); |
| } |
| |
| const Identifier& Value::GetIdentifier() const { |
| DCHECK_EQ(type_, IDENT); |
| return identifier_; |
| } |
| |
| const HtmlColor& Value::GetColorValue() const { |
| DCHECK_EQ(type_, COLOR); |
| return color_; |
| } |
| |
| Values::~Values() { STLDeleteElements(this); } |
| |
| FunctionParameters::~FunctionParameters() {} |
| |
| void FunctionParameters::AddSepValue(Separator separator, Value* value) { |
| separators_.push_back(separator); |
| values_->push_back(value); |
| DCHECK_EQ(separators_.size(), values_->size()); |
| } |
| |
| bool FunctionParameters::Equals(const FunctionParameters& other) const { |
| if (size() != other.size()) { |
| return false; |
| } |
| for (int i = 0, n = size(); i < n; ++i) { |
| if (!value(i)->Equals(*other.value(i)) || |
| separator(i) != other.separator(i)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| void FunctionParameters::Copy(const FunctionParameters& other) { |
| if (this != &other) { |
| int size = other.size(); |
| values_->clear(); |
| values_->reserve(size); |
| separators_.clear(); |
| separators_.reserve(size); |
| for (int i = 0; i < size; ++i) { |
| values_->push_back(new Value(*other.values_->at(i))); |
| separators_.push_back(other.separators_[i]); |
| } |
| } |
| DCHECK(this->Equals(other)); |
| } |
| |
| } // namespace |