| /* |
| * 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. |
| */ |
| |
| // Author: jmaessen@google.com (Jan Maessen) |
| |
| #include "net/instaweb/htmlparse/public/logging_html_filter.h" |
| #include "net/instaweb/htmlparse/public/statistics_log.h" |
| #include "pagespeed/kernel/html/html_element.h" |
| |
| // TODO(jmarantz): convert to Statistics interface |
| |
| namespace { |
| // Printable names of the statistics. |
| // Must match up with enum Statistic in logging_html_filter.h; |
| // is this bad for maintenance? |
| const char* kStatisticNames[] = { |
| "explicit_close", "implicit_close", "brief_close", "closed", "unclosed", |
| "spurious_close", "tags", "cdata", "comments", "directives", "documents", |
| "IE_directives", |
| }; |
| } |
| |
| namespace net_instaweb { |
| |
| LoggingFilter::LoggingFilter() { |
| Reset(); |
| } |
| |
| void LoggingFilter::StartDocument() { |
| ++stats_[NUM_DOCUMENTS]; |
| } |
| |
| void LoggingFilter::StartElement(HtmlElement* element) { |
| // Does EndElement get called for singleton elements? |
| if (element->style() != HtmlElement::INVISIBLE) { |
| ++stats_[NUM_UNCLOSED]; |
| ++stats_[NUM_TAGS]; |
| } |
| } |
| |
| void LoggingFilter::EndElement(HtmlElement* element) { |
| // Figure out what's up with the element (implicitly vs explicitly closed) |
| switch (element->style()) { |
| case HtmlElement::EXPLICIT_CLOSE: { |
| --stats_[NUM_UNCLOSED]; |
| ++stats_[NUM_CLOSED]; |
| ++stats_[NUM_EXPLICIT_CLOSED]; |
| break; |
| } |
| case HtmlElement::IMPLICIT_CLOSE: { |
| --stats_[NUM_UNCLOSED]; |
| ++stats_[NUM_CLOSED]; |
| ++stats_[NUM_IMPLICIT_CLOSED]; |
| break; |
| } |
| case HtmlElement::BRIEF_CLOSE: { |
| --stats_[NUM_UNCLOSED]; |
| ++stats_[NUM_CLOSED]; |
| ++stats_[NUM_BRIEF_CLOSED]; |
| break; |
| } |
| case HtmlElement::INVISIBLE: |
| case HtmlElement::UNCLOSED: { |
| // We assumed unmatchedness at StartElement, so do nothing. |
| break; |
| } |
| case HtmlElement::AUTO_CLOSE: { |
| // Another form of unmated tag, again do nothing. |
| break; |
| } |
| } |
| } |
| |
| void LoggingFilter::Cdata(HtmlCdataNode* cdata) { |
| ++stats_[NUM_CDATA]; |
| } |
| |
| void LoggingFilter::Comment(HtmlCommentNode* comment) { |
| ++stats_[NUM_COMMENTS]; |
| } |
| |
| void LoggingFilter::IEDirective(HtmlIEDirectiveNode* directive) { |
| ++stats_[NUM_IE_DIRECTIVES]; |
| } |
| |
| void LoggingFilter::Directive(HtmlDirectiveNode* directive) { |
| ++stats_[NUM_DIRECTIVES]; |
| } |
| |
| // Logging, diffing, and aggregation |
| void LoggingFilter::LogStatistics(StatisticsLog *statistics_log) const { |
| for (int statistic = MIN_STAT; statistic < MAX_STAT; ++statistic) { |
| statistics_log->LogStat(kStatisticNames[statistic], stats_[statistic]); |
| } |
| } |
| |
| void LoggingFilter::Reset() { |
| // Cleaner than memset? |
| for (int statistic = MIN_STAT; statistic < MAX_STAT; ++statistic) { |
| stats_[statistic] = 0; |
| } |
| } |
| |
| } // namespace net_instaweb |