mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 14:07:04 +00:00
Use the slice repr for ~[T]
This commit is contained in:
parent
5fb2dfaa20
commit
34d607f9c9
@ -92,6 +92,8 @@ use core::iter::{range_step, MultiplicativeIterator};
|
||||
|
||||
use MutableSeq;
|
||||
use vec::Vec;
|
||||
#[cfg(not(stage0))]
|
||||
use raw::Slice;
|
||||
|
||||
pub use core::slice::{Chunks, Slice, ImmutableSlice, ImmutablePartialEqSlice};
|
||||
pub use core::slice::{ImmutableOrdSlice, MutableSlice, Items, MutItems};
|
||||
@ -282,6 +284,64 @@ pub trait CloneableVector<T> {
|
||||
|
||||
impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
|
||||
/// Returns a copy of `v`.
|
||||
#[cfg(not(stage0))]
|
||||
fn to_owned(&self) -> ~[T] {
|
||||
use num::CheckedMul;
|
||||
use option::Expect;
|
||||
|
||||
let len = self.len();
|
||||
|
||||
if len == 0 {
|
||||
unsafe {
|
||||
let slice: Slice<T> = Slice{data: 0 as *T, len: 0};
|
||||
mem::transmute(slice)
|
||||
}
|
||||
} else {
|
||||
let unit_size = mem::size_of::<T>();
|
||||
let data_size = if unit_size == 0 {
|
||||
len
|
||||
} else {
|
||||
let data_size = len.checked_mul(&unit_size);
|
||||
data_size.expect("overflow in from_iter()")
|
||||
};
|
||||
|
||||
unsafe {
|
||||
// this should pass the real required alignment
|
||||
let ret = allocate(data_size, 8) as *mut T;
|
||||
|
||||
if unit_size > 0 {
|
||||
// Be careful with the following loop. We want it to be optimized
|
||||
// to a memcpy (or something similarly fast) when T is Copy. LLVM
|
||||
// is easily confused, so any extra operations during the loop can
|
||||
// prevent this optimization.
|
||||
let mut i = 0;
|
||||
let p = &mut (*ret) as *mut _ as *mut T;
|
||||
try_finally(
|
||||
&mut i, (),
|
||||
|i, ()| while *i < len {
|
||||
mem::move_val_init(
|
||||
&mut(*p.offset(*i as int)),
|
||||
self.unsafe_ref(*i).clone());
|
||||
*i += 1;
|
||||
},
|
||||
|i| if *i < len {
|
||||
// we must be failing, clean up after ourselves
|
||||
for j in range(0, *i as int) {
|
||||
ptr::read(&*p.offset(j));
|
||||
}
|
||||
// FIXME: #13994 (should pass align and size here)
|
||||
deallocate(ret as *mut u8, 0, 8);
|
||||
});
|
||||
}
|
||||
let slice: Slice<T> = Slice{data: ret as *T, len: len};
|
||||
mem::transmute(slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a copy of `v`.
|
||||
// NOTE: remove after snapshot
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
fn to_vec(&self) -> Vec<T> { Vec::from_slice(*self) }
|
||||
|
||||
|
@ -174,7 +174,7 @@ pub unsafe fn overwrite<T>(dst: *mut T, src: T) {
|
||||
|
||||
/// Deprecated, use `overwrite` instead
|
||||
#[inline]
|
||||
#[deprecated = "use ptr::write"]
|
||||
#[deprecated = "this function has been renamed to overwrite()"]
|
||||
pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
|
||||
ptr::write(dst, src)
|
||||
}
|
||||
|
@ -305,8 +305,7 @@ impl Case {
|
||||
|
||||
// Box<T> could either be a thin or fat pointer depending on T
|
||||
ty::ty_uniq(t) => match ty::get(t).sty {
|
||||
// Box<[T]>/Box<str> might be FatPointer in a post DST world
|
||||
ty::ty_vec(_, None) | ty::ty_str => continue,
|
||||
ty::ty_vec(_, None) | return Some(FatPointer(i, slice_elt_base)),
|
||||
|
||||
// Box<Trait> is a pair of pointers: the actual object and a vtable
|
||||
ty::ty_trait(..) => return Some(FatPointer(i, trt_field_box)),
|
||||
@ -326,7 +325,6 @@ impl Case {
|
||||
|
||||
// Anything else is not a pointer
|
||||
_ => continue
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,6 +195,16 @@ pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
|
||||
llvm::NoReturnAttribute as uint64_t)
|
||||
}
|
||||
}
|
||||
// `~` pointer return values never alias because ownership is transferred
|
||||
ty::ty_uniq(t)
|
||||
=> match ty::get(t).sty {
|
||||
ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => {}
|
||||
_ => unsafe {
|
||||
llvm::LLVMAddReturnAttribute(llfn,
|
||||
lib::llvm::NoAliasAttribute as c_uint,
|
||||
lib::llvm::NoReturnAttribute as uint64_t);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -364,20 +374,19 @@ fn require_alloc_fn(bcx: &Block, info_ty: ty::t, it: LangItem) -> ast::DefId {
|
||||
// a given type, but with a potentially dynamic size.
|
||||
|
||||
pub fn malloc_raw_dyn<'a>(bcx: &'a Block<'a>,
|
||||
ptr_ty: ty::t,
|
||||
llty_ptr: Type,
|
||||
info_ty: ty::t,
|
||||
size: ValueRef,
|
||||
align: ValueRef)
|
||||
-> Result<'a> {
|
||||
let _icx = push_ctxt("malloc_raw_exchange");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
// Allocate space:
|
||||
let r = callee::trans_lang_call(bcx,
|
||||
require_alloc_fn(bcx, ptr_ty, ExchangeMallocFnLangItem),
|
||||
require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem),
|
||||
[size, align],
|
||||
None);
|
||||
|
||||
let llty_ptr = type_of::type_of(ccx, ptr_ty);
|
||||
Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
|
||||
}
|
||||
|
||||
@ -731,8 +740,8 @@ pub fn iter_structural_ty<'r,
|
||||
}
|
||||
}
|
||||
ty::ty_vec(_, Some(n)) => {
|
||||
let (base, len) = tvec::get_fixed_base_and_len(cx, av, n);
|
||||
let unit_ty = ty::sequence_element_type(cx.tcx(), t);
|
||||
let (base, len) = tvec::get_fixed_base_and_byte_len(cx, av, unit_ty, n);
|
||||
cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
|
||||
}
|
||||
ty::ty_tup(ref args) => {
|
||||
|
@ -2718,81 +2718,6 @@ fn fixed_vec_metadata(cx: &CrateContext,
|
||||
return MetadataCreationResult::new(metadata, false);
|
||||
}
|
||||
|
||||
fn heap_vec_metadata(cx: &CrateContext,
|
||||
vec_pointer_type: ty::t,
|
||||
element_type: ty::t,
|
||||
unique_type_id: UniqueTypeId,
|
||||
span: Span)
|
||||
-> MetadataCreationResult {
|
||||
let element_type_metadata = type_metadata(cx, element_type, span);
|
||||
let element_llvm_type = type_of::type_of(cx, element_type);
|
||||
let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
|
||||
|
||||
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
||||
|
||||
let vecbox_llvm_type = Type::vec(cx, &element_llvm_type);
|
||||
let vec_pointer_type_name = compute_debuginfo_type_name(cx,
|
||||
vec_pointer_type,
|
||||
true);
|
||||
let vec_pointer_type_name = vec_pointer_type_name.as_slice();
|
||||
|
||||
let member_llvm_types = vecbox_llvm_type.field_types();
|
||||
|
||||
let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
|
||||
let array_type_metadata = unsafe {
|
||||
llvm::LLVMDIBuilderCreateArrayType(
|
||||
DIB(cx),
|
||||
bytes_to_bits(element_size),
|
||||
bytes_to_bits(element_align),
|
||||
element_type_metadata,
|
||||
create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
|
||||
};
|
||||
|
||||
let member_descriptions = [
|
||||
MemberDescription {
|
||||
name: "fill".to_string(),
|
||||
llvm_type: *member_llvm_types.get(0),
|
||||
type_metadata: int_type_metadata,
|
||||
offset: ComputedMemberOffset,
|
||||
},
|
||||
MemberDescription {
|
||||
name: "alloc".to_string(),
|
||||
llvm_type: *member_llvm_types.get(1),
|
||||
type_metadata: int_type_metadata,
|
||||
offset: ComputedMemberOffset,
|
||||
},
|
||||
MemberDescription {
|
||||
name: "elements".to_string(),
|
||||
llvm_type: *member_llvm_types.get(2),
|
||||
type_metadata: array_type_metadata,
|
||||
offset: ComputedMemberOffset,
|
||||
}
|
||||
];
|
||||
|
||||
assert!(member_descriptions.len() == member_llvm_types.len());
|
||||
|
||||
let loc = span_start(cx, span);
|
||||
let file_metadata = file_metadata(cx, loc.file.name.as_slice());
|
||||
|
||||
let vec_box_unique_id = debug_context(cx).type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_of_heap_vec_box(cx,
|
||||
element_type);
|
||||
|
||||
let vecbox_metadata = composite_type_metadata(cx,
|
||||
vecbox_llvm_type,
|
||||
vec_pointer_type_name,
|
||||
vec_box_unique_id,
|
||||
member_descriptions,
|
||||
UNKNOWN_SCOPE_METADATA,
|
||||
file_metadata,
|
||||
span);
|
||||
|
||||
MetadataCreationResult::new(pointer_type_metadata(cx,
|
||||
vec_pointer_type,
|
||||
vecbox_metadata), false)
|
||||
}
|
||||
|
||||
fn vec_slice_metadata(cx: &CrateContext,
|
||||
vec_type: ty::t,
|
||||
element_type: ty::t,
|
||||
@ -2995,11 +2920,13 @@ fn type_metadata(cx: &CrateContext,
|
||||
ty::ty_uniq(pointee_type) => {
|
||||
match ty::get(pointee_type).sty {
|
||||
ty::ty_vec(ref mt, None) => {
|
||||
heap_vec_metadata(cx, pointee_type, mt.ty, unique_type_id, usage_site_span)
|
||||
let vec_metadata = vec_slice_metadata(cx, t, mt.ty, usage_site_span);
|
||||
pointer_type_metadata(cx, t, vec_metadata)
|
||||
}
|
||||
ty::ty_str => {
|
||||
let i8_t = ty::mk_i8();
|
||||
heap_vec_metadata(cx, pointee_type, i8_t, unique_type_id, usage_site_span)
|
||||
let vec_metadata = vec_slice_metadata(cx, t, i8_t, usage_site_span);
|
||||
pointer_type_metadata(cx, t, vec_metadata)
|
||||
}
|
||||
ty::ty_trait(..) => {
|
||||
MetadataCreationResult::new(
|
||||
|
@ -395,8 +395,8 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
|
||||
ast::ExprField(ref base, ident, _) => {
|
||||
trans_rec_field(bcx, &**base, ident.node)
|
||||
}
|
||||
ast::ExprIndex(ref base, ref idx) => {
|
||||
trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
|
||||
ast::ExprIndex(base, idx) => {
|
||||
trans_index(bcx, expr.span, &**base, &**idx, MethodCall::expr(expr.id))
|
||||
}
|
||||
ast::ExprVstore(ref contents, ast::ExprVstoreUniq) => {
|
||||
fcx.push_ast_cleanup_scope(contents.id);
|
||||
@ -465,7 +465,7 @@ fn trans_rec_field<'a>(bcx: &'a Block<'a>,
|
||||
}
|
||||
|
||||
fn trans_index<'a>(bcx: &'a Block<'a>,
|
||||
index_expr: &ast::Expr,
|
||||
sp: codemap::Span,
|
||||
base: &ast::Expr,
|
||||
idx: &ast::Expr,
|
||||
method_call: MethodCall)
|
||||
@ -1256,10 +1256,8 @@ fn trans_uniq_expr<'a>(bcx: &'a Block<'a>,
|
||||
let llty = type_of::type_of(bcx.ccx(), contents_ty);
|
||||
let size = llsize_of(bcx.ccx(), llty);
|
||||
let align = C_uint(bcx.ccx(), llalign_of_min(bcx.ccx(), llty) as uint);
|
||||
// We need to a make a pointer type because box_ty is ty_bot
|
||||
// if content_ty is, e.g. box fail!().
|
||||
let real_box_ty = ty::mk_uniq(bcx.tcx(), contents_ty);
|
||||
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size, align);
|
||||
let llty_ptr = llty.ptr_to();
|
||||
let Result { bcx, val } = malloc_raw_dyn(bcx, llty_ptr, box_ty, size, align);
|
||||
// Unique boxes do not allocate for zero-size types. The standard library
|
||||
// may assume that `free` is never called on the pointer returned for
|
||||
// `Box<ZeroSizeType>`.
|
||||
|
@ -51,7 +51,7 @@ pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> {
|
||||
Some(expr::Ignore)).bcx
|
||||
}
|
||||
|
||||
fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef, size: u64,
|
||||
pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef, size: u64,
|
||||
align: u64) -> &'a Block<'a> {
|
||||
let _icx = push_ctxt("trans_exchange_free");
|
||||
let ccx = cx.ccx();
|
||||
@ -120,8 +120,8 @@ pub fn drop_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
|
||||
-> &'a Block<'a> {
|
||||
// NB: v is an *alias* of type t here, not a direct value.
|
||||
let _icx = push_ctxt("drop_ty");
|
||||
let ccx = bcx.ccx();
|
||||
if ty::type_needs_drop(bcx.tcx(), t) {
|
||||
let ccx = bcx.ccx();
|
||||
let glue = get_drop_glue(ccx, t);
|
||||
let glue_type = get_drop_glue_type(ccx, t);
|
||||
let ptr = if glue_type != t {
|
||||
@ -277,23 +277,11 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
|
||||
ty::ty_uniq(content_ty) => {
|
||||
match ty::get(content_ty).sty {
|
||||
ty::ty_vec(mt, None) => {
|
||||
let llbox = Load(bcx, v0);
|
||||
let not_null = IsNotNull(bcx, llbox);
|
||||
with_cond(bcx, not_null, |bcx| {
|
||||
let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, mt.ty);
|
||||
// FIXME: #13994: the old `Box<[T]>` will not support sized deallocation
|
||||
trans_exchange_free(bcx, llbox, 0, 8)
|
||||
})
|
||||
tvec::make_drop_glue_unboxed(bcx, v0, mt.ty)
|
||||
}
|
||||
ty::ty_str => {
|
||||
let llbox = Load(bcx, v0);
|
||||
let not_null = IsNotNull(bcx, llbox);
|
||||
with_cond(bcx, not_null, |bcx| {
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
|
||||
let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, unit_ty);
|
||||
// FIXME: #13994: the old `Box<str>` will not support sized deallocation
|
||||
trans_exchange_free(bcx, llbox, 0, 8)
|
||||
})
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
|
||||
tvec::make_drop_glue_unboxed(bcx, v0, unit_ty)
|
||||
}
|
||||
ty::ty_trait(..) => {
|
||||
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
|
||||
|
@ -164,6 +164,10 @@ impl<'a, 'b> Reflector<'a, 'b> {
|
||||
});
|
||||
self.visit("box", extra.as_slice())
|
||||
}
|
||||
ty::ty_ptr(ref mt) => {
|
||||
let extra = self.c_mt(mt);
|
||||
self.visit("ptr", extra.as_slice())
|
||||
}
|
||||
ty::ty_uniq(typ) => {
|
||||
match ty::get(typ).sty {
|
||||
ty::ty_vec(ref mt, None) => {
|
||||
@ -188,17 +192,12 @@ impl<'a, 'b> Reflector<'a, 'b> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ty_ptr(ref mt) => {
|
||||
let extra = self.c_mt(mt);
|
||||
self.visit("ptr", extra.as_slice())
|
||||
}
|
||||
ty::ty_rptr(_, ref mt) => {
|
||||
match ty::get(mt.ty).sty {
|
||||
ty::ty_vec(ref mt, None) => {
|
||||
let (name, extra) = ("slice".to_string(), Vec::new());
|
||||
let extra = Vec::new();
|
||||
let extra = extra.append(self.c_mt(mt).as_slice());
|
||||
self.visit(format!("evec_{}", name).as_slice(),
|
||||
extra.as_slice())
|
||||
self.visit("evec_slice", extra.as_slice())
|
||||
}
|
||||
ty::ty_str => self.visit("estr_slice", &[]),
|
||||
ty::ty_trait(..) => {
|
||||
|
@ -17,7 +17,6 @@ use middle::lang_items::StrDupUniqFnLangItem;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::base;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::callee;
|
||||
use middle::trans::cleanup;
|
||||
use middle::trans::cleanup::CleanupMethods;
|
||||
use middle::trans::common::*;
|
||||
@ -25,7 +24,7 @@ use middle::trans::datum::*;
|
||||
use middle::trans::expr::{Dest, Ignore, SaveIn};
|
||||
use middle::trans::expr;
|
||||
use middle::trans::glue;
|
||||
use middle::trans::machine::{llsize_of, nonzero_llsize_of, llsize_of_alloc};
|
||||
use middle::trans::machine::{nonzero_llsize_of, llsize_of_alloc};
|
||||
use middle::trans::type_::Type;
|
||||
use middle::trans::type_of;
|
||||
use middle::ty;
|
||||
@ -34,14 +33,14 @@ use util::ppaux::ty_to_string;
|
||||
use syntax::ast;
|
||||
use syntax::parse::token::InternedString;
|
||||
|
||||
pub fn get_fill(bcx: &Block, vptr: ValueRef) -> ValueRef {
|
||||
let _icx = push_ctxt("tvec::get_fill");
|
||||
Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill]))
|
||||
fn get_len(bcx: &Block, vptr: ValueRef) -> ValueRef {
|
||||
let _icx = push_ctxt("tvec::get_lenl");
|
||||
Load(bcx, GEPi(bcx, vptr, [0u, abi::slice_elt_len]))
|
||||
}
|
||||
|
||||
pub fn get_dataptr(bcx: &Block, vptr: ValueRef) -> ValueRef {
|
||||
fn get_dataptr(bcx: &Block, vptr: ValueRef) -> ValueRef {
|
||||
let _icx = push_ctxt("tvec::get_dataptr");
|
||||
GEPi(bcx, vptr, [0u, abi::vec_elt_elems, 0u])
|
||||
Load(bcx, GEPi(bcx, vptr, [0u, abi::slice_elt_base]))
|
||||
}
|
||||
|
||||
pub fn pointer_add_byte(bcx: &Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
|
||||
@ -56,13 +55,21 @@ pub fn make_drop_glue_unboxed<'a>(
|
||||
vptr: ValueRef,
|
||||
unit_ty: ty::t)
|
||||
-> &'a Block<'a> {
|
||||
let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
|
||||
let tcx = bcx.tcx();
|
||||
if ty::type_needs_drop(tcx, unit_ty) {
|
||||
let fill = get_fill(bcx, vptr);
|
||||
let not_null = IsNotNull(bcx, vptr);
|
||||
with_cond(bcx, not_null, |bcx| {
|
||||
let tcx = bcx.tcx();
|
||||
let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
|
||||
|
||||
let len = get_len(bcx, vptr);
|
||||
let dataptr = get_dataptr(bcx, vptr);
|
||||
iter_vec_raw(bcx, dataptr, unit_ty, fill, glue::drop_ty)
|
||||
} else { bcx }
|
||||
let bcx = if ty::type_needs_drop(tcx, unit_ty) {
|
||||
iter_vec_raw(bcx, dataptr, unit_ty, len, glue::drop_ty)
|
||||
} else {
|
||||
bcx
|
||||
};
|
||||
|
||||
glue::trans_exchange_free(bcx, dataptr, 0, 8)
|
||||
})
|
||||
}
|
||||
|
||||
pub struct VecTypes {
|
||||
@ -112,12 +119,11 @@ pub fn trans_fixed_vstore<'a>(
|
||||
};
|
||||
}
|
||||
|
||||
pub fn trans_slice_vstore<'a>(
|
||||
bcx: &'a Block<'a>,
|
||||
vstore_expr: &ast::Expr,
|
||||
content_expr: &ast::Expr,
|
||||
dest: expr::Dest)
|
||||
-> &'a Block<'a> {
|
||||
pub fn trans_slice_vstore<'a>(bcx: &'a Block<'a>,
|
||||
vstore_expr: &ast::Expr,
|
||||
content_expr: &ast::Expr,
|
||||
dest: expr::Dest)
|
||||
-> &'a Block<'a> {
|
||||
/*!
|
||||
* &[...] allocates memory on the stack and writes the values into it,
|
||||
* returning a slice (pair of ptr, len). &"..." is similar except that
|
||||
@ -150,17 +156,16 @@ pub fn trans_slice_vstore<'a>(
|
||||
// Handle the &[...] case:
|
||||
let vt = vec_types_from_expr(bcx, vstore_expr);
|
||||
let count = elements_required(bcx, content_expr);
|
||||
debug!("vt={}, count={:?}", vt.to_string(ccx), count);
|
||||
|
||||
debug!(" vt={}, count={:?}", vt.to_str(ccx), count);
|
||||
let llcount = C_uint(ccx, count);
|
||||
let llfixed;
|
||||
if count == 0 {
|
||||
|
||||
let llfixed = if count == 0 {
|
||||
// Just create a zero-sized alloca to preserve
|
||||
// the non-null invariant of the inner slice ptr
|
||||
llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
|
||||
base::arrayalloca(bcx, vt.llunit_ty, llcount)
|
||||
} else {
|
||||
// Make a fixed-length backing array and allocate it on the stack.
|
||||
llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
|
||||
let llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
|
||||
|
||||
// Arrange for the backing array to be cleaned up.
|
||||
let fixed_ty = ty::mk_vec(bcx.tcx(),
|
||||
@ -176,7 +181,9 @@ pub fn trans_slice_vstore<'a>(
|
||||
// Generate the content into the backing array.
|
||||
bcx = write_content(bcx, &vt, vstore_expr,
|
||||
content_expr, SaveIn(llfixed));
|
||||
}
|
||||
|
||||
llfixed
|
||||
};
|
||||
|
||||
// Finally, create the slice pair itself.
|
||||
match dest {
|
||||
@ -198,7 +205,7 @@ pub fn trans_lit_str<'a>(
|
||||
-> &'a Block<'a> {
|
||||
/*!
|
||||
* Literal strings translate to slices into static memory. This is
|
||||
* different from trans_slice_vstore() above because it does need to copy
|
||||
* different from trans_slice_vstore() above because it doesn't need to copy
|
||||
* the content anywhere.
|
||||
*/
|
||||
|
||||
@ -214,17 +221,14 @@ pub fn trans_lit_str<'a>(
|
||||
let llbytes = C_uint(bcx.ccx(), bytes);
|
||||
let llcstr = C_cstr(bcx.ccx(), str_lit, false);
|
||||
let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p(bcx.ccx()).to_ref());
|
||||
Store(bcx, llcstr,
|
||||
GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
|
||||
Store(bcx, llbytes,
|
||||
GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
|
||||
Store(bcx, llcstr, GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
|
||||
Store(bcx, llbytes, GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
|
||||
bcx
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
|
||||
vstore_expr: &ast::Expr,
|
||||
content_expr: &ast::Expr)
|
||||
@ -238,74 +242,47 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
|
||||
let fcx = bcx.fcx;
|
||||
let ccx = fcx.ccx;
|
||||
|
||||
// Handle "".to_string().
|
||||
match content_expr.node {
|
||||
ast::ExprLit(lit) => {
|
||||
match lit.node {
|
||||
ast::LitStr(ref s, _) => {
|
||||
let llptrval = C_cstr(ccx, (*s).clone(), false);
|
||||
let llptrval = PointerCast(bcx, llptrval, Type::i8p(ccx));
|
||||
let llsizeval = C_uint(ccx, s.get().len());
|
||||
let typ = ty::mk_uniq(bcx.tcx(), ty::mk_str(bcx.tcx()));
|
||||
let lldestval = rvalue_scratch_datum(bcx,
|
||||
typ,
|
||||
"");
|
||||
let alloc_fn = langcall(bcx,
|
||||
Some(lit.span),
|
||||
"",
|
||||
StrDupUniqFnLangItem);
|
||||
let bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
alloc_fn,
|
||||
[ llptrval, llsizeval ],
|
||||
Some(expr::SaveIn(lldestval.val))).bcx;
|
||||
return DatumBlock::new(bcx, lldestval).to_expr_datumblock();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let vec_ty = node_id_type(bcx, vstore_expr.id);
|
||||
let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
|
||||
let vt = vec_types_from_expr(bcx, vstore_expr);
|
||||
let count = elements_required(bcx, content_expr);
|
||||
debug!(" vt={}, count={:?}", vt.to_str(ccx), count);
|
||||
let llcount = C_uint(ccx, count);
|
||||
let vec_ty = node_id_type(bcx, vstore_expr.id);
|
||||
|
||||
let llunitty = type_of::type_of(ccx, vt.unit_ty);
|
||||
let unit_sz = nonzero_llsize_of(ccx, llunitty);
|
||||
|
||||
let unit_sz = nonzero_llsize_of(ccx, type_of::type_of(ccx, vt.unit_ty));
|
||||
let fill = Mul(bcx, C_uint(ccx, count), unit_sz);
|
||||
let alloc = if count < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) }
|
||||
else { fill };
|
||||
|
||||
let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
|
||||
|
||||
// ~[T] is not going to be changed to support alignment, since it's obsolete.
|
||||
let alloc = if count < 4u {
|
||||
Mul(bcx, C_int(ccx, 4), unit_sz)
|
||||
} else {
|
||||
fill
|
||||
};
|
||||
let llty_ptr = type_of::type_of(ccx, vt.unit_ty).ptr_to();
|
||||
let align = C_uint(ccx, 8);
|
||||
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize, align);
|
||||
Store(bcx, fill, GEPi(bcx, val, [0u, abi::vec_elt_fill]));
|
||||
Store(bcx, alloc, GEPi(bcx, val, [0u, abi::vec_elt_alloc]));
|
||||
let Result { bcx: bcx, val: dataptr } = malloc_raw_dyn(bcx,
|
||||
llty_ptr,
|
||||
vec_ty,
|
||||
alloc,
|
||||
align);
|
||||
|
||||
// Create a temporary scope lest execution should fail while
|
||||
// constructing the vector.
|
||||
let temp_scope = fcx.push_custom_cleanup_scope();
|
||||
|
||||
// FIXME: #13994: the old `Box<[T]> will not support sized deallocation, this is a placeholder
|
||||
let content_ty = vt.unit_ty;
|
||||
// FIXME: #13994: the old `Box<[T]> will not support sized deallocation,
|
||||
// this is a placeholder
|
||||
fcx.schedule_free_value(cleanup::CustomScope(temp_scope),
|
||||
val, cleanup::HeapExchange, content_ty);
|
||||
dataptr, cleanup::HeapExchange, vt.unit_ty);
|
||||
|
||||
let dataptr = get_dataptr(bcx, val);
|
||||
debug!(" alloc_uniq_vec() returned dataptr={}, len={}",
|
||||
bcx.val_to_str(dataptr), count);
|
||||
|
||||
debug!("alloc_uniq_vec() returned val={}, dataptr={}",
|
||||
bcx.val_to_string(val), bcx.val_to_string(dataptr));
|
||||
|
||||
let bcx = write_content(bcx, &vt, vstore_expr,
|
||||
content_expr, SaveIn(dataptr));
|
||||
let bcx = write_content(bcx, &vt, vstore_expr,
|
||||
content_expr, SaveIn(dataptr));
|
||||
|
||||
fcx.pop_custom_cleanup_scope(temp_scope);
|
||||
|
||||
immediate_rvalue_bcx(bcx, val, vec_ty).to_expr_datumblock()
|
||||
let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
|
||||
Store(bcx, dataptr, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
|
||||
Store(bcx, llcount, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
|
||||
DatumBlock(bcx, scratch.to_expr_datum())
|
||||
}
|
||||
|
||||
pub fn write_content<'a>(
|
||||
@ -451,21 +428,19 @@ pub fn elements_required(bcx: &Block, content_expr: &ast::Expr) -> uint {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_fixed_base_and_byte_len(bcx: &Block,
|
||||
llval: ValueRef,
|
||||
unit_ty: ty::t,
|
||||
vec_length: uint)
|
||||
-> (ValueRef, ValueRef) {
|
||||
pub fn get_fixed_base_and_len(bcx: &Block,
|
||||
llval: ValueRef,
|
||||
vec_length: uint)
|
||||
-> (ValueRef, ValueRef) {
|
||||
/*!
|
||||
* Converts a fixed-length vector into the slice pair.
|
||||
* The vector should be stored in `llval` which should be by ref.
|
||||
*/
|
||||
|
||||
let ccx = bcx.ccx();
|
||||
let vt = vec_types(bcx, unit_ty);
|
||||
|
||||
let base = GEPi(bcx, llval, [0u, 0u]);
|
||||
let len = Mul(bcx, C_uint(ccx, vec_length), vt.llunit_size);
|
||||
let base = GEPi(bcx, llval, [0u, abi::slice_elt_base]);
|
||||
let len = C_uint(ccx, vec_length);
|
||||
(base, len)
|
||||
}
|
||||
|
||||
@ -488,23 +463,13 @@ pub fn get_base_and_len(bcx: &Block,
|
||||
let base = GEPi(bcx, llval, [0u, 0u]);
|
||||
(base, C_uint(ccx, n))
|
||||
}
|
||||
ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
|
||||
ty::ty_vec(_, None) | ty::ty_str => {
|
||||
assert!(!type_is_immediate(bcx.ccx(), vec_ty));
|
||||
let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
|
||||
let count = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
|
||||
(base, count)
|
||||
let len = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
|
||||
(base, len)
|
||||
}
|
||||
_ => ccx.sess().bug("unexpected type (ty_rptr) in get_base_and_len"),
|
||||
},
|
||||
ty::ty_uniq(t) => match ty::get(t).sty {
|
||||
ty::ty_vec(_, None) | ty::ty_str => {
|
||||
assert!(type_is_immediate(bcx.ccx(), vec_ty));
|
||||
let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
|
||||
let body = Load(bcx, llval);
|
||||
(get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
|
||||
}
|
||||
_ => ccx.sess().bug("unexpected type (ty_uniq) in get_base_and_len"),
|
||||
_ => ccx.sess().bug("unexpected type in get_base_and_len"),
|
||||
},
|
||||
_ => ccx.sess().bug("unexpected type in get_base_and_len"),
|
||||
}
|
||||
@ -576,13 +541,15 @@ pub fn iter_vec_raw<'r,
|
||||
bcx: &'b Block<'b>,
|
||||
data_ptr: ValueRef,
|
||||
unit_ty: ty::t,
|
||||
fill: ValueRef,
|
||||
len: ValueRef,
|
||||
f: iter_vec_block<'r,'b>)
|
||||
-> &'b Block<'b> {
|
||||
let _icx = push_ctxt("tvec::iter_vec_raw");
|
||||
let fcx = bcx.fcx;
|
||||
|
||||
let vt = vec_types(bcx, unit_ty);
|
||||
let fill = Mul(bcx, len, vt.llunit_size);
|
||||
|
||||
if vt.llunit_alloc_size == 0 {
|
||||
// Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
|
||||
iter_vec_loop(bcx, data_ptr, &vt, fill, f)
|
||||
|
@ -215,7 +215,7 @@ impl Type {
|
||||
|
||||
pub fn vec(ccx: &CrateContext, ty: &Type) -> Type {
|
||||
Type::struct_(ccx,
|
||||
[Type::int(ccx), Type::int(ccx), Type::array(ty, 0)],
|
||||
[Type::array(ty, 0), Type::int(ccx)],
|
||||
false)
|
||||
}
|
||||
|
||||
|
@ -169,14 +169,8 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
|
||||
|
||||
ty::ty_box(..) |
|
||||
ty::ty_ptr(..) => Type::i8p(cx),
|
||||
ty::ty_uniq(ty) => {
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_trait(..) => Type::opaque_trait(cx),
|
||||
_ => Type::i8p(cx),
|
||||
}
|
||||
}
|
||||
ty::ty_rptr(_, mt) => {
|
||||
match ty::get(mt.ty).sty {
|
||||
ty::ty_vec(_, None) | ty::ty_str => {
|
||||
Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false)
|
||||
}
|
||||
@ -283,17 +277,10 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
|
||||
ty::ty_box(typ) => {
|
||||
Type::at_box(cx, type_of(cx, typ)).ptr_to()
|
||||
}
|
||||
ty::ty_uniq(typ) => {
|
||||
match ty::get(typ).sty {
|
||||
ty::ty_vec(mt, None) => Type::vec(cx, &type_of(cx, mt.ty)).ptr_to(),
|
||||
ty::ty_str => Type::vec(cx, &Type::i8(cx)).ptr_to(),
|
||||
ty::ty_trait(..) => Type::opaque_trait(cx),
|
||||
_ => type_of(cx, typ).ptr_to(),
|
||||
}
|
||||
}
|
||||
ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
|
||||
ty::ty_rptr(_, ref mt) => {
|
||||
match ty::get(mt.ty).sty {
|
||||
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_vec(mt, None) => {
|
||||
let p_ty = type_of(cx, mt.ty).ptr_to();
|
||||
let u_ty = Type::uint_from_ty(cx, ast::TyU);
|
||||
@ -304,7 +291,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
|
||||
cx.tn.find_type("str_slice").unwrap()
|
||||
}
|
||||
ty::ty_trait(..) => Type::opaque_trait(cx),
|
||||
_ => type_of(cx, mt.ty).ptr_to(),
|
||||
_ => type_of(cx, ty).ptr_to(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1816,8 +1816,7 @@ pub fn type_is_boxed(ty: t) -> bool {
|
||||
pub fn type_is_region_ptr(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_rptr(_, mt) => match get(mt.ty).sty {
|
||||
// FIXME(nrc, DST) slices weren't regarded as rptrs, so we preserve this
|
||||
// odd behaviour for now. (But ~[] were unique. I have no idea why).
|
||||
// DST pointers should not be treated like regular pointers.
|
||||
ty_vec(_, None) | ty_str | ty_trait(..) => false,
|
||||
_ => true
|
||||
},
|
||||
|
@ -23,11 +23,5 @@ pub static fn_field_box: uint = 1u;
|
||||
pub static trt_field_vtable: uint = 0u;
|
||||
pub static trt_field_box: uint = 1u;
|
||||
|
||||
pub static vec_elt_fill: uint = 0u;
|
||||
|
||||
pub static vec_elt_alloc: uint = 1u;
|
||||
|
||||
pub static vec_elt_elems: uint = 2u;
|
||||
|
||||
pub static slice_elt_base: uint = 0u;
|
||||
pub static slice_elt_len: uint = 1u;
|
||||
|
@ -18,6 +18,7 @@ use std::path;
|
||||
use std::rc::Rc;
|
||||
use std::gc::{Gc, GC};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::strbuf::StrBuf;
|
||||
|
||||
pub trait Encoder<E> {
|
||||
// Primitive types:
|
||||
|
@ -268,7 +268,19 @@ pub struct Tm {
|
||||
pub tm_nsec: i32,
|
||||
}
|
||||
|
||||
impl Tm {
|
||||
pub fn tm_zone<'a>(&'a self) -> &'a str {
|
||||
self.tm_zone.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty_tm() -> Tm {
|
||||
// 64 is the max size of the timezone buffer allocated on windows
|
||||
// in rust_localtime. In glibc the max timezone size is supposedly 3.
|
||||
let mut zone = StrBuf::new();
|
||||
for _ in range(0, 64) {
|
||||
zone.push_char(' ')
|
||||
}
|
||||
Tm {
|
||||
tm_sec: 0_i32,
|
||||
tm_min: 0_i32,
|
||||
@ -280,6 +292,7 @@ pub fn empty_tm() -> Tm {
|
||||
tm_yday: 0_i32,
|
||||
tm_isdst: 0_i32,
|
||||
tm_gmtoff: 0_i32,
|
||||
tm_zone: zone,
|
||||
tm_nsec: 0_i32,
|
||||
}
|
||||
}
|
||||
@ -760,6 +773,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, String> {
|
||||
'Z' => {
|
||||
if match_str(s, pos, "UTC") || match_str(s, pos, "GMT") {
|
||||
tm.tm_gmtoff = 0_i32;
|
||||
tm.tm_zone = "UTC".into_strbuf();
|
||||
Ok(pos + 3u)
|
||||
} else {
|
||||
// It's odd, but to maintain compatibility with c's
|
||||
@ -784,6 +798,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, String> {
|
||||
let (v, pos) = item;
|
||||
if v == 0_i32 {
|
||||
tm.tm_gmtoff = 0_i32;
|
||||
tm.tm_zone = "UTC".into_strbuf();
|
||||
}
|
||||
|
||||
Ok(pos)
|
||||
@ -813,6 +828,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, String> {
|
||||
tm_yday: 0_i32,
|
||||
tm_isdst: 0_i32,
|
||||
tm_gmtoff: 0_i32,
|
||||
tm_zone: StrBuf::new(),
|
||||
tm_nsec: 0_i32,
|
||||
};
|
||||
let mut pos = 0u;
|
||||
@ -859,6 +875,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, String> {
|
||||
tm_yday: tm.tm_yday,
|
||||
tm_isdst: tm.tm_isdst,
|
||||
tm_gmtoff: tm.tm_gmtoff,
|
||||
tm_zone: tm.tm_zone.clone(),
|
||||
tm_nsec: tm.tm_nsec,
|
||||
})
|
||||
} else { result }
|
||||
@ -1060,7 +1077,7 @@ pub fn strftime(format: &str, tm: &Tm) -> String {
|
||||
'w' => (tm.tm_wday as int).to_string(),
|
||||
'Y' => (tm.tm_year as int + 1900).to_string(),
|
||||
'y' => format!("{:02d}", (tm.tm_year as int + 1900) % 100),
|
||||
'Z' => "".to_string(), // FIXME(pcwalton): Implement this.
|
||||
'Z' => tm.tm_zone.as_slice().to_owned(),
|
||||
'z' => {
|
||||
let sign = if tm.tm_gmtoff > 0_i32 { '+' } else { '-' };
|
||||
let mut m = num::abs(tm.tm_gmtoff) / 60_i32;
|
||||
@ -1186,6 +1203,7 @@ mod tests {
|
||||
assert_eq!(utc.tm_yday, 43_i32);
|
||||
assert_eq!(utc.tm_isdst, 0_i32);
|
||||
assert_eq!(utc.tm_gmtoff, 0_i32);
|
||||
assert_eq!(utc.tm_zone(), "UTC");
|
||||
assert_eq!(utc.tm_nsec, 54321_i32);
|
||||
}
|
||||
|
||||
@ -1207,6 +1225,12 @@ mod tests {
|
||||
assert_eq!(local.tm_yday, 43_i32);
|
||||
assert_eq!(local.tm_isdst, 0_i32);
|
||||
assert_eq!(local.tm_gmtoff, -28800_i32);
|
||||
|
||||
// FIXME (#2350): We should probably standardize on the timezone
|
||||
// abbreviation.
|
||||
let zone = local.tm_zone();
|
||||
assert!(zone == "PST" || zone == "Pacific Standard Time");
|
||||
|
||||
assert_eq!(local.tm_nsec, 54321_i32);
|
||||
}
|
||||
|
||||
@ -1249,6 +1273,7 @@ mod tests {
|
||||
assert!(tm.tm_wday == 0_i32);
|
||||
assert!(tm.tm_isdst == 0_i32);
|
||||
assert!(tm.tm_gmtoff == 0_i32);
|
||||
assert!(tm.tm_zone() == "");
|
||||
assert!(tm.tm_nsec == 0_i32);
|
||||
}
|
||||
Err(_) => ()
|
||||
@ -1272,6 +1297,7 @@ mod tests {
|
||||
assert!(tm.tm_yday == 0_i32);
|
||||
assert!(tm.tm_isdst == 0_i32);
|
||||
assert!(tm.tm_gmtoff == 0_i32);
|
||||
assert!(tm.tm_zone() == "");
|
||||
assert!(tm.tm_nsec == 12340000_i32);
|
||||
}
|
||||
}
|
||||
@ -1383,10 +1409,10 @@ mod tests {
|
||||
assert!(test("6", "%w"));
|
||||
assert!(test("2009", "%Y"));
|
||||
assert!(test("09", "%y"));
|
||||
assert!(strptime("-0000", "%z").unwrap().tm_gmtoff ==
|
||||
0);
|
||||
assert!(strptime("-0800", "%z").unwrap().tm_gmtoff ==
|
||||
0);
|
||||
assert!(strptime("UTC", "%Z").unwrap().tm_zone() == "UTC");
|
||||
assert!(strptime("PST", "%Z").unwrap().tm_zone() == "");
|
||||
assert!(strptime("-0000", "%z").unwrap().tm_gmtoff == 0);
|
||||
assert!(strptime("-0800", "%z").unwrap().tm_gmtoff == 0);
|
||||
assert!(test("%", "%%"));
|
||||
|
||||
// Test for #7256
|
||||
|
@ -127,6 +127,15 @@ rust_list_dir_wfd_fp_buf(void* wfd) {
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t fill; // in bytes; if zero, heapified
|
||||
size_t alloc; // in bytes
|
||||
uint8_t *data;
|
||||
} rust_vec;
|
||||
|
||||
typedef rust_vec rust_str_buf;
|
||||
|
||||
typedef struct {
|
||||
int32_t tm_sec;
|
||||
int32_t tm_min;
|
||||
@ -138,6 +147,7 @@ typedef struct {
|
||||
int32_t tm_yday;
|
||||
int32_t tm_isdst;
|
||||
int32_t tm_gmtoff;
|
||||
rust_str_buf tm_zone;
|
||||
int32_t tm_nsec;
|
||||
} rust_tm;
|
||||
|
||||
@ -154,10 +164,8 @@ void rust_tm_to_tm(rust_tm* in_tm, struct tm* out_tm) {
|
||||
out_tm->tm_isdst = in_tm->tm_isdst;
|
||||
}
|
||||
|
||||
void tm_to_rust_tm(struct tm* in_tm,
|
||||
rust_tm* out_tm,
|
||||
int32_t gmtoff,
|
||||
int32_t nsec) {
|
||||
void tm_to_rust_tm(struct tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
|
||||
const char *zone, int32_t nsec) {
|
||||
out_tm->tm_sec = in_tm->tm_sec;
|
||||
out_tm->tm_min = in_tm->tm_min;
|
||||
out_tm->tm_hour = in_tm->tm_hour;
|
||||
@ -169,6 +177,13 @@ void tm_to_rust_tm(struct tm* in_tm,
|
||||
out_tm->tm_isdst = in_tm->tm_isdst;
|
||||
out_tm->tm_gmtoff = gmtoff;
|
||||
out_tm->tm_nsec = nsec;
|
||||
|
||||
if (zone != NULL) {
|
||||
size_t size = strlen(zone);
|
||||
assert(out_tm->tm_zone.alloc >= size);
|
||||
memcpy(out_tm->tm_zone.data, zone, size);
|
||||
out_tm->tm_zone.fill = size;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__WIN32__)
|
||||
@ -210,7 +225,7 @@ rust_gmtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
|
||||
time_t s = sec;
|
||||
GMTIME(&s, &tm);
|
||||
|
||||
tm_to_rust_tm(&tm, timeptr, 0, nsec);
|
||||
tm_to_rust_tm(&tm, timeptr, 0, "UTC", nsec);
|
||||
}
|
||||
|
||||
void
|
||||
@ -219,13 +234,28 @@ rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
|
||||
time_t s = sec;
|
||||
LOCALTIME(&s, &tm);
|
||||
|
||||
const char* zone = NULL;
|
||||
#if defined(__WIN32__)
|
||||
int32_t gmtoff = -timezone;
|
||||
wchar_t wbuffer[64] = {0};
|
||||
char buffer[256] = {0};
|
||||
// strftime("%Z") can contain non-UTF-8 characters on non-English locale (issue #9418),
|
||||
// so time zone should be converted from UTF-16 string.
|
||||
// Since wcsftime depends on setlocale() result,
|
||||
// instead we convert it using MultiByteToWideChar.
|
||||
if (strftime(buffer, sizeof(buffer) / sizeof(char), "%Z", &tm) > 0) {
|
||||
// ANSI -> UTF-16
|
||||
MultiByteToWideChar(CP_ACP, 0, buffer, -1, wbuffer, sizeof(wbuffer) / sizeof(wchar_t));
|
||||
// UTF-16 -> UTF-8
|
||||
WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, sizeof(buffer), NULL, NULL);
|
||||
zone = buffer;
|
||||
}
|
||||
#else
|
||||
int32_t gmtoff = tm.tm_gmtoff;
|
||||
zone = tm.tm_zone;
|
||||
#endif
|
||||
|
||||
tm_to_rust_tm(&tm, timeptr, gmtoff, nsec);
|
||||
tm_to_rust_tm(&tm, timeptr, gmtoff, zone, nsec);
|
||||
}
|
||||
|
||||
int64_t
|
||||
|
Loading…
Reference in New Issue
Block a user