<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Blocking posix-based file I/O

use std::c_str::CString;
use std::io::IoError;
use std::io;
use std::libc::{c_int, c_void};
use std::libc;
use std::os;
use std::rt::rtio;
use std::unstable::intrinsics;
use std::vec;

use io::{IoResult, retry};

#[cfg(windows)] use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
#[cfg(windows)] use std::ptr;
#[cfg(windows)] use std::str;

pub fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 {
    #[cfg(windows)] static eintr: int = 0; // doesn't matter
    #[cfg(not(windows))] static eintr: int = libc::EINTR as int;

    let origamt = data.len();
    let mut data = data.as_ptr();
    let mut amt = origamt;
    while amt > 0 {
        let mut ret;
        loop {
            ret = f(data, amt);
            if cfg!(windows) { break } // windows has no eintr
            // if we get an eintr, then try again
            if ret != -1 || os::errno() as int != eintr { break }
        }
        if ret == 0 {
            break
        } else if ret != -1 {
            amt -= ret as uint;
            data = unsafe { data.offset(ret as int) };
        } else {
            return ret;
        }
    }
    return (origamt - amt) as i64;
}

pub type fd_t = libc::c_int;

pub struct FileDesc {
    priv fd: fd_t,
    priv close_on_drop: bool,
}

impl FileDesc {
    /// Create a `FileDesc` from an open C file descriptor.
    ///
    /// The `FileDesc` will take ownership of the specified file descriptor and
    /// close it upon destruction if the `close_on_drop` flag is true, otherwise
    /// it will not close the file descriptor when this `FileDesc` is dropped.
    ///
    /// Note that all I/O operations done on this object will be *blocking*, but
    /// they do not require the runtime to be active.
    pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
        FileDesc { fd: fd, close_on_drop: close_on_drop }
    }

    // FIXME(#10465) these functions should not be public, but anything in
    //               native::io wanting to use them is forced to have all the
    //               rtio traits in scope
    pub fn inner_read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
        #[cfg(windows)] type rlen = libc::c_uint;
        #[cfg(not(windows))] type rlen = libc::size_t;
        let ret = retry(|| unsafe {
            libc::read(self.fd,
                       buf.as_ptr() as *mut libc::c_void,
                       buf.len() as rlen) as libc::c_int
        });
        if ret == 0 {
            Err(io::standard_error(io::EndOfFile))
        } else if ret < 0 {
            Err(super::last_error())
        } else {
            Ok(ret as uint)
        }
    }
    pub fn inner_write(&mut self, buf: &[u8]) -> Result<(), IoError> {
        #[cfg(windows)] type wlen = libc::c_uint;
        #[cfg(not(windows))] type wlen = libc::size_t;
        let ret = keep_going(buf, |buf, len| {
            unsafe {
                libc::write(self.fd, buf as *libc::c_void, len as wlen) as i64
            }
        });
        if ret < 0 {
            Err(super::last_error())
        } else {
            Ok(())
        }
    }

    pub fn fd(&self) -> fd_t { self.fd }
}

impl io::Reader for FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        match self.inner_read(buf) { Ok(n) => Some(n), Err(..) => None }
    }
}

impl io::Writer for FileDesc {
    fn write(&mut self, buf: &[u8]) {
        match self.inner_write(buf) {
            Ok(()) => {}
            Err(e) => { io::io_error::cond.raise(e); }
        }
    }
}

impl rtio::RtioFileStream for FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
        self.inner_read(buf).map(|i| i as int)
    }
    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
        self.inner_write(buf)
    }
    fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
        return os_pread(self.fd, buf.as_ptr(), buf.len(), offset);

        #[cfg(windows)]
        fn os_pread(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<int> {
            unsafe {
                let mut overlap: libc::OVERLAPPED = intrinsics::init();<commit_msg>native: Remove io_error usage<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Blocking posix-based file I/O

use std::c_str::CString;
use std::io::IoError;
use std::io;
use std::libc::{c_int, c_void};
use std::libc;
use std::os;
use std::rt::rtio;
use std::unstable::intrinsics;
use std::vec;

use io::{IoResult, retry};

#[cfg(windows)] use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
#[cfg(windows)] use std::ptr;
#[cfg(windows)] use std::str;

pub fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 {
    #[cfg(windows)] static eintr: int = 0; // doesn't matter
    #[cfg(not(windows))] static eintr: int = libc::EINTR as int;

    let origamt = data.len();
    let mut data = data.as_ptr();
    let mut amt = origamt;
    while amt > 0 {
        let mut ret;
        loop {
            ret = f(data, amt);
            if cfg!(windows) { break } // windows has no eintr
            // if we get an eintr, then try again
            if ret != -1 || os::errno() as int != eintr { break }
        }
        if ret == 0 {
            break
        } else if ret != -1 {
            amt -= ret as uint;
            data = unsafe { data.offset(ret as int) };
        } else {
            return ret;
        }
    }
    return (origamt - amt) as i64;
}

pub type fd_t = libc::c_int;

pub struct FileDesc {
    priv fd: fd_t,
    priv close_on_drop: bool,
}

impl FileDesc {
    /// Create a `FileDesc` from an open C file descriptor.
    ///
    /// The `FileDesc` will take ownership of the specified file descriptor and
    /// close it upon destruction if the `close_on_drop` flag is true, otherwise
    /// it will not close the file descriptor when this `FileDesc` is dropped.
    ///
    /// Note that all I/O operations done on this object will be *blocking*, but
    /// they do not require the runtime to be active.
    pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
        FileDesc { fd: fd, close_on_drop: close_on_drop }
    }

    // FIXME(#10465) these functions should not be public, but anything in
    //               native::io wanting to use them is forced to have all the
    //               rtio traits in scope
    pub fn inner_read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
        #[cfg(windows)] type rlen = libc::c_uint;
        #[cfg(not(windows))] type rlen = libc::size_t;
        let ret = retry(|| unsafe {
            libc::read(self.fd,
                       buf.as_ptr() as *mut libc::c_void,
                       buf.len() as rlen) as libc::c_int
        });
        if ret == 0 {
            Err(io::standard_error(io::EndOfFile))
        } else if ret < 0 {
            Err(super::last_error())
        } else {
            Ok(ret as uint)
        }
    }
    pub fn inner_write(&mut self, buf: &[u8]) -> Result<(), IoError> {
        #[cfg(windows)] type wlen = libc::c_uint;
        #[cfg(not(windows))] type wlen = libc::size_t;
        let ret = keep_going(buf, |buf, len| {
            unsafe {
                libc::write(self.fd, buf as *libc::c_void, len as wlen) as i64
            }
        });
        if ret < 0 {
            Err(super::last_error())
        } else {
            Ok(())
        }
    }

    pub fn fd(&self) -> fd_t { self.fd }
}

impl io::Reader for FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        self.inner_read(buf)
    }
}

impl io::Writer for FileDesc {
    fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
        self.inner_write(buf)
    }
}

impl rtio::RtioFileStream for FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
        self.inner_read(buf).map(|i| i as int)
    }
    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
        self.inner_write(buf)
    }
    fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
        return os_pread(self.fd, buf.as_ptr(), buf.len(), offset);

        #[cfg(windows)]
        fn os_pread(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<int> {
            unsafe {
                let mut overlap: libc::OVERLAPPED = intrinsics::init();
{'fraction_non_alphanumeric': 0.14534757027674874, 'fraction_numerical': 0.010677707561560253, 'mean_word_length': 2.1651724137931034, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6685399', 'n_tokens_mistral': 3099, 'n_tokens_neox': 3022, 'n_words': 940}