1
Fork 0

More slice use in vec, io, str, ebml, metadata encoder and decoder.

This commit is contained in:
Graydon Hoare 2012-04-25 17:18:06 -07:00
parent 90c1b4645f
commit 753b683939
7 changed files with 220 additions and 118 deletions

View file

@ -297,23 +297,22 @@ enum fileflag { append, create, truncate, no_flag, }
// FIXME: eventually u64
// #2004
iface writer {
fn write([const u8]);
fn write([const u8]/&);
fn seek(int, seek_style);
fn tell() -> uint;
fn flush() -> int;
}
impl <T: writer, C> of writer for {base: T, cleanup: C} {
fn write(bs: [const u8]) { self.base.write(bs); }
fn write(bs: [const u8]/&) { self.base.write(bs); }
fn seek(off: int, style: seek_style) { self.base.seek(off, style); }
fn tell() -> uint { self.base.tell() }
fn flush() -> int { self.base.flush() }
}
impl of writer for *libc::FILE {
fn write(v: [const u8]) unsafe {
let len = vec::len(v);
vec::as_buf(v) {|vbuf|
fn write(v: [const u8]/&) unsafe {
vec::unpack_slice(v) {|vbuf, len|
let nout = libc::fwrite(vbuf as *c_void, len, 1u, self);
if nout < 1 as size_t {
#error("error writing buffer");
@ -339,10 +338,9 @@ fn FILE_writer(f: *libc::FILE, cleanup: bool) -> writer {
}
impl of writer for fd_t {
fn write(v: [const u8]) unsafe {
let len = vec::len(v);
fn write(v: [const u8]/&) unsafe {
let mut count = 0u;
vec::as_buf(v) {|vbuf|
vec::unpack_slice(v) {|vbuf, len|
while count < len {
let vb = ptr::offset(vbuf, count) as *c_void;
let nout = libc::write(self, vb, len);
@ -408,18 +406,56 @@ fn mk_file_writer(path: str, flags: [fileflag])
}
}
fn u64_to_le_bytes(n: u64, size: uint) -> [u8] {
fn u64_to_le_bytes<T>(n: u64, size: uint, f: fn([u8]/&) -> T) -> T {
assert size <= 8u;
alt size {
1u { f([n as u8]/&) }
2u { f([n as u8,
(n >> 8) as u8]/&) }
4u { f([n as u8,
(n >> 8) as u8,
(n >> 16) as u8,
(n >> 24) as u8]/&) }
8u { f([n as u8,
(n >> 8) as u8,
(n >> 16) as u8,
(n >> 24) as u8,
(n >> 32) as u8,
(n >> 40) as u8,
(n >> 48) as u8,
(n >> 56) as u8]/&) }
_ {
let mut bytes: [u8] = [], i = size, n = n;
while i > 0u {
bytes += [(n & 255_u64) as u8];
n >>= 8_u64;
i -= 1u;
}
ret bytes;
f(bytes)
}
}
}
fn u64_to_be_bytes(n: u64, size: uint) -> [u8] {
fn u64_to_be_bytes<T>(n: u64, size: uint, f: fn([u8]/&) -> T) -> T {
assert size <= 8u;
alt size {
1u { f([n as u8]/&) }
2u { f([(n >> 8) as u8,
n as u8]/&) }
4u { f([(n >> 24) as u8,
(n >> 16) as u8,
(n >> 8) as u8,
n as u8]/&) }
8u { f([(n >> 56) as u8,
(n >> 48) as u8,
(n >> 40) as u8,
(n >> 32) as u8,
(n >> 24) as u8,
(n >> 16) as u8,
(n >> 8) as u8,
n as u8]/&) }
_ {
let mut bytes: [u8] = [];
let mut i = size;
while i > 0u {
@ -427,7 +463,9 @@ fn u64_to_be_bytes(n: u64, size: uint) -> [u8] {
bytes += [(n >> shift) as u8];
i -= 1u;
}
ret bytes;
f(bytes)
}
}
}
fn u64_from_be_bytes(data: [u8], start: uint, size: uint) -> u64 {
@ -448,45 +486,67 @@ impl writer_util for writer {
if ch as uint < 128u {
self.write([ch as u8]);
} else {
self.write(str::bytes(str::from_char(ch)));
self.write_str(str::from_char(ch));
}
}
fn write_str(s: str) { self.write(str::bytes(s)); }
fn write_line(s: str) { self.write(str::bytes(s + "\n")); }
fn write_int(n: int) { self.write(str::bytes(int::to_str(n, 10u))); }
fn write_uint(n: uint) { self.write(str::bytes(uint::to_str(n, 10u))); }
fn write_str(s: str/&) { str::byte_slice(s) {|v| self.write(v); } }
fn write_line(s: str/&) {
self.write_str(s);
self.write_str("\n"/&);
}
fn write_int(n: int) { self.write_str(int::to_str(n, 10u)); }
fn write_uint(n: uint) { self.write_str(uint::to_str(n, 10u)); }
fn write_le_uint(n: uint, size: uint) {
self.write(u64_to_le_bytes(n as u64, size));
u64_to_le_bytes(n as u64, size) {|v| self.write(v); }
}
fn write_le_int(n: int, size: uint) {
self.write(u64_to_le_bytes(n as u64, size));
u64_to_le_bytes(n as u64, size) {|v| self.write(v); }
}
fn write_be_uint(n: uint, size: uint) {
self.write(u64_to_be_bytes(n as u64, size));
u64_to_be_bytes(n as u64, size) {|v| self.write(v); }
}
fn write_be_int(n: int, size: uint) {
self.write(u64_to_be_bytes(n as u64, size));
u64_to_be_bytes(n as u64, size) {|v| self.write(v); }
}
fn write_be_u64(n: u64) {
u64_to_be_bytes(n, 8u) {|v| self.write(v); }
}
fn write_be_u32(n: u32) {
u64_to_be_bytes(n as u64, 4u) {|v| self.write(v); }
}
fn write_be_u16(n: u16) {
u64_to_be_bytes(n as u64, 2u) {|v| self.write(v); }
}
fn write_be_i64(n: i64) {
u64_to_be_bytes(n as u64, 8u) {|v| self.write(v); }
}
fn write_be_i32(n: i32) {
u64_to_be_bytes(n as u64, 4u) {|v| self.write(v); }
}
fn write_be_i16(n: i16) {
u64_to_be_bytes(n as u64, 2u) {|v| self.write(v); }
}
fn write_le_u64(n: u64) {
u64_to_le_bytes(n, 8u) {|v| self.write(v); }
}
fn write_le_u32(n: u32) {
u64_to_le_bytes(n as u64, 4u) {|v| self.write(v); }
}
fn write_le_u16(n: u16) {
u64_to_le_bytes(n as u64, 2u) {|v| self.write(v); }
}
fn write_le_i64(n: i64) {
u64_to_le_bytes(n as u64, 8u) {|v| self.write(v); }
}
fn write_le_i32(n: i32) {
u64_to_le_bytes(n as u64, 4u) {|v| self.write(v); }
}
fn write_le_i16(n: i16) {
u64_to_le_bytes(n as u64, 2u) {|v| self.write(v); }
}
fn write_be_u64(n: u64) { self.write(u64_to_be_bytes(n, 8u)); }
fn write_be_u32(n: u32) { self.write(u64_to_be_bytes(n as u64, 4u)); }
fn write_be_u16(n: u16) { self.write(u64_to_be_bytes(n as u64, 2u)); }
fn write_be_i64(n: i64) { self.write(u64_to_be_bytes(n as u64, 8u)); }
fn write_be_i32(n: i32) { self.write(u64_to_be_bytes(n as u64, 4u)); }
fn write_be_i16(n: i16) { self.write(u64_to_be_bytes(n as u64, 2u)); }
fn write_le_u64(n: u64) { self.write(u64_to_le_bytes(n, 8u)); }
fn write_le_u32(n: u32) { self.write(u64_to_le_bytes(n as u64, 4u)); }
fn write_le_u16(n: u16) { self.write(u64_to_le_bytes(n as u64, 2u)); }
fn write_le_i64(n: i64) { self.write(u64_to_le_bytes(n as u64, 8u)); }
fn write_le_i32(n: i32) { self.write(u64_to_le_bytes(n as u64, 4u)); }
fn write_le_i16(n: i16) { self.write(u64_to_le_bytes(n as u64, 2u)); }
fn write_u8(n: u8) { self.write([n]) }
fn write_u8(n: u8) { self.write([n]/&) }
}
fn file_writer(path: str, flags: [fileflag]) -> result<writer, str> {
@ -518,7 +578,7 @@ type mem_buffer = @{mut buf: [mut u8],
mut pos: uint};
impl of writer for mem_buffer {
fn write(v: [const u8]) {
fn write(v: [const u8]/&) {
// Fast path.
if self.pos == vec::len(self.buf) {
for vec::each(v) {|b| self.buf += [mut b]; }

View file

@ -33,6 +33,7 @@ export
// Transforming strings
bytes,
byte_slice,
chars,
substr,
slice,
@ -323,6 +324,16 @@ fn bytes(s: str) -> [u8] unsafe {
ret v;
}
#[doc = "
Work with the string as a byte slice, not including trailing null.
"]
#[inline(always)]
fn byte_slice<T>(s: str/&, f: fn([u8]/&) -> T) -> T unsafe {
unpack_slice(s) {|p,n|
vec::unsafe::form_slice(p, n-1u, f)
}
}
#[doc = "Convert a string to a vector of characters"]
fn chars(s: str) -> [char] {
let mut buf = [], i = 0u;
@ -1549,6 +1560,7 @@ length of the string. This is to permit probing the byte past the
indexable area for a null byte, as is the case in slices pointing
to full strings, or suffixes of them.
"]
#[inline(always)]
fn unpack_slice<T>(s: str/&, f: fn(*u8, uint) -> T) -> T unsafe {
let v : *(*u8,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;

View file

@ -150,9 +150,8 @@ fn capacity<T>(&&v: [const T]) -> uint unsafe {
#[doc = "Returns the length of a vector"]
#[inline(always)]
pure fn len<T>(&&v: [const T]) -> uint unsafe {
let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
(**repr).fill / sys::size_of::<T>()
pure fn len<T>(&&v: [const T]/&) -> uint unsafe {
unpack_slice(v) {|_p, len| len}
}
#[doc = "
@ -823,28 +822,32 @@ fn iter_between<T>(v: [const T], start: uint, end: uint, f: fn(T)) {
Iterates over a vector, with option to break
"]
#[inline(always)]
fn each<T>(v: [const T], f: fn(T) -> bool) unsafe {
let mut n = len(v);
let mut p = ptr::offset(unsafe::to_ptr(v), 0u);
fn each<T>(v: [const T]/&, f: fn(T) -> bool) unsafe {
vec::unpack_slice(v) {|p, n|
let mut n = n;
let mut p = p;
while n > 0u {
if !f(*p) { break; }
p = ptr::offset(p, 1u);
n -= 1u;
}
}
}
#[doc = "
Iterates over a vector's elements and indices
"]
#[inline(always)]
fn eachi<T>(v: [const T], f: fn(uint, T) -> bool) unsafe {
let mut i = 0u, l = len(v);
let mut p = ptr::offset(unsafe::to_ptr(v), 0u);
while i < l {
fn eachi<T>(v: [const T]/&, f: fn(uint, T) -> bool) unsafe {
vec::unpack_slice(v) {|p, n|
let mut i = 0u;
let mut p = p;
while i < n {
if !f(i, *p) { break; }
p = ptr::offset(p, 1u);
i += 1u;
}
}
}
#[doc = "
@ -958,6 +961,7 @@ fn as_mut_buf<E,T>(v: [mut E], f: fn(*mut E) -> T) -> T unsafe {
#[doc = "
Work with the buffer and length of a slice.
"]
#[inline(always)]
fn unpack_slice<T,U>(s: [const T]/&, f: fn(*T, uint) -> U) -> U unsafe {
let v : *(*T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
@ -1191,6 +1195,17 @@ mod unsafe {
let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
ret ::unsafe::reinterpret_cast(addr_of((**repr).data));
}
#[doc = "
Form a slice from a pointer and length (as a number of units, not bytes).
"]
#[inline(always)]
unsafe fn form_slice<T,U>(p: *T, len: uint, f: fn([T]/&) -> U) -> U {
let pair = (p, len * sys::size_of::<T>());
let v : *([T]/&) = ::unsafe::reinterpret_cast(ptr::addr_of(pair));
f(*v)
}
}
#[doc = "Operations on `[u8]`"]

View file

@ -39,7 +39,7 @@ type doc = {data: @[u8], start: uint, end: uint};
type tagged_doc = {tag: uint, doc: doc};
fn vuint_at(data: [u8], start: uint) -> {val: uint, next: uint} {
fn vuint_at(data: [u8]/&, start: uint) -> {val: uint, next: uint} {
let a = data[start];
if a & 0x80u8 != 0u8 {
ret {val: (a & 0x7fu8) as uint, next: start + 1u};
@ -152,20 +152,23 @@ fn doc_as_i64(d: doc) -> i64 { doc_as_u64(d) as i64 }
type writer = {writer: io::writer, mut size_positions: [uint]};
fn write_sized_vuint(w: io::writer, n: uint, size: uint) {
let buf: [u8] = alt size {
1u { [0x80u8 | (n as u8)] }
2u { [0x40u8 | ((n >> 8_u) as u8), n as u8] }
alt size {
1u {
w.write([0x80u8 | (n as u8)]/&);
}
2u {
w.write([0x40u8 | ((n >> 8_u) as u8), n as u8]/&);
}
3u {
[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
n as u8]
w.write([0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
n as u8]/&);
}
4u {
[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
(n >> 8_u) as u8, n as u8]
w.write([0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
(n >> 8_u) as u8, n as u8]/&);
}
_ { fail #fmt("vint to write too big: %?", n); }
};
w.write(buf);
}
fn write_vuint(w: io::writer, n: uint) {
@ -191,7 +194,7 @@ impl writer for writer {
// Write a placeholder four-byte size.
self.size_positions += [self.writer.tell()];
let zeroes: [u8] = [0u8, 0u8, 0u8, 0u8];
let zeroes: [u8]/& = [0u8, 0u8, 0u8, 0u8]/&;
self.writer.write(zeroes);
}
@ -212,42 +215,54 @@ impl writer for writer {
self.end_tag();
}
fn wr_tagged_bytes(tag_id: uint, b: [u8]) {
fn wr_tagged_bytes(tag_id: uint, b: [u8]/&) {
write_vuint(self.writer, tag_id);
write_vuint(self.writer, vec::len(b));
self.writer.write(b);
}
fn wr_tagged_u64(tag_id: uint, v: u64) {
self.wr_tagged_bytes(tag_id, io::u64_to_be_bytes(v, 8u));
io::u64_to_be_bytes(v, 8u) {|v|
self.wr_tagged_bytes(tag_id, v);
}
}
fn wr_tagged_u32(tag_id: uint, v: u32) {
self.wr_tagged_bytes(tag_id, io::u64_to_be_bytes(v as u64, 4u));
io::u64_to_be_bytes(v as u64, 4u) {|v|
self.wr_tagged_bytes(tag_id, v);
}
}
fn wr_tagged_u16(tag_id: uint, v: u16) {
self.wr_tagged_bytes(tag_id, io::u64_to_be_bytes(v as u64, 2u));
io::u64_to_be_bytes(v as u64, 2u) {|v|
self.wr_tagged_bytes(tag_id, v);
}
}
fn wr_tagged_u8(tag_id: uint, v: u8) {
self.wr_tagged_bytes(tag_id, [v]);
self.wr_tagged_bytes(tag_id, [v]/&);
}
fn wr_tagged_i64(tag_id: uint, v: i64) {
self.wr_tagged_bytes(tag_id, io::u64_to_be_bytes(v as u64, 8u));
io::u64_to_be_bytes(v as u64, 8u) {|v|
self.wr_tagged_bytes(tag_id, v);
}
}
fn wr_tagged_i32(tag_id: uint, v: i32) {
self.wr_tagged_bytes(tag_id, io::u64_to_be_bytes(v as u64, 4u));
io::u64_to_be_bytes(v as u64, 4u) {|v|
self.wr_tagged_bytes(tag_id, v);
}
}
fn wr_tagged_i16(tag_id: uint, v: i16) {
self.wr_tagged_bytes(tag_id, io::u64_to_be_bytes(v as u64, 2u));
io::u64_to_be_bytes(v as u64, 2u) {|v|
self.wr_tagged_bytes(tag_id, v);
}
}
fn wr_tagged_i8(tag_id: uint, v: i8) {
self.wr_tagged_bytes(tag_id, [v as u8]);
self.wr_tagged_bytes(tag_id, [v as u8]/&);
}
fn wr_tagged_str(tag_id: uint, v: str) {
@ -260,7 +275,7 @@ impl writer for writer {
self.wr_tagged_bytes(tag_id, str::bytes(v));
}
fn wr_bytes(b: [u8]) {
fn wr_bytes(b: [u8]/&) {
#debug["Write %u bytes", vec::len(b)];
self.writer.write(b);
}

View file

@ -62,7 +62,7 @@ fn encode_named_def_id(ebml_w: ebml::writer, name: str, id: def_id) {
fn encode_mutability(ebml_w: ebml::writer, mt: class_mutability) {
ebml_w.wr_tag(tag_class_mut) {||
ebml_w.writer.write([alt mt { class_immutable { 'i' }
class_mutable { 'm' } } as u8]);
class_mutable { 'm' } } as u8]/&);
}
}
@ -230,7 +230,7 @@ fn encode_reexport_paths(ebml_w: ebml::writer,
// Item info table encoding
fn encode_family(ebml_w: ebml::writer, c: char) {
ebml_w.start_tag(tag_items_data_item_family);
ebml_w.writer.write([c as u8]);
ebml_w.writer.write([c as u8]/&);
ebml_w.end_tag();
}
@ -1016,7 +1016,7 @@ fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> [u8] {
// Pad this, since something (LLVM, presumably) is cutting off the
// remaining % 4 bytes.
buf_w.write([0u8, 0u8, 0u8, 0u8]);
buf_w.write([0u8, 0u8, 0u8, 0u8]/&);
io::mem_buffer_buf(buf)
}

View file

@ -190,45 +190,45 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
alt t {
ty_i { w.write_char('i'); }
ty_char { w.write_char('c'); }
ty_i8 { w.write_str("MB"); }
ty_i16 { w.write_str("MW"); }
ty_i32 { w.write_str("ML"); }
ty_i64 { w.write_str("MD"); }
ty_i8 { w.write_str("MB"/&); }
ty_i16 { w.write_str("MW"/&); }
ty_i32 { w.write_str("ML"/&); }
ty_i64 { w.write_str("MD"/&); }
}
}
ty::ty_uint(t) {
alt t {
ty_u { w.write_char('u'); }
ty_u8 { w.write_str("Mb"); }
ty_u16 { w.write_str("Mw"); }
ty_u32 { w.write_str("Ml"); }
ty_u64 { w.write_str("Md"); }
ty_u8 { w.write_str("Mb"/&); }
ty_u16 { w.write_str("Mw"/&); }
ty_u32 { w.write_str("Ml"/&); }
ty_u64 { w.write_str("Md"/&); }
}
}
ty::ty_float(t) {
alt t {
ty_f { w.write_char('l'); }
ty_f32 { w.write_str("Mf"); }
ty_f64 { w.write_str("MF"); }
ty_f32 { w.write_str("Mf"/&); }
ty_f64 { w.write_str("MF"/&); }
}
}
ty::ty_str { w.write_char('S'); }
ty::ty_enum(def, substs) {
w.write_str("t[");
w.write_str("t["/&);
w.write_str(cx.ds(def));
w.write_char('|');
enc_substs(w, cx, substs);
w.write_char(']');
}
ty::ty_iface(def, tys) {
w.write_str("x[");
w.write_str("x["/&);
w.write_str(cx.ds(def));
w.write_char('|');
for tys.each {|t| enc_ty(w, cx, t); }
w.write_char(']');
}
ty::ty_tup(ts) {
w.write_str("T[");
w.write_str("T["/&);
for ts.each {|t| enc_ty(w, cx, t); }
w.write_char(']');
}
@ -251,7 +251,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
}
ty::ty_vec(mt) { w.write_char('I'); enc_mt(w, cx, mt); }
ty::ty_rec(fields) {
w.write_str("R[");
w.write_str("R["/&);
for fields.each {|field|
w.write_str(field.ident);
w.write_char('=');
@ -264,7 +264,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
enc_ty_fn(w, cx, f);
}
ty::ty_res(def, ty, substs) {
w.write_str("r[");
w.write_str("r["/&);
w.write_str(cx.ds(def));
w.write_char('|');
enc_ty(w, cx, ty);
@ -282,16 +282,16 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
w.write_str(uint::str(id));
}
ty::ty_self(tps) {
w.write_str("s[");
w.write_str("s["/&);
for tps.each {|t| enc_ty(w, cx, t); }
w.write_char(']');
}
ty::ty_type { w.write_char('Y'); }
ty::ty_opaque_closure_ptr(ty::ck_block) { w.write_str("C&"); }
ty::ty_opaque_closure_ptr(ty::ck_box) { w.write_str("C@"); }
ty::ty_opaque_closure_ptr(ty::ck_uniq) { w.write_str("C~"); }
ty::ty_opaque_closure_ptr(ty::ck_block) { w.write_str("C&"/&); }
ty::ty_opaque_closure_ptr(ty::ck_box) { w.write_str("C@"/&); }
ty::ty_opaque_closure_ptr(ty::ck_uniq) { w.write_str("C~"/&); }
ty::ty_constr(ty, cs) {
w.write_str("A[");
w.write_str("A["/&);
enc_ty(w, cx, ty);
for cs.each {|tc| enc_ty_constr(w, cx, tc); }
w.write_char(']');
@ -299,12 +299,12 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
ty::ty_opaque_box { w.write_char('B'); }
ty::ty_class(def, substs) {
#debug("~~~~ %s", "a[");
w.write_str("a[");
w.write_str("a["/&);
let s = cx.ds(def);
#debug("~~~~ %s", s);
w.write_str(s);
#debug("~~~~ %s", "|");
w.write_str("|");
w.write_char('|');
enc_substs(w, cx, substs);
#debug("~~~~ %s", "]");
w.write_char(']');
@ -313,11 +313,11 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
}
fn enc_proto(w: io::writer, proto: proto) {
alt proto {
proto_uniq { w.write_str("f~"); }
proto_box { w.write_str("f@"); }
proto_uniq { w.write_str("f~"/&); }
proto_box { w.write_str("f@"/&); }
proto_block { w.write_str("f&"); }
proto_any { w.write_str("f*"); }
proto_bare { w.write_str("fn"); }
proto_any { w.write_str("f*"/&); }
proto_bare { w.write_str("fn"/&); }
}
}

View file

@ -80,7 +80,7 @@ fn chanmb(i: uint, size: uint, ch: comm::chan<line>) -> ()
type devnull = {dn: int};
impl of io::writer for devnull {
fn write(_b: [const u8]) {}
fn write(_b: [const u8]/&) {}
fn seek(_i: int, _s: io::seek_style) {}
fn tell() -> uint {0_u}
fn flush() -> int {0}