Skip to content

Commit 9892b3c

Browse files
committedJul 19, 2018
move Date's s3e internal into native (based on MRI's C impl)
1 parent 5c280fa commit 9892b3c

File tree

4 files changed

+151
-54
lines changed

4 files changed

+151
-54
lines changed
 

‎core/src/main/java/org/jruby/ext/date/RubyDate.java

+134
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,140 @@ public static RubyInteger _comp_year69(ThreadContext context, IRubyObject self,
16551655
return y;
16561656
}
16571657

1658+
@JRubyMethod(name = "s3e", meta = true, required = 4, optional = 1, visibility = Visibility.PRIVATE)
1659+
public static IRubyObject _s3e(ThreadContext context, IRubyObject self, IRubyObject[] args) {
1660+
final IRubyObject nil = context.nil;
1661+
1662+
final RubyHash hash = (RubyHash) args[0];
1663+
RubyString y = args[1] == nil ? null : (RubyString) args[1];
1664+
RubyString m = args[2] == nil ? null : (RubyString) args[2];
1665+
RubyString d = args[3] == nil ? null : (RubyString) args[3];
1666+
boolean bc = args.length > 4 ? args[4].isTrue() : false;
1667+
1668+
Boolean comp = null; RubyString oy, om, od;
1669+
1670+
if (d == null && y != null && m != null) {
1671+
oy = y; om = m; od = d;
1672+
y = od; m = oy; d = om;
1673+
}
1674+
1675+
if (y == null) {
1676+
if (d != null && d.strLength() > 2) {
1677+
y = d; d = null;
1678+
} else if (d != null && strPtr(d, '\'')) {
1679+
y = d; d = null;
1680+
}
1681+
}
1682+
1683+
1684+
if (y != null) {
1685+
int s = skipNonDigitsAndSign(y);
1686+
int bp = s;
1687+
char c = s < y.strLength() ? y.charAt(s) : '\0';
1688+
if (c == '+' || c == '-') s++;
1689+
int ep = skipDigits(y, s);
1690+
if (ep != y.strLength()) {
1691+
oy = y; y = d;
1692+
d = (RubyString) oy.substr19(context.runtime, bp, ep - bp);
1693+
}
1694+
}
1695+
1696+
if (m != null) {
1697+
if (strPtr(m, '\'') || m.strLength() > 2) {
1698+
/* us -> be */
1699+
oy = y; om = m; od = d;
1700+
y = om; m = od; d = oy;
1701+
}
1702+
}
1703+
1704+
if (d != null) {
1705+
if (strPtr(d, '\'') || d.strLength() > 2) {
1706+
oy = y; od = d;
1707+
y = od; d = oy;
1708+
}
1709+
}
1710+
1711+
if (y != null) {
1712+
boolean sign = false;
1713+
1714+
int s = skipNonDigitsAndSign(y);
1715+
1716+
int bp = s;
1717+
char c = s < y.strLength() ? y.charAt(s) : '\0';
1718+
if (c == '+' || c == '-') {
1719+
s++; sign = true;
1720+
}
1721+
if (sign) comp = false;
1722+
int ep = skipDigits(y, s);
1723+
if (ep - s > 2) comp = false;
1724+
1725+
RubyInteger iy = cstr2num(context.runtime, y, bp, ep);
1726+
if (bc) iy = (RubyInteger) iy.negate().op_plus(context, 1);
1727+
set_hash(context, hash, "year", iy);
1728+
}
1729+
1730+
//if (bc) set_hash("_bc", Qtrue);
1731+
1732+
if (m != null) {
1733+
int s = skipNonDigitsAndSign(m);
1734+
1735+
int bp = s;
1736+
int ep = skipDigits(m, s);
1737+
set_hash(context, hash, "mon", cstr2num(context.runtime, m, bp, ep));
1738+
}
1739+
1740+
if (d != null) {
1741+
int s = skipNonDigitsAndSign(d);
1742+
1743+
int bp = s;
1744+
int ep = skipDigits(d, s);
1745+
set_hash(context, hash, "mday", cstr2num(context.runtime, d, bp, ep));
1746+
}
1747+
1748+
if (comp != null) set_hash(context, hash, "_comp", context.runtime.newBoolean(comp));
1749+
1750+
return hash;
1751+
}
1752+
1753+
private static void set_hash(final ThreadContext context, RubyHash hash, String key, IRubyObject val) {
1754+
hash.fastASet(context.runtime.newSymbol(key), val);
1755+
}
1756+
1757+
private static RubyInteger cstr2num(Ruby runtime, RubyString str, int bp, int ep) {
1758+
if (bp == ep) return RubyFixnum.zero(runtime);
1759+
return ConvertBytes.byteListToInum(runtime, str.getByteList(), bp, ep, 10, true);
1760+
}
1761+
1762+
private static boolean strPtr(RubyString str, char c) {
1763+
return str.strLength() > 0 && str.charAt(0) == c;
1764+
}
1765+
1766+
private static boolean isDigit(char c) {
1767+
switch (c) {
1768+
case '0': case '1': case '2': case '3': case '4': return true;
1769+
case '5': case '6': case '7': case '8': case '9': return true;
1770+
default: return false;
1771+
}
1772+
}
1773+
1774+
private static int skipNonDigitsAndSign(RubyString str) {
1775+
int s = 0;
1776+
while (s < str.length()) {
1777+
char c = str.charAt(s);
1778+
if (isDigit(c) || (c == '+' || c == '-')) break;
1779+
s++;
1780+
}
1781+
return s;
1782+
}
1783+
1784+
private static int skipDigits(RubyString str, int off) {
1785+
int i = off;
1786+
for (; i < str.length(); i++) {
1787+
if (!isDigit(str.charAt(i))) return i;
1788+
}
1789+
return i;
1790+
}
1791+
16581792
// Java API
16591793

16601794
/**

‎core/src/main/java/org/jruby/util/ConvertBytes.java

+14
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ public ConvertBytes(Ruby runtime, ByteList str, int base, boolean badcheck) {
3030
this.base = base;
3131
}
3232

33+
ConvertBytes(Ruby runtime, ByteList str, int off, int end, int base, boolean badcheck) {
34+
this.runtime = runtime;
35+
this.str = str;
36+
this.beg = off + str.getBegin();
37+
this.data = str.getUnsafeBytes();
38+
this.end = str.getBegin() + end;
39+
this.badcheck = badcheck;
40+
this.base = base;
41+
}
42+
3343
@Deprecated
3444
public ConvertBytes(Ruby runtime, ByteList str, int base, boolean badcheck, boolean is19) {
3545
this(runtime, str, base, badcheck);
@@ -233,6 +243,10 @@ public static RubyInteger byteListToInum(Ruby runtime, ByteList str, int base, b
233243
return new ConvertBytes(runtime, str, base, badcheck).byteListToInum();
234244
}
235245

246+
public static RubyInteger byteListToInum(Ruby runtime, ByteList str, int off, int end, int base, boolean badcheck) {
247+
return new ConvertBytes(runtime, str, off, end, base, badcheck).byteListToInum();
248+
}
249+
236250
@Deprecated
237251
public static RubyInteger byteListToInum19(Ruby runtime, ByteList str, int base, boolean badcheck) {
238252
return byteListToInum(runtime, str, base, badcheck);

‎lib/ruby/stdlib/date/format.rb

+3-53
Original file line numberDiff line numberDiff line change
@@ -141,56 +141,6 @@ def jisx0301
141141
end
142142
end
143143

144-
def self.s3e(e, y, m, d, bc=false)
145-
y, m, d = d, y, m if y && m && !d
146-
147-
if y == nil
148-
if d && d.size > 2
149-
y = d
150-
d = nil
151-
end
152-
if d && d[0].eql?("'")
153-
y = d
154-
d = nil
155-
end
156-
end
157-
158-
if y
159-
s = y.scan(/(\d+)(.+)?/)
160-
if s[0] && s[0][1] # $2
161-
y, d = d, s[0][0] # $1
162-
end
163-
end
164-
165-
if m
166-
if m[0].eql?("'") || m.size > 2
167-
y, m, d = m, d, y # us -> be
168-
end
169-
end
170-
171-
if d
172-
if d[0].eql?("'") || d.size > 2
173-
y, d = d, y
174-
end
175-
end
176-
177-
if y
178-
if match = y.match(/([-+])?(\d+)/)
179-
c = false if match[1] || match[2].size > 2
180-
end
181-
y = match&.[](0).to_i
182-
e[:year] = bc ? -y + 1 : y
183-
end
184-
185-
e[:mon] = m.match(/\d+/)&.[](0).to_i if m
186-
187-
e[:mday] = d.match(/\d+/)&.[](0).to_i if d
188-
189-
e[:_comp] = c if c != nil
190-
191-
end
192-
private_class_method :s3e
193-
194144
ABBR_MONTHS_KEYS = Format::ABBR_MONTHS.keys.join('|').freeze
195145
private_constant :ABBR_MONTHS_KEYS
196146

@@ -837,9 +787,9 @@ def self._jisx0301(str) # :nodoc:
837787
end
838788
end
839789

840-
def self.set_zone(h, zone) # :nodoc:
841-
h[:zone] = zone
842-
h[:offset] = zone_to_diff(zone)
790+
def self.set_zone(hash, zone) # :nodoc:
791+
hash[:zone] = zone
792+
hash[:offset] = zone_to_diff(zone)
843793
end
844794
private_class_method :set_zone
845795

‎test/mri/excludes/TestDateParse.rb

-1
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
exclude :test__parse_odd_offset, ''

0 commit comments

Comments
 (0)
Please sign in to comment.