@@ -46,24 +46,87 @@ pub trait Reader {
46
46
}
47
47
48
48
// Generic utility functions defined on readers
49
-
50
49
pub trait ReaderUtil {
51
50
fn read_bytes ( len : uint ) -> ~[ u8 ] ;
52
51
fn read_line ( ) -> ~str ;
53
52
54
53
fn read_chars ( n : uint ) -> ~[ char ] ;
55
54
fn read_char ( ) -> char ;
56
55
fn read_c_str ( ) -> ~str ;
57
- fn read_le_uint ( size : uint ) -> uint ;
58
- fn read_le_int ( size : uint ) -> int ;
59
- fn read_be_uint ( size : uint ) -> uint ;
60
56
fn read_whole_stream ( ) -> ~[ u8 ] ;
61
57
fn each_byte ( it : fn ( int ) -> bool ) ;
62
58
fn each_char ( it : fn ( char ) -> bool ) ;
63
59
fn each_line ( it : fn ( ( & str ) ) -> bool ) ;
60
+
61
+ /// read n (between 1 and 8) little-endian unsigned integer bytes
62
+ fn read_le_uint_n ( nbytes : uint ) -> u64 ;
63
+
64
+ /// read n (between 1 and 8) little-endian signed integer bytes
65
+ fn read_le_int_n ( nbytes : uint ) -> i64 ;
66
+
67
+ /// read n (between 1 and 8) big-endian unsigned integer bytes
68
+ fn read_be_uint_n ( nbytes : uint ) -> u64 ;
69
+
70
+ /// read n (between 1 and 8) big-endian signed integer bytes
71
+ fn read_be_int_n ( nbytes : uint ) -> i64 ;
72
+
73
+ /// read a little-endian uint (number of bytes read depends on system)
74
+ fn read_le_uint ( ) -> uint ;
75
+
76
+ /// read a little-endian int (number of bytes read depends on system)
77
+ fn read_le_int ( ) -> int ;
78
+
79
+ /// read a big-endian uint (number of bytes read depends on system)
80
+ fn read_be_uint ( ) -> uint ;
81
+
82
+ /// read a big-endian int (number of bytes read depends on system)
83
+ fn read_be_int ( ) -> int ;
84
+
85
+ /// read a big-endian u64 (8 bytes)
86
+ fn read_be_u64 ( ) -> u64 ;
87
+
88
+ /// read a big-endian u32 (4 bytes)
89
+ fn read_be_u32 ( ) -> u32 ;
90
+
91
+ /// read a big-endian u16 (2 bytes)
92
+ fn read_be_u16 ( ) -> u16 ;
93
+
94
+ /// read a big-endian i64 (8 bytes)
95
+ fn read_be_i64 ( ) -> i64 ;
96
+
97
+ /// read a big-endian i32 (4 bytes)
98
+ fn read_be_i32 ( ) -> i32 ;
99
+
100
+ /// read a big-endian i16 (2 bytes)
101
+ fn read_be_i16 ( ) -> i16 ;
102
+
103
+ /// read a little-endian u64 (8 bytes)
104
+ fn read_le_u64 ( ) -> u64 ;
105
+
106
+ /// read a little-endian u32 (4 bytes)
107
+ fn read_le_u32 ( ) -> u32 ;
108
+
109
+ /// read a little-endian u16 (2 bytes)
110
+ fn read_le_u16 ( ) -> u16 ;
111
+
112
+ /// read a litle-endian i64 (8 bytes)
113
+ fn read_le_i64 ( ) -> i64 ;
114
+
115
+ /// read a litle-endian i32 (4 bytes)
116
+ fn read_le_i32 ( ) -> i32 ;
117
+
118
+ /// read a litle-endian i16 (2 bytes)
119
+ fn read_le_i16 ( ) -> i16 ;
120
+
121
+ /// read a u8 (1 byte)
122
+ fn read_u8 ( ) -> u8 ;
123
+
124
+ /// read a i8 (1 byte)
125
+ fn read_i8 ( ) -> i8 ;
64
126
}
65
127
66
128
impl < T : Reader > T : ReaderUtil {
129
+
67
130
fn read_bytes ( len : uint ) -> ~[ u8 ] {
68
131
let mut bytes = vec:: with_capacity ( len) ;
69
132
unsafe { vec:: raw:: set_len ( & mut bytes, len) ; }
@@ -73,6 +136,7 @@ impl<T: Reader> T : ReaderUtil {
73
136
unsafe { vec:: raw:: set_len ( & mut bytes, count) ; }
74
137
move bytes
75
138
}
139
+
76
140
fn read_line ( ) -> ~str {
77
141
let mut bytes = ~[ ] ;
78
142
loop {
@@ -162,34 +226,6 @@ impl<T: Reader> T : ReaderUtil {
162
226
str:: from_bytes ( bytes)
163
227
}
164
228
165
- // FIXME deal with eof? // #2004
166
- fn read_le_uint ( size : uint ) -> uint {
167
- let mut val = 0 u, pos = 0 u, i = size;
168
- while i > 0 u {
169
- val += ( self . read_byte ( ) as uint ) << pos;
170
- pos += 8 u;
171
- i -= 1 u;
172
- }
173
- val
174
- }
175
- fn read_le_int ( size : uint ) -> int {
176
- let mut val = 0 u, pos = 0 u, i = size;
177
- while i > 0 u {
178
- val += ( self . read_byte ( ) as uint ) << pos;
179
- pos += 8 u;
180
- i -= 1 u;
181
- }
182
- val as int
183
- }
184
- fn read_be_uint ( size : uint ) -> uint {
185
- let mut val = 0 u, i = size;
186
- while i > 0 u {
187
- i -= 1 u;
188
- val += ( self . read_byte ( ) as uint ) << i * 8 u;
189
- }
190
- val
191
- }
192
-
193
229
fn read_whole_stream ( ) -> ~[ u8 ] {
194
230
let mut bytes: ~[ u8 ] = ~[ ] ;
195
231
while !self . eof ( ) { bytes. push_all ( self . read_bytes ( 2048 u) ) ; }
@@ -213,6 +249,116 @@ impl<T: Reader> T : ReaderUtil {
213
249
if !it ( self . read_line ( ) ) { break ; }
214
250
}
215
251
}
252
+
253
+ // FIXME int reading methods need to deal with eof - issue #2004
254
+
255
+ fn read_le_uint_n ( nbytes : uint ) -> u64 {
256
+ assert nbytes > 0 && nbytes <= 8 ;
257
+
258
+ let mut val = 0u64 , pos = 0 , i = nbytes;
259
+ while i > 0 {
260
+ val += ( self . read_u8 ( ) as u64 ) << pos;
261
+ pos += 8 ;
262
+ i -= 1 ;
263
+ }
264
+ val
265
+ }
266
+
267
+ fn read_le_int_n ( nbytes : uint ) -> i64 {
268
+ extend_sign ( self . read_le_uint_n ( nbytes) , nbytes)
269
+ }
270
+
271
+ fn read_be_uint_n ( nbytes : uint ) -> u64 {
272
+ assert nbytes > 0 && nbytes <= 8 ;
273
+
274
+ let mut val = 0u64 , i = nbytes;
275
+ while i > 0 {
276
+ i -= 1 ;
277
+ val += ( self . read_u8 ( ) as u64 ) << i * 8 ;
278
+ }
279
+ val
280
+ }
281
+
282
+ fn read_be_int_n ( nbytes : uint ) -> i64 {
283
+ extend_sign ( self . read_be_uint_n ( nbytes) , nbytes)
284
+ }
285
+
286
+ fn read_le_uint ( ) -> uint {
287
+ self . read_le_uint_n ( uint:: bytes) as uint
288
+ }
289
+
290
+ fn read_le_int ( ) -> int {
291
+ self . read_le_int_n ( int:: bytes) as int
292
+ }
293
+
294
+ fn read_be_uint ( ) -> uint {
295
+ self . read_be_uint_n ( uint:: bytes) as uint
296
+ }
297
+
298
+ fn read_be_int ( ) -> int {
299
+ self . read_be_int_n ( int:: bytes) as int
300
+ }
301
+
302
+ fn read_be_u64 ( ) -> u64 {
303
+ self . read_be_uint_n ( 8 ) as u64
304
+ }
305
+
306
+ fn read_be_u32 ( ) -> u32 {
307
+ self . read_be_uint_n ( 4 ) as u32
308
+ }
309
+
310
+ fn read_be_u16 ( ) -> u16 {
311
+ self . read_be_uint_n ( 2 ) as u16
312
+ }
313
+
314
+ fn read_be_i64 ( ) -> i64 {
315
+ self . read_be_int_n ( 8 ) as i64
316
+ }
317
+
318
+ fn read_be_i32 ( ) -> i32 {
319
+ self . read_be_int_n ( 4 ) as i32
320
+ }
321
+
322
+ fn read_be_i16 ( ) -> i16 {
323
+ self . read_be_int_n ( 2 ) as i16
324
+ }
325
+
326
+ fn read_le_u64 ( ) -> u64 {
327
+ self . read_le_uint_n ( 8 ) as u64
328
+ }
329
+
330
+ fn read_le_u32 ( ) -> u32 {
331
+ self . read_le_uint_n ( 4 ) as u32
332
+ }
333
+
334
+ fn read_le_u16 ( ) -> u16 {
335
+ self . read_le_uint_n ( 2 ) as u16
336
+ }
337
+
338
+ fn read_le_i64 ( ) -> i64 {
339
+ self . read_le_int_n ( 8 ) as i64
340
+ }
341
+
342
+ fn read_le_i32 ( ) -> i32 {
343
+ self . read_le_int_n ( 4 ) as i32
344
+ }
345
+
346
+ fn read_le_i16 ( ) -> i16 {
347
+ self . read_le_int_n ( 2 ) as i16
348
+ }
349
+
350
+ fn read_u8 ( ) -> u8 {
351
+ self . read_byte ( ) as u8
352
+ }
353
+
354
+ fn read_i8 ( ) -> i8 {
355
+ self . read_byte ( ) as i8
356
+ }
357
+ }
358
+
359
+ fn extend_sign ( val : u64 , nbytes : uint ) -> i64 {
360
+ let shift = ( 8 - nbytes) * 8 ;
361
+ ( val << shift) as i64 >> shift
216
362
}
217
363
218
364
// Reader implementations
@@ -589,6 +735,7 @@ pub trait WriterUtil {
589
735
fn write_le_i32 ( n : i32 ) ;
590
736
fn write_le_i16 ( n : i16 ) ;
591
737
fn write_u8 ( n : u8 ) ;
738
+ fn write_i8 ( n : i8 ) ;
592
739
}
593
740
594
741
impl < T : Writer > T : WriterUtil {
@@ -659,7 +806,8 @@ impl<T: Writer> T : WriterUtil {
659
806
u64_to_le_bytes ( n as u64 , 2 u, |v| self . write ( v) )
660
807
}
661
808
662
- fn write_u8 ( n : u8 ) { self . write ( & [ n] ) }
809
+ fn write_u8 ( n : u8 ) { self . write ( [ n] ) }
810
+ fn write_i8 ( n : i8 ) { self . write ( [ n as u8 ] ) }
663
811
}
664
812
665
813
#[ allow( non_implicitly_copyable_typarams) ]
@@ -1001,6 +1149,75 @@ mod tests {
1001
1149
assert wr. bytes . borrow ( |bytes| bytes ==
1002
1150
~[ 0u8 , 9u8 , 4u8 , 5u8 , 8u8 , 7u8 ] ) ;
1003
1151
}
1152
+
1153
+ #[ test]
1154
+ fn test_read_write_le ( ) {
1155
+ let path = Path ( "tmp/lib-io-test-read-write-le.tmp" ) ;
1156
+ let uints = [ 0 , 1 , 2 , 42 , 10_123 , 100_123_456 , u64:: max_value] ;
1157
+
1158
+ // write the ints to the file
1159
+ {
1160
+ let file = io:: file_writer ( & path, [ io:: Create ] ) . get ( ) ;
1161
+ for uints. each |i| {
1162
+ file. write_le_u64 ( * i) ;
1163
+ }
1164
+ }
1165
+
1166
+ // then read them back and check that they are the same
1167
+ {
1168
+ let file = io:: file_reader ( & path) . get ( ) ;
1169
+ for uints. each |i| {
1170
+ assert file. read_le_u64( ) == * i;
1171
+ }
1172
+ }
1173
+ }
1174
+
1175
+ #[ test]
1176
+ fn test_read_write_be ( ) {
1177
+ let path = Path ( "tmp/lib-io-test-read-write-be.tmp" ) ;
1178
+ let uints = [ 0 , 1 , 2 , 42 , 10_123 , 100_123_456 , u64:: max_value] ;
1179
+
1180
+ // write the ints to the file
1181
+ {
1182
+ let file = io:: file_writer ( & path, [ io:: Create ] ) . get ( ) ;
1183
+ for uints. each |i| {
1184
+ file. write_be_u64 ( * i) ;
1185
+ }
1186
+ }
1187
+
1188
+ // then read them back and check that they are the same
1189
+ {
1190
+ let file = io:: file_reader ( & path) . get ( ) ;
1191
+ for uints. each |i| {
1192
+ assert file. read_be_u64( ) == * i;
1193
+ }
1194
+ }
1195
+ }
1196
+
1197
+ #[ test]
1198
+ fn test_read_be_int_n ( ) {
1199
+ let path = Path ( "tmp/lib-io-test-read-be-int-n.tmp" ) ;
1200
+ let ints = [ i32:: min_value, -123456 , -42 , -5 , 0 , 1 , i32:: max_value] ;
1201
+
1202
+ // write the ints to the file
1203
+ {
1204
+ let file = io:: file_writer ( & path, [ io:: Create ] ) . get ( ) ;
1205
+ for ints. each |i| {
1206
+ file. write_be_i32 ( * i) ;
1207
+ }
1208
+ }
1209
+
1210
+ // then read them back and check that they are the same
1211
+ {
1212
+ let file = io:: file_reader ( & path) . get ( ) ;
1213
+ for ints. each |i| {
1214
+ // this tests that the sign extension is working
1215
+ // (comparing the values as i32 would not test this)
1216
+ assert file. read_be_int_n( 4 ) == * i as i64;
1217
+ }
1218
+ }
1219
+ }
1220
+
1004
1221
}
1005
1222
1006
1223
//
0 commit comments