Page Speed Optimization Libraries
1.5.27.2
|
00001 /* 00002 * Copyright 2010 Google Inc. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http:///www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00018 00019 #ifndef NET_INSTAWEB_HTMLPARSE_PUBLIC_HTML_ELEMENT_H_ 00020 #define NET_INSTAWEB_HTMLPARSE_PUBLIC_HTML_ELEMENT_H_ 00021 00022 #include "net/instaweb/htmlparse/public/html_name.h" 00023 #include "net/instaweb/htmlparse/public/html_node.h" 00024 #include "net/instaweb/util/public/basictypes.h" 00025 #include "net/instaweb/util/public/inline_slist.h" 00026 #include "net/instaweb/util/public/scoped_ptr.h" 00027 #include "net/instaweb/util/public/string.h" 00028 #include "net/instaweb/util/public/string_util.h" 00029 00030 namespace net_instaweb { 00031 00042 class HtmlElement : public HtmlNode { 00043 public: 00050 enum CloseStyle { 00051 AUTO_CLOSE, 00052 IMPLICIT_CLOSE, 00053 EXPLICIT_CLOSE, 00054 BRIEF_CLOSE, 00055 UNCLOSED 00056 }; 00057 00059 enum QuoteStyle { 00060 NO_QUOTE, 00061 SINGLE_QUOTE, 00062 DOUBLE_QUOTE 00063 }; 00064 00065 class Attribute : public InlineSListElement<Attribute> { 00066 public: 00070 00074 00078 const char* name_str() const { return name_.c_str(); } 00079 00083 HtmlName::Keyword keyword() const { return name_.keyword(); } 00084 00085 HtmlName name() const { return name_; } 00086 void set_name(const HtmlName& name) { name_ = name; } 00087 00090 const char* escaped_value() const { return escaped_value_.get(); } 00091 00117 const char* DecodedValueOrNull() const { 00118 if (!decoded_value_computed_) { 00119 ComputeDecodedValue(); 00120 } 00121 return decoded_value_.get(); 00122 } 00123 00124 void set_decoding_error(bool x) { decoding_error_ = x; } 00125 bool decoding_error() const { 00126 if (!decoded_value_computed_) { 00127 ComputeDecodedValue(); 00128 } 00129 return decoding_error_; 00130 } 00131 00134 QuoteStyle quote_style() const { return quote_style_; } 00135 00137 const char* quote_str() const; 00138 00152 00157 void SetValue(const StringPiece& value); 00158 00162 void SetEscapedValue(const StringPiece& value); 00163 00164 void set_quote_style(QuoteStyle new_quote_style) { 00165 quote_style_ = new_quote_style; 00166 } 00167 00168 friend class HtmlElement; 00169 00170 private: 00171 void ComputeDecodedValue() const; 00172 00174 Attribute(const HtmlName& name, const StringPiece& escaped_value, 00175 QuoteStyle quote_style); 00176 00177 static inline void CopyValue(const StringPiece& src, 00178 scoped_array<char>* dst); 00179 00180 HtmlName name_; 00181 QuoteStyle quote_style_ : 8; 00182 mutable bool decoding_error_; 00183 mutable bool decoded_value_computed_; 00184 00193 scoped_array<char> escaped_value_; 00194 00211 mutable scoped_array<char> decoded_value_; 00212 00213 DISALLOW_COPY_AND_ASSIGN(Attribute); 00214 }; 00215 00216 typedef InlineSList<Attribute> AttributeList; 00217 typedef InlineSList<Attribute>::Iterator AttributeIterator; 00218 typedef InlineSList<Attribute>::ConstIterator AttributeConstIterator; 00219 00220 virtual ~HtmlElement(); 00221 00228 virtual bool live() const { return (data_.get() != NULL) && data_->live_; } 00229 00230 virtual void MarkAsDead(const HtmlEventListIterator& end); 00231 00234 void AddAttribute(const Attribute& attr); 00235 00245 void AddAttribute(const HtmlName& name, 00246 const StringPiece& decoded_value, 00247 QuoteStyle quote_style); 00249 void AddEscapedAttribute(const HtmlName& name, 00250 const StringPiece& escaped_value, 00251 QuoteStyle quote_style); 00252 00255 bool DeleteAttribute(HtmlName::Keyword keyword); 00256 00260 const Attribute* FindAttribute(HtmlName::Keyword keyword) const; 00261 Attribute* FindAttribute(HtmlName::Keyword keyword) { 00262 const HtmlElement* const_this = this; 00263 const Attribute* result = const_this->FindAttribute(keyword); 00264 return const_cast<Attribute*>(result); 00265 } 00266 00276 const char* AttributeValue(HtmlName::Keyword name) const { 00277 const Attribute* attribute = FindAttribute(name); 00278 if (attribute != NULL) { 00279 return attribute->DecodedValueOrNull(); 00280 } 00281 return NULL; 00282 } 00283 00292 const char* EscapedAttributeValue(HtmlName::Keyword name) const { 00293 const Attribute* attribute = FindAttribute(name); 00294 if (attribute != NULL) { 00295 return attribute->escaped_value(); 00296 } 00297 return NULL; 00298 } 00299 00303 const char* name_str() const { return data_->name_.c_str(); } 00304 00308 HtmlName::Keyword keyword() const { return data_->name_.keyword(); } 00309 00310 const HtmlName& name() const { return data_->name_; } 00311 00315 void set_name(const HtmlName& new_tag) { data_->name_ = new_tag; } 00316 00317 const AttributeList& attributes() const { return data_->attributes_; } 00318 AttributeList* mutable_attributes() { return &data_->attributes_; } 00319 00320 friend class HtmlParse; 00321 friend class HtmlLexer; 00322 00323 CloseStyle close_style() const { return data_->close_style_; } 00324 void set_close_style(CloseStyle style) { data_->close_style_ = style; } 00325 00328 void ToString(GoogleString* buf) const; 00329 void DebugPrint() const; 00330 00331 int begin_line_number() const { return data_->begin_line_number_; } 00332 int end_line_number() const { return data_->end_line_number_; } 00333 00334 protected: 00335 virtual void SynthesizeEvents(const HtmlEventListIterator& iter, 00336 HtmlEventList* queue); 00337 00338 virtual HtmlEventListIterator begin() const { return data_->begin_; } 00339 virtual HtmlEventListIterator end() const { return data_->end_; } 00340 00341 private: 00344 struct Data { 00345 Data(const HtmlName& name, 00346 const HtmlEventListIterator& begin, 00347 const HtmlEventListIterator& end); 00348 ~Data(); 00349 00361 unsigned begin_line_number_ : 24; 00362 unsigned live_ : 8; 00363 unsigned end_line_number_ : 24; 00364 CloseStyle close_style_ : 8; 00365 00366 HtmlName name_; 00367 AttributeList attributes_; 00368 HtmlEventListIterator begin_; 00369 HtmlEventListIterator end_; 00370 }; 00371 00375 void set_begin(const HtmlEventListIterator& begin) { data_->begin_ = begin; } 00376 void set_end(const HtmlEventListIterator& end) { data_->end_ = end; } 00377 00378 void set_begin_line_number(int line) { data_->begin_line_number_ = line; } 00379 void set_end_line_number(int line) { data_->end_line_number_ = line; } 00380 00382 HtmlElement(HtmlElement* parent, const HtmlName& name, 00383 const HtmlEventListIterator& begin, 00384 const HtmlEventListIterator& end); 00385 00391 void FreeData() { data_.reset(NULL); } 00392 00393 scoped_ptr<Data> data_; 00394 00395 DISALLOW_COPY_AND_ASSIGN(HtmlElement); 00396 }; 00397 00398 } 00399 00400 #endif ///< NET_INSTAWEB_HTMLPARSE_PUBLIC_HTML_ELEMENT_H_