@@ -241,38 +241,132 @@ pub fn append(lhs: ~str, rhs: &str) -> ~str {
241
241
242
242
/// Concatenate a vector of strings
243
243
pub fn concat ( v : & [ ~str ] ) -> ~str {
244
- let mut s: ~str = ~"";
245
- for vec:: each( v) |ss| {
246
- push_str ( & mut s, * ss) ;
244
+ if v. is_empty ( ) { return ~""; }
245
+
246
+ let mut len = 0 ;
247
+ for v. each |ss| {
248
+ len += ss. len ( ) ;
249
+ }
250
+ let mut s = ~"";
251
+
252
+ reserve ( & mut s, len) ;
253
+
254
+ unsafe {
255
+ do as_buf ( s) |buf, _len| {
256
+ let mut buf = :: cast:: transmute_mut_unsafe ( buf) ;
257
+ for v. each |ss| {
258
+ do as_buf( * ss) |ssbuf, sslen| {
259
+ let sslen = sslen - 1 ;
260
+ ptr:: copy_memory ( buf, ssbuf, sslen) ;
261
+ buf = buf. offset ( sslen) ;
262
+ }
263
+ }
264
+ }
265
+ raw:: set_len ( & mut s, len) ;
247
266
}
248
267
s
249
268
}
250
269
251
270
/// Concatenate a vector of strings, placing a given separator between each
252
271
pub fn connect ( v : & [ ~str ] , sep : & str ) -> ~str {
272
+ if v. is_empty ( ) { return ~""; }
273
+
274
+ // concat is faster
275
+ if sep. is_empty ( ) { return concat ( v) ; }
276
+
277
+ // this is wrong without the guarantee that v is non-empty
278
+ let mut len = sep. len ( ) * ( v. len ( ) - 1 ) ;
279
+ for v. each |ss| {
280
+ len += ss. len ( ) ;
281
+ }
253
282
let mut s = ~"", first = true ;
254
- for vec:: each( v) |ss| {
255
- if first { first = false ; } else { push_str ( & mut s, sep) ; }
256
- push_str ( & mut s, * ss) ;
283
+
284
+ reserve ( & mut s, len) ;
285
+
286
+ unsafe {
287
+ do as_buf ( s) |buf, _len| {
288
+ do as_buf ( sep) |sepbuf, seplen| {
289
+ let seplen = seplen - 1 ;
290
+ let mut buf = :: cast:: transmute_mut_unsafe ( buf) ;
291
+ for v. each |ss| {
292
+ do as_buf( * ss) |ssbuf, sslen| {
293
+ let sslen = sslen - 1 ;
294
+ if first {
295
+ first = false ;
296
+ } else {
297
+ ptr:: copy_memory ( buf, sepbuf, seplen) ;
298
+ buf = buf. offset ( seplen) ;
299
+ }
300
+ ptr:: copy_memory ( buf, ssbuf, sslen) ;
301
+ buf = buf. offset ( sslen) ;
302
+ }
303
+ }
304
+ }
305
+ }
306
+ raw:: set_len ( & mut s, len) ;
257
307
}
258
308
s
259
309
}
260
310
261
311
/// Concatenate a vector of strings, placing a given separator between each
262
312
pub fn connect_slices ( v : & [ & str ] , sep : & str ) -> ~str {
313
+ if v. is_empty ( ) { return ~""; }
314
+
315
+ // this is wrong without the guarantee that v is non-empty
316
+ let mut len = sep. len ( ) * ( v. len ( ) - 1 ) ;
317
+ for v. each |ss| {
318
+ len += ss. len ( ) ;
319
+ }
263
320
let mut s = ~"", first = true ;
264
- for vec:: each( v) |ss| {
265
- if first { first = false ; } else { push_str ( & mut s, sep) ; }
266
- push_str ( & mut s, * ss) ;
321
+
322
+ reserve ( & mut s, len) ;
323
+
324
+ unsafe {
325
+ do as_buf ( s) |buf, _len| {
326
+ do as_buf ( sep) |sepbuf, seplen| {
327
+ let seplen = seplen - 1 ;
328
+ let mut buf = :: cast:: transmute_mut_unsafe ( buf) ;
329
+ for vec:: each( v) |ss| {
330
+ do as_buf( * ss) |ssbuf, sslen| {
331
+ let sslen = sslen - 1 ;
332
+ if first {
333
+ first = false ;
334
+ } else if seplen > 0 {
335
+ ptr:: copy_memory ( buf, sepbuf, seplen) ;
336
+ buf = buf. offset ( seplen) ;
337
+ }
338
+ ptr:: copy_memory ( buf, ssbuf, sslen) ;
339
+ buf = buf. offset ( sslen) ;
340
+ }
341
+ }
342
+ }
343
+ }
344
+ raw:: set_len ( & mut s, len) ;
267
345
}
268
346
s
269
347
}
270
348
271
349
/// Given a string, make a new string with repeated copies of it
272
350
pub fn repeat( ss : & str , nn : uint ) -> ~str {
273
- let mut acc = ~"";
274
- for nn. times { acc += ss; }
275
- acc
351
+ do as_buf ( ss) |buf, len| {
352
+ let mut ret = ~"";
353
+ // ignore the NULL terminator
354
+ let len = len - 1 ;
355
+ reserve ( & mut ret, nn * len) ;
356
+
357
+ unsafe {
358
+ do as_buf ( ret) |rbuf, _len| {
359
+ let mut rbuf = :: cast:: transmute_mut_unsafe ( rbuf) ;
360
+
361
+ for nn. times {
362
+ ptr : : copy_memory( rbuf, buf, len) ;
363
+ rbuf = rbuf. offset( len) ;
364
+ }
365
+ }
366
+ raw :: set_len( & mut ret, nn * len) ;
367
+ }
368
+ ret
369
+ }
276
370
}
277
371
278
372
/*
0 commit comments