Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005 Frerich Raabe <raabe@kde.org> | 2 * Copyright (C) 2005 Frerich Raabe <raabe@kde.org> |
| 3 * Copyright (C) 2006, 2009 Apple Inc. | 3 * Copyright (C) 2006, 2009 Apple Inc. |
| 4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | 4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * | 9 * |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 30 #include "core/XMLNames.h" | 30 #include "core/XMLNames.h" |
| 31 #include "core/dom/Attr.h" | 31 #include "core/dom/Attr.h" |
| 32 #include "core/dom/Element.h" | 32 #include "core/dom/Element.h" |
| 33 #include "core/dom/ProcessingInstruction.h" | 33 #include "core/dom/ProcessingInstruction.h" |
| 34 #include "core/dom/TreeScope.h" | 34 #include "core/dom/TreeScope.h" |
| 35 #include "core/xml/XPathUtil.h" | 35 #include "core/xml/XPathUtil.h" |
| 36 #include "core/xml/XPathValue.h" | 36 #include "core/xml/XPathValue.h" |
| 37 #include "wtf/MathExtras.h" | 37 #include "wtf/MathExtras.h" |
| 38 #include "wtf/text/StringBuilder.h" | 38 #include "wtf/text/StringBuilder.h" |
| 39 | 39 |
| 40 #include <limits> | |
| 41 | |
| 40 namespace blink { | 42 namespace blink { |
| 41 namespace XPath { | 43 namespace XPath { |
| 42 | 44 |
| 43 static inline bool isWhitespace(UChar c) { | 45 static inline bool isWhitespace(UChar c) { |
| 44 return c == ' ' || c == '\n' || c == '\r' || c == '\t'; | 46 return c == ' ' || c == '\n' || c == '\r' || c == '\t'; |
| 45 } | 47 } |
| 46 | 48 |
| 47 #define DEFINE_FUNCTION_CREATOR(Class) \ | 49 #define DEFINE_FUNCTION_CREATOR(Class) \ |
| 48 static Function* create##Class() { return new Class; } | 50 static Function* create##Class() { return new Class; } |
| 49 | 51 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 523 String s1 = arg(0)->evaluate(context).toString(); | 525 String s1 = arg(0)->evaluate(context).toString(); |
| 524 String s2 = arg(1)->evaluate(context).toString(); | 526 String s2 = arg(1)->evaluate(context).toString(); |
| 525 | 527 |
| 526 size_t i = s1.find(s2); | 528 size_t i = s1.find(s2); |
| 527 if (i == kNotFound) | 529 if (i == kNotFound) |
| 528 return ""; | 530 return ""; |
| 529 | 531 |
| 530 return s1.substring(i + s2.length()); | 532 return s1.substring(i + s2.length()); |
| 531 } | 533 } |
| 532 | 534 |
| 535 static unsigned findSubstringStartIndex(unsigned lo, unsigned hi, double pos) { | |
| 536 while (lo != hi) { | |
| 537 unsigned mid = lo + (hi - lo) / 2; | |
| 538 if (mid >= pos) | |
| 539 hi = mid; | |
| 540 else | |
| 541 lo = mid + 1; | |
|
yosin_UTC9
2016/10/17 03:56:00
Note: When |pos| is NaN, |mid >= pos| is false. So
dominicc (has gone to gerrit)
2016/10/21 05:28:45
What's wrong with that?
yosin_UTC9
2016/10/21 05:52:03
Sorry for confusion. This is my notes.
| |
| 542 } | |
| 543 return lo; | |
| 544 } | |
| 545 | |
| 546 // This function may seem redundant given findSubstringStartIndex, but | |
| 547 // it is different. substring's bounds calculations are designed to | |
| 548 // work with NaN, and mid >= pos is different to !(mid < pos) when pos | |
| 549 // is NaN. | |
| 550 static unsigned findSubstringEndIndex(unsigned lo, unsigned hi, double pos) { | |
| 551 while (lo != hi) { | |
| 552 unsigned mid = lo + (hi - lo) / 2; | |
| 553 if (mid < pos) | |
| 554 lo = mid + 1; | |
| 555 else | |
| 556 hi = mid; | |
| 557 } | |
| 558 return lo; | |
| 559 } | |
| 560 | |
| 561 // substring(string, number pos, number? len) | |
| 562 // | |
| 563 // Characters in string are indexed from 1. Numbers are doubles and | |
| 564 // substring is specified to work with IEEE-754 infinity, NaN, and | |
| 565 // XPath's bespoke rounding function, round. | |
| 566 // | |
| 567 // <https://www.w3.org/TR/xpath/#function-substring> | |
| 533 Value FunSubstring::evaluate(EvaluationContext& context) const { | 568 Value FunSubstring::evaluate(EvaluationContext& context) const { |
| 534 String s = arg(0)->evaluate(context).toString(); | 569 String s = arg(0)->evaluate(context).toString(); |
|
yosin_UTC9
2016/10/17 03:56:00
nit: It is better to avoid using one letter variab
| |
| 535 double doublePos = arg(1)->evaluate(context).toNumber(); | 570 double pos = FunRound::round(arg(1)->evaluate(context).toNumber()); |
| 536 if (std::isnan(doublePos)) | 571 double len = argCount() == 3 |
| 572 ? FunRound::round(arg(2)->evaluate(context).toNumber()) | |
| 573 : std::numeric_limits<double>::infinity(); | |
| 574 unsigned start = findSubstringStartIndex(1, s.length() + 1, pos); | |
|
yosin_UTC9
2016/10/17 03:56:00
WDYT? Explicit handling of NaN and Infinity?
In th
dominicc (has gone to gerrit)
2016/10/21 05:28:45
I don't think this works. If pos is -inf and end i
yosin_UTC9
2016/10/21 05:52:03
OK. Simpler code is better.
| |
| 575 unsigned end = findSubstringEndIndex(1, s.length() + 1, pos + len); | |
| 576 if (end <= start) | |
| 537 return ""; | 577 return ""; |
| 538 long pos = static_cast<long>(FunRound::round(doublePos)); | 578 return s.substring(start - 1, end - start); |
| 539 bool haveLength = argCount() == 3; | |
| 540 long len = -1; | |
| 541 if (haveLength) { | |
| 542 double doubleLen = arg(2)->evaluate(context).toNumber(); | |
| 543 if (std::isnan(doubleLen)) | |
| 544 return ""; | |
| 545 len = static_cast<long>(FunRound::round(doubleLen)); | |
| 546 } | |
| 547 | |
| 548 if (pos > long(s.length())) | |
| 549 return ""; | |
| 550 | |
| 551 if (pos < 1) { | |
| 552 if (haveLength) { | |
| 553 len -= 1 - pos; | |
| 554 if (len < 1) | |
| 555 return ""; | |
| 556 } | |
| 557 pos = 1; | |
| 558 } | |
| 559 | |
| 560 return s.substring(pos - 1, len); | |
| 561 } | 579 } |
| 562 | 580 |
| 563 Value FunStringLength::evaluate(EvaluationContext& context) const { | 581 Value FunStringLength::evaluate(EvaluationContext& context) const { |
| 564 if (!argCount()) | 582 if (!argCount()) |
| 565 return Value(context.node.get()).toString().length(); | 583 return Value(context.node.get()).toString().length(); |
| 566 return arg(0)->evaluate(context).toString().length(); | 584 return arg(0)->evaluate(context).toString().length(); |
| 567 } | 585 } |
| 568 | 586 |
| 569 Value FunNormalizeSpace::evaluate(EvaluationContext& context) const { | 587 Value FunNormalizeSpace::evaluate(EvaluationContext& context) const { |
| 570 if (!argCount()) { | 588 if (!argCount()) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 750 return nullptr; | 768 return nullptr; |
| 751 | 769 |
| 752 Function* function = functionRec->factoryFn(); | 770 Function* function = functionRec->factoryFn(); |
| 753 function->setArguments(args); | 771 function->setArguments(args); |
| 754 function->setName(name); | 772 function->setName(name); |
| 755 return function; | 773 return function; |
| 756 } | 774 } |
| 757 | 775 |
| 758 } // namespace XPath | 776 } // namespace XPath |
| 759 } // namespace blink | 777 } // namespace blink |
| OLD | NEW |