Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(308)

Side by Side Diff: pkg/shelf/lib/src/util.dart

Issue 222843003: Convert shelf to use the string_scanner package. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/shelf/lib/src/string_scanner.dart ('k') | pkg/shelf/pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library shelf.util; 5 library shelf.util;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:stack_trace/stack_trace.dart'; 9 import 'package:stack_trace/stack_trace.dart';
10 10 import 'package:string_scanner/string_scanner.dart';
11 import 'string_scanner.dart';
12 11
13 /// Like [Future.sync], but wraps the Future in [Chain.track] as well. 12 /// Like [Future.sync], but wraps the Future in [Chain.track] as well.
14 Future syncFuture(callback()) => Chain.track(new Future.sync(callback)); 13 Future syncFuture(callback()) => Chain.track(new Future.sync(callback));
15 14
16 const _WEEKDAYS = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; 15 const _WEEKDAYS = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
17 const _MONTHS = const ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", 16 const _MONTHS = const ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
18 "Sep", "Oct", "Nov", "Dec"]; 17 "Sep", "Oct", "Nov", "Dec"];
19 18
20 final _shortWeekdayRegExp = new RegExp(r"Mon|Tue|Wed|Thu|Fri|Sat|Sun"); 19 final _shortWeekdayRegExp = new RegExp(r"Mon|Tue|Wed|Thu|Fri|Sat|Sun");
21 final _longWeekdayRegExp = 20 final _longWeekdayRegExp =
(...skipping 27 matching lines...) Expand all
49 return buffer.toString(); 48 return buffer.toString();
50 } 49 }
51 50
52 // TODO(nweiz): Move this into an http_parser package. 51 // TODO(nweiz): Move this into an http_parser package.
53 /// Parses an HTTP-formatted date into a UTC [DateTime]. 52 /// Parses an HTTP-formatted date into a UTC [DateTime].
54 /// 53 ///
55 /// This follows [RFC 54 /// This follows [RFC
56 /// 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3). It will 55 /// 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3). It will
57 /// throw a [FormatException] if [date] is invalid. 56 /// throw a [FormatException] if [date] is invalid.
58 DateTime parseHttpDate(String date) { 57 DateTime parseHttpDate(String date) {
59 var errorMessage = 'Invalid HTTP date "$date".'; 58 try {
60 var scanner = new StringScanner(date); 59 var scanner = new StringScanner(date);
61 60
62 if (scanner.scan(_longWeekdayRegExp)) { 61 if (scanner.scan(_longWeekdayRegExp)) {
63 // RFC 850 starts with a long weekday. 62 // RFC 850 starts with a long weekday.
64 scanner.expect(", ", errorMessage); 63 scanner.expect(", ");
65 var day = _parseInt(scanner, errorMessage, 2); 64 var day = _parseInt(scanner, 2);
66 scanner.expect("-", errorMessage); 65 scanner.expect("-");
67 var month = _parseMonth(scanner, errorMessage); 66 var month = _parseMonth(scanner);
68 scanner.expect("-", errorMessage); 67 scanner.expect("-");
69 var year = 1900 + _parseInt(scanner, errorMessage, 2); 68 var year = 1900 + _parseInt(scanner, 2);
70 scanner.expect(" ", errorMessage); 69 scanner.expect(" ");
71 var time = _parseTime(scanner, errorMessage); 70 var time = _parseTime(scanner);
72 scanner.expect(" GMT", errorMessage); 71 scanner.expect(" GMT");
73 if (!scanner.isDone) throw new FormatException(errorMessage); 72 scanner.expectDone();
74 73
75 return _makeDateTime(year, month, day, time, errorMessage); 74 return _makeDateTime(year, month, day, time);
75 }
76
77 // RFC 1123 and asctime both start with a short weekday.
78 scanner.expect(_shortWeekdayRegExp);
79 if (scanner.scan(", ")) {
80 // RFC 1123 follows the weekday with a comma.
81 var day = _parseInt(scanner, 2);
82 scanner.expect(" ");
83 var month = _parseMonth(scanner);
84 scanner.expect(" ");
85 var year = _parseInt(scanner, 4);
86 scanner.expect(" ");
87 var time = _parseTime(scanner);
88 scanner.expect(" GMT");
89 scanner.expectDone();
90
91 return _makeDateTime(year, month, day, time);
92 }
93
94 // asctime follows the weekday with a space.
95 scanner.expect(" ");
96 var month = _parseMonth(scanner);
97 scanner.expect(" ");
98 var day = scanner.scan(" ") ?
99 _parseInt(scanner, 1) :
100 _parseInt(scanner, 2);
101 scanner.expect(" ");
102 var time = _parseTime(scanner);
103 scanner.expect(" ");
104 var year = _parseInt(scanner, 4);
105 scanner.expectDone();
106
107 return _makeDateTime(year, month, day, time);
108 } on FormatException catch (error) {
109 throw new FormatException('Invalid HTTP date "$date": ${error.message}');
76 } 110 }
77
78 // RFC 1123 and asctime both start with a short weekday.
79 scanner.expect(_shortWeekdayRegExp, errorMessage);
80 if (scanner.scan(", ")) {
81 // RFC 1123 follows the weekday with a comma.
82 var day = _parseInt(scanner, errorMessage, 2);
83 scanner.expect(" ", errorMessage);
84 var month = _parseMonth(scanner, errorMessage);
85 scanner.expect(" ", errorMessage);
86 var year = _parseInt(scanner, errorMessage, 4);
87 scanner.expect(" ", errorMessage);
88 var time = _parseTime(scanner, errorMessage);
89 scanner.expect(" GMT", errorMessage);
90 if (!scanner.isDone) throw new FormatException(errorMessage);
91
92 return _makeDateTime(year, month, day, time, errorMessage);
93 }
94
95 // asctime follows the weekday with a space.
96 scanner.expect(" ", errorMessage);
97 var month = _parseMonth(scanner, errorMessage);
98 scanner.expect(" ", errorMessage);
99 var day = scanner.scan(" ") ?
100 _parseInt(scanner, errorMessage, 1) :
101 _parseInt(scanner, errorMessage, 2);
102 scanner.expect(" ", errorMessage);
103 var time = _parseTime(scanner, errorMessage);
104 scanner.expect(" ", errorMessage);
105 var year = _parseInt(scanner, errorMessage, 4);
106 if (!scanner.isDone) throw new FormatException(errorMessage);
107
108 return _makeDateTime(year, month, day, time, errorMessage);
109 } 111 }
110 112
111 /// Parses a short-form month name to a form accepted by [DateTime]. 113 /// Parses a short-form month name to a form accepted by [DateTime].
112 int _parseMonth(StringScanner scanner, String errorMessage) { 114 int _parseMonth(StringScanner scanner) {
113 scanner.expect(_monthRegExp, errorMessage); 115 scanner.expect(_monthRegExp);
114 // DateTime uses 1-indexed months. 116 // DateTime uses 1-indexed months.
115 return _MONTHS.indexOf(scanner.lastMatch[0]) + 1; 117 return _MONTHS.indexOf(scanner.lastMatch[0]) + 1;
116 } 118 }
117 119
118 /// Parses an int an enforces that it has exactly [digits] digits. 120 /// Parses an int an enforces that it has exactly [digits] digits.
119 int _parseInt(StringScanner scanner, String errorMessage, int digits) { 121 int _parseInt(StringScanner scanner, int digits) {
120 scanner.expect(_digitRegExp, errorMessage); 122 scanner.expect(_digitRegExp);
121 if (scanner.lastMatch[0].length != digits) { 123 if (scanner.lastMatch[0].length != digits) {
122 throw new FormatException(errorMessage); 124 scanner.error("expected a $digits-digit number.");
123 } else { 125 } else {
124 return int.parse(scanner.lastMatch[0]); 126 return int.parse(scanner.lastMatch[0]);
125 } 127 }
126 } 128 }
127 129
128 /// Parses an timestamp of the form "HH:MM:SS" on a 24-hour clock. 130 /// Parses an timestamp of the form "HH:MM:SS" on a 24-hour clock.
129 DateTime _parseTime(StringScanner scanner, String errorMessage) { 131 DateTime _parseTime(StringScanner scanner) {
130 var hours = _parseInt(scanner, errorMessage, 2); 132 var hours = _parseInt(scanner, 2);
131 scanner.expect(':', errorMessage); 133 if (hours >= 24) scanner.error("hours may not be greater than 24.");
134 scanner.expect(':');
132 135
133 var minutes = _parseInt(scanner, errorMessage, 2); 136 var minutes = _parseInt(scanner, 2);
134 scanner.expect(':', errorMessage); 137 if (minutes >= 60) scanner.error("minutes may not be greater than 60.");
138 scanner.expect(':');
135 139
136 var seconds = _parseInt(scanner, errorMessage, 2); 140 var seconds = _parseInt(scanner, 2);
137 141 if (seconds >= 60) scanner.error("seconds may not be greater than 60.");
138 if (hours >= 24 || minutes >= 60 || seconds >= 60) {
139 throw new FormatException(errorMessage);
140 }
141 142
142 return new DateTime(1, 1, 1, hours, minutes, seconds); 143 return new DateTime(1, 1, 1, hours, minutes, seconds);
143 } 144 }
144 145
145 /// Returns a UTC [DateTime] from the given components. 146 /// Returns a UTC [DateTime] from the given components.
146 /// 147 ///
147 /// Validates that [day] is a valid day for [month]. If it's not, throws a 148 /// Validates that [day] is a valid day for [month]. If it's not, throws a
148 /// [FormatException] with [errorMessage]. 149 /// [FormatException].
149 DateTime _makeDateTime(int year, int month, int day, DateTime time, 150 DateTime _makeDateTime(int year, int month, int day, DateTime time) {
150 String errorMessage) {
151 if (day < 1) throw new FormatException(errorMessage);
152 var dateTime = new DateTime.utc( 151 var dateTime = new DateTime.utc(
153 year, month, day, time.hour, time.minute, time.second); 152 year, month, day, time.hour, time.minute, time.second);
154 153
155 // If [day] was too large, it will cause [month] to overflow. 154 // If [day] was too large, it will cause [month] to overflow.
156 if (dateTime.month != month) throw new FormatException(errorMessage); 155 if (dateTime.month != month) {
156 throw new FormatException("invalid day '$day' for month '$month'.");
157 }
157 return dateTime; 158 return dateTime;
158 } 159 }
OLDNEW
« no previous file with comments | « pkg/shelf/lib/src/string_scanner.dart ('k') | pkg/shelf/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698