<commit_before>// Copyright (c) 2016 The Rouille developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use rustc_serialize::Decoder;
use rustc_serialize::Decodable;

use Request;

use std::io::Error as IoError;
use std::io::Read;
use std::mem;
use std::num;
use std::str::ParseBoolError;
use url::form_urlencoded;

/// Error that can happen when decoding POST data.
#[derive(Debug)]
pub enum PostError {
    /// The `Content-Type` header of the request indicates that it doesn't contain POST data.
    WrongContentType,

    /// Can't parse the body of the request because it was already extracted.
    BodyAlreadyExtracted,

    /// Could not read the body from the request. Also happens if the body is not valid UTF-8.
    IoError(IoError),

    /// A field is missing from the received data.
    MissingField(String),

    /// Failed to parse a `bool` field.
    WrongDataTypeBool(ParseBoolError),

    /// Failed to parse an integer field.
    WrongDataTypeInt(num::ParseIntError),

    /// Failed to parse a floating-point field.
    WrongDataTypeFloat(num::ParseFloatError),

    /// Failed to parse a string field.
    NotUtf8(String),
}

impl From<IoError> for PostError {
    #[inline]
    fn from(err: IoError) -> PostError {
        PostError::IoError(err)
    }
}

impl From<ParseBoolError> for PostError {
    #[inline]
    fn from(err: ParseBoolError) -> PostError {
        PostError::WrongDataTypeBool(err)
    }
}

impl From<num::ParseIntError> for PostError {
    #[inline]
    fn from(err: num::ParseIntError) -> PostError {
        PostError::WrongDataTypeInt(err)
    }
}

impl From<num::ParseFloatError> for PostError {
    #[inline]
    fn from(err: num::ParseFloatError) -> PostError {
        PostError::WrongDataTypeFloat(err)
    }
}

/// Attempts to decode the `POST` data received by the request into a struct.
///
/// The struct must implement the `Decodable` trait from `rustc_serialize`.
///
/// An error is returned if a field is missing, if the content type is not POST data, or if a field
/// cannot be parsed.
///
/// # Example
///
/// ```
/// extern crate rustc_serialize;
/// # #[macro_use] extern crate rouille;
/// # use rouille::{Request, Response};
/// # fn main() {}
///
/// fn route_handler(request: &Request) -> Response {
///     #[derive(RustcDecodable)]
///     struct FormData {
///         field1: u32,
///         field2: String,
///     }
///
///     let data: FormData = try_or_400!(rouille::input::get_post_input(&request));
///     Response::text(format!("field1's value is {}", data.field1))
/// }
/// ```
///
pub fn get_post_input<T>(request: &Request) -> Result<T, PostError> where T: Decodable {
    let data = try!(get_raw_post_input(request));
    let mut decoder = PostDecoder::Start(data);
    T::decode(&mut decoder)
}

/// Attempts to decode the `POST` data received by the request.
///
/// If successful, returns a list of fields and values.
///
/// Returns an error if the request's content-type is not related to POST data.
// TODO: handle multipart here as well
pub fn get_raw_post_input(request: &Request) -> Result<Vec<(String, String)>, PostError> {
    // TODO: slow
    if request.header("Content-Type") != Some("application/x-www-form-urlencoded".to_owned()) {
        return Err(PostError::WrongContentType);
    }

    let body = {
        // TODO: DDoSable server if body is too large?
        let mut out = Vec::new();       // TODO: with_capacity()?
        if let Some(mut b) = request.data() {
            try!(b.read_to_end(&mut out));
        } else {
            return Err(PostError::BodyAlreadyExtracted);
        }
        out
    };

    Ok(form_urlencoded::parse(&body))
}

enum PostDecoder {
    Empty,

    Start(Vec<(String, String)>),

    ExpectsStructMember(Vec<(String, String)>),

    ExpectsData(Vec<(String, String)>, String),
}

impl Decoder for PostDecoder {
    type Error = PostError;

    fn read_usize(&mut self) -> Result<usize, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_u64(&mut self) -> Result<u64, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_u32(&mut self) -> Result<u32, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_u16(&mut self) -> Result<u16, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_u8(&mut self) -> Result<u8, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_isize(&mut self) -> Result<isize, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_i64(&mut self) -> Result<i64, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_i32(&mut self) -> Result<i32, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_i16(&mut self) -> Result<i16, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_i8(&mut self) -> Result<i8, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_bool(&mut self) -> Result<bool, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_f64(&mut self) -> Result<f64, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_f32(&mut self) -> Result<f32, PostError> { Ok(try!(try!(self.read_str()).parse())) }

    fn read_char(&mut self) -> Result<char, PostError> {
        unimplemented!();
    }

    fn read_str(&mut self) -> Result<String, PostError> {
        match self {
            &mut PostDecoder::ExpectsData(ref data, ref field_name) => {
                let val = data.iter().find(|&&(ref key, _)| key == field_name)
                              .map(|&(_, ref value)| value);

                if let Some(val) = val {
                    Ok(val.clone())
                } else {
                    Err(PostError::MissingField(field_name.clone()))
                }
            },

            _ => panic!()
        }
    }

    fn read_nil(&mut self) -> Result<(), PostError> {
        unimplemented!();
    }

    fn read_enum<T, F>(&mut self, name: &str, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, PostError> where F: FnMut(&mut Self, usize) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_enum_variant_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, PostError> where F: FnMut(&mut Self, usize) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_enum_struct_variant_field<T, F>(&mut self, f_name: &str, f_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_struct<T, F>(&mut self, s_name: &str, len: usize, mut f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        let mut tmp = match mem::replace(self, PostDecoder::Empty) {
            PostDecoder::Start(data) => PostDecoder::ExpectsStructMember(data),
            _ => panic!()
        };

        f(&mut tmp)
    }

    fn read_struct_field<T, F>(&mut self, f_name: &str, f_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        let mut tmp = match mem::replace(self, PostDecoder::Empty) {
            PostDecoder::ExpectsStructMember(data) => PostDecoder::ExpectsData(data, f_name.to_owned()),
            _ => panic!()
        };

        let result = f(&mut tmp);

        match tmp {
            PostDecoder::ExpectsData(data, _) => mem::replace(self, PostDecoder::ExpectsStructMember(data)),
            _ => panic!()
        };

        result
    }

    fn read_tuple<T, F>(&mut self, len: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_tuple_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_tuple_struct<T, F>(&mut self, s_name: &str, len: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_option<T, F>(&mut self, mut f: F) -> Result<T, PostError> where F: FnMut(&mut Self, bool) -> Result<T, PostError> {
        let found = match self {
            &mut PostDecoder::ExpectsData(ref data, ref field_name) => {
                data.iter().find(|&&(ref key, _)| key == field_name).is_some()
            },
            _ => panic!()
        };

        f(self, found)
    }

    fn read_seq<T, F>(&mut self, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self, usize) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_map<T, F>(&mut self, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self, usize) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn error(&mut self, err: &str) -> PostError {
        unimplemented!();
    }
}
<commit_msg>Add decode_raw_post_input<commit_after>// Copyright (c) 2016 The Rouille developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use rustc_serialize::Decoder;
use rustc_serialize::Decodable;

use Request;

use std::io::Error as IoError;
use std::io::Read;
use std::mem;
use std::num;
use std::str::ParseBoolError;
use url::form_urlencoded;

/// Error that can happen when decoding POST data.
#[derive(Debug)]
pub enum PostError {
    /// The `Content-Type` header of the request indicates that it doesn't contain POST data.
    WrongContentType,

    /// Can't parse the body of the request because it was already extracted.
    BodyAlreadyExtracted,

    /// Could not read the body from the request. Also happens if the body is not valid UTF-8.
    IoError(IoError),

    /// A field is missing from the received data.
    MissingField(String),

    /// Failed to parse a `bool` field.
    WrongDataTypeBool(ParseBoolError),

    /// Failed to parse an integer field.
    WrongDataTypeInt(num::ParseIntError),

    /// Failed to parse a floating-point field.
    WrongDataTypeFloat(num::ParseFloatError),

    /// Failed to parse a string field.
    NotUtf8(String),
}

impl From<IoError> for PostError {
    #[inline]
    fn from(err: IoError) -> PostError {
        PostError::IoError(err)
    }
}

impl From<ParseBoolError> for PostError {
    #[inline]
    fn from(err: ParseBoolError) -> PostError {
        PostError::WrongDataTypeBool(err)
    }
}

impl From<num::ParseIntError> for PostError {
    #[inline]
    fn from(err: num::ParseIntError) -> PostError {
        PostError::WrongDataTypeInt(err)
    }
}

impl From<num::ParseFloatError> for PostError {
    #[inline]
    fn from(err: num::ParseFloatError) -> PostError {
        PostError::WrongDataTypeFloat(err)
    }
}

/// Attempts to decode the `POST` data received by the request into a struct.
///
/// The struct must implement the `Decodable` trait from `rustc_serialize`.
///
/// An error is returned if a field is missing, if the content type is not POST data, or if a field
/// cannot be parsed.
///
/// # Example
///
/// ```
/// extern crate rustc_serialize;
/// # #[macro_use] extern crate rouille;
/// # use rouille::{Request, Response};
/// # fn main() {}
///
/// fn route_handler(request: &Request) -> Response {
///     #[derive(RustcDecodable)]
///     struct FormData {
///         field1: u32,
///         field2: String,
///     }
///
///     let data: FormData = try_or_400!(rouille::input::get_post_input(&request));
///     Response::text(format!("field1's value is {}", data.field1))
/// }
/// ```
///
#[inline]
pub fn get_post_input<T>(request: &Request) -> Result<T, PostError> where T: Decodable {
    let data = try!(get_raw_post_input(request));
    decode_raw_post_input(data)
}

/// Takes raw post input (as obtained with `get_raw_post_input`) and decodes it into a struct.
///
/// Since you can only retreive the body of the request once, it will trigger an error to call
/// `get_post_input` and `get_raw_post_input` on the same request. This function is provided so
/// that you can do that.
///
/// > **Note**: The `get_post_input` function is just a shortcut for `get_raw_post_input` followed
/// > with `decode_raw_post_input`.
pub fn decode_raw_post_input<T>(data: Vec<(String, String)>) -> Result<T, PostError>
    where T: Decodable
{
    let mut decoder = PostDecoder::Start(data);
    T::decode(&mut decoder)
}

/// Attempts to decode the `POST` data received by the request.
///
/// If successful, returns a list of fields and values.
///
/// Returns an error if the request's content-type is not related to POST data.
// TODO: handle multipart here as well
pub fn get_raw_post_input(request: &Request) -> Result<Vec<(String, String)>, PostError> {
    // TODO: slow
    if request.header("Content-Type") != Some("application/x-www-form-urlencoded".to_owned()) {
        return Err(PostError::WrongContentType);
    }

    let body = {
        // TODO: DDoSable server if body is too large?
        let mut out = Vec::new();       // TODO: with_capacity()?
        if let Some(mut b) = request.data() {
            try!(b.read_to_end(&mut out));
        } else {
            return Err(PostError::BodyAlreadyExtracted);
        }
        out
    };

    Ok(form_urlencoded::parse(&body))
}

enum PostDecoder {
    Empty,

    Start(Vec<(String, String)>),

    ExpectsStructMember(Vec<(String, String)>),

    ExpectsData(Vec<(String, String)>, String),
}

impl Decoder for PostDecoder {
    type Error = PostError;

    fn read_usize(&mut self) -> Result<usize, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_u64(&mut self) -> Result<u64, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_u32(&mut self) -> Result<u32, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_u16(&mut self) -> Result<u16, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_u8(&mut self) -> Result<u8, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_isize(&mut self) -> Result<isize, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_i64(&mut self) -> Result<i64, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_i32(&mut self) -> Result<i32, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_i16(&mut self) -> Result<i16, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_i8(&mut self) -> Result<i8, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_bool(&mut self) -> Result<bool, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_f64(&mut self) -> Result<f64, PostError> { Ok(try!(try!(self.read_str()).parse())) }
    fn read_f32(&mut self) -> Result<f32, PostError> { Ok(try!(try!(self.read_str()).parse())) }

    fn read_char(&mut self) -> Result<char, PostError> {
        unimplemented!();
    }

    fn read_str(&mut self) -> Result<String, PostError> {
        match self {
            &mut PostDecoder::ExpectsData(ref data, ref field_name) => {
                let val = data.iter().find(|&&(ref key, _)| key == field_name)
                              .map(|&(_, ref value)| value);

                if let Some(val) = val {
                    Ok(val.clone())
                } else {
                    Err(PostError::MissingField(field_name.clone()))
                }
            },

            _ => panic!()
        }
    }

    fn read_nil(&mut self) -> Result<(), PostError> {
        unimplemented!();
    }

    fn read_enum<T, F>(&mut self, name: &str, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, PostError> where F: FnMut(&mut Self, usize) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_enum_variant_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, PostError> where F: FnMut(&mut Self, usize) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_enum_struct_variant_field<T, F>(&mut self, f_name: &str, f_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_struct<T, F>(&mut self, s_name: &str, len: usize, mut f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        let mut tmp = match mem::replace(self, PostDecoder::Empty) {
            PostDecoder::Start(data) => PostDecoder::ExpectsStructMember(data),
            _ => panic!()
        };

        f(&mut tmp)
    }

    fn read_struct_field<T, F>(&mut self, f_name: &str, f_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        let mut tmp = match mem::replace(self, PostDecoder::Empty) {
            PostDecoder::ExpectsStructMember(data) => PostDecoder::ExpectsData(data, f_name.to_owned()),
            _ => panic!()
        };

        let result = f(&mut tmp);

        match tmp {
            PostDecoder::ExpectsData(data, _) => mem::replace(self, PostDecoder::ExpectsStructMember(data)),
            _ => panic!()
        };

        result
    }

    fn read_tuple<T, F>(&mut self, len: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_tuple_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_tuple_struct<T, F>(&mut self, s_name: &str, len: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_option<T, F>(&mut self, mut f: F) -> Result<T, PostError> where F: FnMut(&mut Self, bool) -> Result<T, PostError> {
        let found = match self {
            &mut PostDecoder::ExpectsData(ref data, ref field_name) => {
                data.iter().find(|&&(ref key, _)| key == field_name).is_some()
            },
            _ => panic!()
        };

        f(self, found)
    }

    fn read_seq<T, F>(&mut self, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self, usize) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_map<T, F>(&mut self, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self, usize) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) -> Result<T, PostError> where F: FnOnce(&mut Self) -> Result<T, PostError> {
        unimplemented!();
    }

    fn error(&mut self, err: &str) -> PostError {
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>use scaly::memory::bucket::Bucket;
use scaly::memory::bucket::Bucket::Heap;
use scaly::memory::bucket::Bucket::Stack;
use scaly::memory::page::Page;
use scaly::memory::page::PAGE_SIZE;
use scaly::memory::pool::Pool;
use std::mem::size_of;
use std::usize::MAX;

pub struct HeapBucket {
    pool: *mut Pool,
    map: usize,
}

impl HeapBucket {
    pub fn create(pool: *mut Pool) -> *mut HeapBucket {
        unsafe {
            let page = Bucket::allocate_bucket();
            let bucket = (*page).allocate(Bucket::Heap(HeapBucket {
                pool: pool,
                map: MAX,
            }));
            //println!("Bucket object:{:X}", bucket as usize);
            let heap_bucket = match *bucket {
                Heap(ref mut h) => h,
                Stack(_) => panic!("Oops, we have a heap bucket which cannot happen."),
            };
            (*pool).current_bucket = heap_bucket;
            let heap_bucket_pointer = heap_bucket as *const HeapBucket as *mut HeapBucket;
            //println!("Stack bucket object:{:X}", stack_bucket_pointer as usize);
            heap_bucket_pointer
        }
    }

    pub fn allocate_page(&mut self) -> *mut Page {
        if self.map == MAX {
            self.map = self.map - 1;
            let page = Page::get(self as *const HeapBucket as usize);
            println!("HeapBucket allocated first page:{:X}", page as usize);
            return page;
        }

        if self.map == 0 {
            unsafe {
                //println!("self.pool: {:X}", self.pool as usize);
                if self as *mut HeapBucket == (*self.pool).current_bucket {
                    //println!("Let the pool allocate a new one.");
                    (*self.pool).allocate_bucket();
                }
                return (*(*self.pool).current_bucket).allocate_page();
            }
        }

        let position = HeapBucket::find_least_position(self.map);
        println!("HeapBucket position: {}", position);
        self.map = self.map & !(1 << size_of::<usize>() * 8 - position);

        let page = (Page::get(self as *const HeapBucket as usize) as usize + position * PAGE_SIZE)
            as *mut Page;
        println!("HeapBucket allocated page:{:X}", page as usize);
        unsafe { (*page).reset() }
        page
    }

    pub fn deallocate_page(&mut self, page: &Page) {
        let base_page = Page::get(self as *const HeapBucket as usize) as usize;
        println!("HeapBucket about to de-allocate a page:{:X}", base_page);
        let distance = page as *const Page as usize - base_page;
        let position = distance / PAGE_SIZE;
        println!("Position to de-allocate: {}", position);
        if position > size_of::<usize>() * 8 - 1 {
            panic!("Position invalid for page {:X}", base_page)
        };
        let bit = 1 << size_of::<usize>() * 8 - position - 1;
        println!("Bit: {:X}", bit);
        if self.map & bit != 0 {
            panic!("Page {:X} was not allocated!", base_page)
        }
        self.map = self.map & bit;
    }

    fn find_least_position(n: usize) -> usize {
        match size_of::<usize>() * 8 {
            64 => HeapBucket::find_least_position_64(n),
            32 => HeapBucket::find_least_position_32(n),
            _ => panic!(
                "Scaly currently does not support {}bit architecture.",
                size_of::<usize>() * 8
            ),
        }
    }

    // from http://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers
    fn find_least_position_64(n: usize) -> usize {
        static NUMBERS: &'static [usize] = &[
            0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20,
            55, 30, 34, 11, 43, 14, 22, 4, 62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10,
            13, 21, 56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63,
        ];

        let n = n | n >> 1;
        let n = n | n >> 2;
        let n = n | n >> 4;
        let n = n | n >> 8;
        let n = n | n >> 16;
        let n = n | n >> 32;

        let product = n as u128 * 0x03f6eaf2cd271461;

        let log = NUMBERS[product as usize >> 58];
        size_of::<usize>() * 8 - log
    }

    // from http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
    fn find_least_position_32(n: usize) -> usize {
        static NUMBERS: &'static [usize] = &[
            0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24,
            7, 19, 27, 23, 6, 26, 5, 4, 31,
        ];

        let n = n | n >> 1;
        let n = n | n >> 2;
        let n = n | n >> 4;
        let n = n | n >> 8;
        let n = n | n >> 16;

        let log = NUMBERS[(n * 0x07C4ACDD) >> 27];
        size_of::<usize>() * 8 - log
    }
}

#[test]
fn test_heapbucket() {
    unsafe {
        let mut pool = Pool::create();
        //println!("pool: {:X}", &pool as *const Pool as usize);
        let bucket = HeapBucket::create(&mut pool);
        let page0 = (*bucket).allocate_page();
        let page1 = (*bucket).allocate_page();
        let page2 = (*bucket).allocate_page();
        let page3 = (*bucket).allocate_page();
        let page4 = (*bucket).allocate_page();
        let page5 = (*bucket).allocate_page();
        let page6 = (*bucket).allocate_page();
        let page7 = (*bucket).allocate_page();
        let page8 = (*bucket).allocate_page();
        let page9 = (*bucket).allocate_page();
        (*page1).forget();
        (*page5).forget();
        (*page4).forget();
        (*page3).forget();
        (*page8).forget();
        (*page0).forget();
        (*page7).forget();
        (*page6).forget();
        (*page2).forget();
        (*page9).forget();
        assert_eq!((*bucket).map, 0);
    }
}
<commit_msg>Fixed HeapBucket de-allocation<commit_after>use scaly::memory::bucket::Bucket;
use scaly::memory::bucket::Bucket::Heap;
use scaly::memory::bucket::Bucket::Stack;
use scaly::memory::bucket::BUCKET_PAGES;
use scaly::memory::page::Page;
use scaly::memory::page::PAGE_SIZE;
use scaly::memory::pool::Pool;
use std::usize::MAX;

pub struct HeapBucket {
    pool: *mut Pool,
    map: usize,
}

impl HeapBucket {
    pub fn create(pool: *mut Pool) -> *mut HeapBucket {
        unsafe {
            let page = Bucket::allocate_bucket();
            let bucket = (*page).allocate(Bucket::Heap(HeapBucket {
                pool: pool,
                map: MAX,
            }));
            //println!("Bucket object:{:X}", bucket as usize);
            let heap_bucket = match *bucket {
                Heap(ref mut h) => h,
                Stack(_) => panic!("Oops, we have a heap bucket which cannot happen."),
            };
            (*pool).current_bucket = heap_bucket;
            let heap_bucket_pointer = heap_bucket as *const HeapBucket as *mut HeapBucket;
            //println!("Stack bucket object:{:X}", stack_bucket_pointer as usize);
            heap_bucket_pointer
        }
    }

    pub fn allocate_page(&mut self) -> *mut Page {
        if self.map == MAX {
            self.map = self.map - 1;
            let page = Page::get(self as *const HeapBucket as usize);
            // println!("HeapBucket allocated first page:{:X}", page as usize);
            return page;
        }

        if self.map == 0 {
            unsafe {
                // println!("self.pool: {:X}", self.pool as usize);
                if self as *mut HeapBucket == (*self.pool).current_bucket {
                    //println!("Let the pool allocate a new one.");
                    (*self.pool).allocate_bucket();
                }
                return (*(*self.pool).current_bucket).allocate_page();
            }
        }

        let position = HeapBucket::find_least_position(self.map);
        // println!("HeapBucket position: {}", position);
        let bit = 1 << (BUCKET_PAGES - position);
        // println!("Bit for allocation: {:X}", bit);
        self.map = self.map & !bit;

        let page = (Page::get(self as *const HeapBucket as usize) as usize + position * PAGE_SIZE)
            as *mut Page;
        // println!("HeapBucket allocated page:{:X}", page as usize);
        unsafe { (*page).reset() }
        page
    }

    pub fn deallocate_page(&mut self, page: &Page) {
        let base_page = Page::get(self as *const HeapBucket as usize) as usize;
        // println!("HeapBucket about to de-allocate a page:{:X}", base_page);
        let distance = page as *const Page as usize - base_page;
        let position = distance / PAGE_SIZE;
        // println!("Position to de-allocate: {}", position);
        if position > BUCKET_PAGES - 1 {
            panic!("Position invalid for page {:X}", base_page)
        };
        let bit = 1 << (BUCKET_PAGES - position);
        // println!("Bit for deallocation: {:X}", bit);
        if self.map & bit != 0 {
            panic!("Page {:X} was not allocated!", base_page)
        }
        // println!("self.map before deallocation: {:X}", self.map);
        self.map = self.map | bit;
        // println!("self.map after deallocation: {:X}", self.map);
    }

    fn find_least_position(n: usize) -> usize {
        match BUCKET_PAGES {
            64 => HeapBucket::find_least_position_64(n),
            32 => HeapBucket::find_least_position_32(n),
            _ => panic!(
                "Scaly currently does not support {}bit architecture.",
                BUCKET_PAGES
            ),
        }
    }

    // from http://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers
    fn find_least_position_64(n: usize) -> usize {
        static NUMBERS: &'static [usize] = &[
            0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20,
            55, 30, 34, 11, 43, 14, 22, 4, 62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10,
            13, 21, 56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63,
        ];

        let n = n | n >> 1;
        let n = n | n >> 2;
        let n = n | n >> 4;
        let n = n | n >> 8;
        let n = n | n >> 16;
        let n = n | n >> 32;

        let product = n as u128 * 0x03f6eaf2cd271461;

        let log = NUMBERS[product as usize >> 58];
        // println!("Log: {}", log);
        BUCKET_PAGES - log
    }

    // from http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
    fn find_least_position_32(n: usize) -> usize {
        static NUMBERS: &'static [usize] = &[
            0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24,
            7, 19, 27, 23, 6, 26, 5, 4, 31,
        ];

        let n = n | n >> 1;
        let n = n | n >> 2;
        let n = n | n >> 4;
        let n = n | n >> 8;
        let n = n | n >> 16;

        let log = NUMBERS[(n * 0x07C4ACDD) >> 27];
        BUCKET_PAGES - log
    }
}

#[test]
fn test_heapbucket() {
    unsafe {
        let mut pool = Pool::create();
        //println!("pool: {:X}", &pool as *const Pool as usize);
        let bucket = HeapBucket::create(&mut pool);
        let _page00 = (*bucket).allocate_page();
        let _page01 = (*bucket).allocate_page();
        let page02 = (*bucket).allocate_page();
        let page03 = (*bucket).allocate_page();
        let page04 = (*bucket).allocate_page();
        let page05 = (*bucket).allocate_page();
        let _page06 = (*bucket).allocate_page();
        let _page07 = (*bucket).allocate_page();
        let _page08 = (*bucket).allocate_page();
        let _page09 = (*bucket).allocate_page();
        let _page10 = (*bucket).allocate_page();
        let _page11 = (*bucket).allocate_page();
        let _page12 = (*bucket).allocate_page();
        let _page13 = (*bucket).allocate_page();
        let _page14 = (*bucket).allocate_page();
        let _page15 = (*bucket).allocate_page();
        let page16 = (*bucket).allocate_page();
        let _page17 = (*bucket).allocate_page();
        let page18 = (*bucket).allocate_page();
        let _page19 = (*bucket).allocate_page();
        let _page20 = (*bucket).allocate_page();
        let _page21 = (*bucket).allocate_page();
        let _page22 = (*bucket).allocate_page();
        let _page23 = (*bucket).allocate_page();
        let _page24 = (*bucket).allocate_page();
        let _page25 = (*bucket).allocate_page();
        let _page26 = (*bucket).allocate_page();
        let _page27 = (*bucket).allocate_page();
        let _page28 = (*bucket).allocate_page();
        let _page29 = (*bucket).allocate_page();
        let _page30 = (*bucket).allocate_page();
        let _page31 = (*bucket).allocate_page();
        let _page32 = (*bucket).allocate_page();
        let _page33 = (*bucket).allocate_page();
        let _page34 = (*bucket).allocate_page();
        let _page35 = (*bucket).allocate_page();
        let _page36 = (*bucket).allocate_page();
        let _page37 = (*bucket).allocate_page();
        let _page38 = (*bucket).allocate_page();
        let _page39 = (*bucket).allocate_page();
        let _page40 = (*bucket).allocate_page();
        let _page41 = (*bucket).allocate_page();
        let _page42 = (*bucket).allocate_page();
        let _page43 = (*bucket).allocate_page();
        let _page44 = (*bucket).allocate_page();
        let _page45 = (*bucket).allocate_page();
        let _page46 = (*bucket).allocate_page();
        let _page47 = (*bucket).allocate_page();
        let _page48 = (*bucket).allocate_page();
        let _page49 = (*bucket).allocate_page();
        let _page50 = (*bucket).allocate_page();
        let _page51 = (*bucket).allocate_page();
        let _page52 = (*bucket).allocate_page();
        let _page53 = (*bucket).allocate_page();
        let _page54 = (*bucket).allocate_page();
        let _page55 = (*bucket).allocate_page();
        let _page56 = (*bucket).allocate_page();
        let _page57 = (*bucket).allocate_page();
        let _page58 = (*bucket).allocate_page();
        let _page59 = (*bucket).allocate_page();
        let _page60 = (*bucket).allocate_page();
        let _page61 = (*bucket).allocate_page();
        let page62 = (*bucket).allocate_page();
        let page63 = (*bucket).allocate_page();
        assert_eq!((*bucket).map, 0);
        (*bucket).deallocate_page(&*page62);
        let page62a = (*bucket).allocate_page();
        assert_eq!(page62, page62a);
        assert_eq!((*bucket).map, 0);
        (*bucket).deallocate_page(&*page02);
        (*bucket).deallocate_page(&*page03);
        (*bucket).deallocate_page(&*page04);
        (*bucket).deallocate_page(&*page05);
        let page02a = (*bucket).allocate_page();
        let page03a = (*bucket).allocate_page();
        let page04a = (*bucket).allocate_page();
        let page05a = (*bucket).allocate_page();
        assert_eq!(page02, page02a);
        assert_eq!(page03, page03a);
        assert_eq!(page04, page04a);
        assert_eq!(page05, page05a);
        assert_eq!((*bucket).map, 0);
        (*bucket).deallocate_page(&*page16);
        (*bucket).deallocate_page(&*page18);
        let page16a = (*bucket).allocate_page();
        let page18a = (*bucket).allocate_page();
        assert_eq!(page16, page16a);
        assert_eq!(page18, page18a);
        assert_eq!((*bucket).map, 0);
        (*bucket).deallocate_page(&*page63);
        let page63a = (*bucket).allocate_page();
        assert_eq!(page63, page63a);
        assert_eq!((*bucket).map, 0);
    }
}
<|endoftext|>


<commit_before>/*!
 * Bounded package merge algorithm, based on the paper
 * "A Fast and Space-Economical Algorithm for Length-Limited Coding
 * Jyrki Katajainen, Alistair Moffat, Andrew Turpin".
 */

use std::mem;
use std::ptr::{null, null_mut};

use libc::{c_void, size_t};
use libc::funcs::c95::stdlib::{free, malloc};

/// Nodes forming chains. Also used to represent leaves.
struct Node {
    /// Total weight (symbol count) of this chain.
    weight: usize,
    /// Previous node(s) of this chain, or 0 if none.
    tail: *mut Node,
    /// Leaf symbol index, or number of leaves before this chain.
    count: i32,
    /// Tracking for garbage collection.
    in_use: bool,
}

/// Memory pool for nodes.
struct NodePool {
    /// The pool.
    nodes: *mut Node,
    /// Pointer to a possibly free node in the pool.
    next: *mut Node,
    /// Size of the memory pool.
    size: u32,
}

/// Initializes a chain node with the given values and marks it as in use.
unsafe fn init_node(weight: usize, count: i32, tail: *mut Node, node: *mut Node) {
    (*node).weight = weight;
    (*node).count = count;
    (*node).tail = tail;
    (*node).in_use = true;
}

/**
 * Finds a free location in the memory pool. Performs garbage collection if needed.
 * lists: If given, used to mark in-use nodes during garbage collection.
 * maxbits: Size of lists.
 * pool: Memory pool to get free node from.
 */
unsafe fn get_free_node(lists: *const *mut *mut Node, maxbits: i32, pool: *mut NodePool) -> *mut Node {
    loop {
        if (*pool).next >= (*pool).nodes.offset((*pool).size as isize) {
            // Garbage collection
            for i in 0..(*pool).size {
                (*(*pool).nodes.offset(i as isize)).in_use = false;
            }
            if lists != null_mut() {
                for i in 0..maxbits*2 {
                    let mut node = *(*lists.offset((i / 2) as isize)).offset((i % 2) as isize);
                    while node != null_mut() {
                        (*node).in_use = true;
                        node = (*node).tail;
                    }
                }
            }
            (*pool).next = (*pool).nodes;
        }
        if (*(*pool).next).in_use {
            break;
        }
        (*pool).next = (*pool).next.offset(1);
    }
    let free_node = (*pool).next;
    (*pool).next = (*pool).next.offset(1);
    free_node
}

/**
 * Performs a Boundary Package-Merge step. Puts a new chain in the given list. The
 * new chain is, depending on the weights, a leaf or a combination of two chains
 * from the previous list.
 * lists: The lists of chains.
 * maxbits: Number of lists.
 * leaves: The leaves, one per symbol.
 * numsymbols: Number of leaves.
 * pool: the node memory pool.
 * index: The index of the list in which a new chain or leaf is required.
 * final: Whether this is the last time this function is called. If it is then it
 *   is no more needed to recursively call self.
 */
unsafe fn boundary_pm(lists: *const *mut *mut Node, maxbits: i32, leaves: *const Node, numsymbols: i32, pool: *mut NodePool,
                      index: i32, is_final: bool) {
    let lastcount = (**(*lists.offset(index as isize)).offset(1)).count; // Count of last chain of list.

    if index == 0 && lastcount >= numsymbols {
        return;
    }

    let newchain = get_free_node(lists, maxbits, pool);
    let oldchain = *(*lists.offset(index as isize)).offset(1);

    // These are set up before the recursive calls below, so that there is a list
    // pointing to the new node, to let the garbage collection know it's in use.
    *(*lists.offset(index as isize)).offset(0) = oldchain;
    *(*lists.offset(index as isize)).offset(1) = newchain;

    if index == 0 {
        //New leaf node in list 0.
        init_node((*leaves.offset(lastcount as isize)).weight, lastcount + 1, null_mut(), newchain);
    } else {
        let sum = (**(*lists.offset((index - 1) as isize)).offset(0)).weight + (**(*lists.offset((index - 1) as isize)).offset(0)).weight;
        if lastcount < numsymbols && sum > (*leaves.offset(lastcount as isize)).weight {
            // New leaf inserted in list, so count is incremented.
            init_node((*leaves.offset(lastcount as isize)).weight, lastcount + 1, (*oldchain).tail, newchain);
        } else {
            init_node(sum, lastcount, *(*lists.offset((index - 1) as isize)).offset(1), newchain);
            if !is_final {
                // Two lookahead chains of previous list used up, create new ones.
                boundary_pm(lists, maxbits, leaves, numsymbols, pool, index - 1, false);
                boundary_pm(lists, maxbits, leaves, numsymbols, pool, index - 1, false);
            }
        }
    }
}

/// Initializes each list with as lookahead chains the two leaves with lowest weights.
unsafe fn init_lists(pool: *mut NodePool, leaves: *const Node, maxbits: i32, lists: *const *mut *mut Node) {
    let node0 = get_free_node(null(), maxbits, pool);
    let node1 = get_free_node(null(), maxbits, pool);
    init_node((*leaves.offset(0)).weight, 1, null_mut(), node0);
    init_node((*leaves.offset(1)).weight, 2, null_mut(), node1);
    for i in 0..maxbits {
        *(*lists.offset(i as isize)).offset(0) = node0;
        *(*lists.offset(i as isize)).offset(1) = node1;
    }
}

/**
 * Converts result of boundary package-merge to the bitlengths. The result in the
 * last chain of the last list contains the amount of active leaves in each list.
 * chain: Chain to extract the bit length from (last chain from last list).
 */
unsafe fn extract_bit_lengths(chain: *const Node, leaves: *const Node, bitlengths: *mut u32) {
    let mut node = chain;
    while node != null() {
        for i in 0..(*node).count {
            *bitlengths.offset((*leaves.offset(i as isize)).count as isize) = *bitlengths.offset((*leaves.offset(i as isize)).count as isize) + 1;
        }
        node = (*node).tail;
    }
}

/// Comparator for sorting the leaves. Has the function signature for qsort.
extern fn leaf_comparator(a: *const c_void, b: *const c_void) -> i32 {
    unsafe {
        let node_a: *const Node = a as *const Node;
        let node_b: *const Node = b as *const Node;
        (*node_a).weight as i32 - (*node_b).weight as i32
    }
}

#[link(name="c")]
extern {
    fn qsort(base: *mut c_void, nmemb: size_t, size: size_t, compar: extern fn(*const c_void, *const c_void) -> i32);
}

pub unsafe fn length_limited_code_lengths(frequencies: *const usize, n: i32, maxbits: i32, bitlengths: *mut u32) -> bool {
    // Amount of symbols with frequency > 0.
    let mut numsymbols = 0;

    // One leaf per symbol. Only numsymbols leaves will be used.
    let leaves: *mut Node = malloc((n as usize * mem::size_of::<Node>()) as size_t) as *mut Node;

    // Initialize all bitlengths at 0.
    for i in 0..n {
        *bitlengths.offset(i as isize) = 0;
    }

    // Count used symbols and place them in the leaves.
    for i in 0..n {
        if *frequencies.offset(i as isize) != 0 {
            (*leaves.offset(numsymbols)).weight = *frequencies.offset(i as isize);
            (*leaves.offset(numsymbols)).count = i;
            numsymbols = numsymbols + 1;
        }
    }

    // Check special cases and error conditions.
    if (1 << maxbits) < numsymbols {
        free(leaves as *mut c_void);
        return true; // Error, too few maxbits to represent symbols.
    }
    if numsymbols == 0 {
        free(leaves as *mut c_void);
        return false; // No symbols at all. OK.
    }
    if numsymbols == 1 {
        *bitlengths.offset((*leaves.offset(0)).count as isize) = 1;
        free(leaves as *mut c_void);
        return false; // Only one symbol, give it bitlength 1, not 0. OK.
    }

    // Sort the leaves from lightest to heaviest.
    qsort(leaves as *mut c_void, numsymbols as size_t, mem::size_of::<Node>() as size_t, leaf_comparator);

    // Initialize node memory pool.
    let pool_size = 2 * maxbits * (maxbits + 1);
    let pool_nodes = malloc((pool_size as usize * mem::size_of::<Node>()) as size_t) as *mut Node;
    let mut pool = NodePool { size: pool_size as u32, nodes: pool_nodes, next: pool_nodes };
    for i in 0..pool.size {
        (*pool.nodes.offset(i as isize)).in_use = false;
    }

    // Array of lists of chains. Each list requires only two lookahead chains at
    // a time, so each list is a array of two Node*'s.
    let lists: *const *mut *mut Node = malloc((maxbits as usize * mem::size_of::<*const *const Node>()) as size_t) as *const *mut *mut Node;
    init_lists(&mut pool, leaves, maxbits, lists);

    // In the last list, 2 * numsymbols - 2 active chains need to be created. Two
    // are already created in the initialization. Each BoundaryPM run creates one.
    let num_boundary_pm_runs = 2 * numsymbols - 4;
    for i in 0..num_boundary_pm_runs {
        let is_final = i == num_boundary_pm_runs - 1;
        boundary_pm(lists, maxbits, leaves, numsymbols as i32, &mut pool, maxbits - 1, is_final);
    }

    extract_bit_lengths(*(*lists.offset(maxbits as isize - 1)).offset(1), leaves, bitlengths);

    free(lists as *mut c_void);
    free(leaves as *mut c_void);
    free(pool.nodes as *mut c_void);
    false
}

#[cfg(test)]
mod tests {
    use std::mem::size_of;
    use libc::{c_void, size_t};

    use super::qsort;

    extern fn comparator(a: *const c_void, b: *const c_void) -> i32 {
        unsafe {
            *(a as *const i32) - *(b as *const i32)
        }
    }

    #[test]
    fn test_qsort() {
        unsafe {
            let mut a: [i32; 5] = [3, 2, 4, 1, 5];
            qsort(a.as_mut_ptr() as *mut c_void, a.len() as size_t, size_of::<i32>() as size_t, comparator);
            assert_eq!(a, [1, 2, 3, 4, 5]);
        }
    }
}
<commit_msg>cleanup<commit_after>/*!
 * Bounded package merge algorithm, based on the paper
 * "A Fast and Space-Economical Algorithm for Length-Limited Coding
 * Jyrki Katajainen, Alistair Moffat, Andrew Turpin".
 */

use std::mem;
use std::ptr::{null, null_mut};

use libc::{c_void, size_t};
use libc::funcs::c95::stdlib::{free, malloc};

/// Nodes forming chains. Also used to represent leaves.
struct Node {
    /// Total weight (symbol count) of this chain.
    weight: usize,
    /// Previous node(s) of this chain, or 0 if none.
    tail: *mut Node,
    /// Leaf symbol index, or number of leaves before this chain.
    count: i32,
    /// Tracking for garbage collection.
    in_use: bool,
}

/// Memory pool for nodes.
struct NodePool {
    /// The pool.
    nodes: *mut Node,
    /// Pointer to a possibly free node in the pool.
    next: *mut Node,
    /// Size of the memory pool.
    size: u32,
}

/// Initializes a chain node with the given values and marks it as in use.
unsafe fn init_node(weight: usize, count: i32, tail: *mut Node, node: *mut Node) {
    (*node).weight = weight;
    (*node).count = count;
    (*node).tail = tail;
    (*node).in_use = true;
}

/**
 * Finds a free location in the memory pool. Performs garbage collection if needed.
 * lists: If given, used to mark in-use nodes during garbage collection.
 * maxbits: Size of lists.
 * pool: Memory pool to get free node from.
 */
unsafe fn get_free_node(lists: *const *mut *mut Node, maxbits: i32, pool: *mut NodePool) -> *mut Node {
    loop {
        if (*pool).next >= (*pool).nodes.offset((*pool).size as isize) {
            // Garbage collection
            for i in 0..(*pool).size {
                (*(*pool).nodes.offset(i as isize)).in_use = false;
            }
            if !lists.is_null() {
                for i in 0..maxbits*2 {
                    let mut node = *(*lists.offset((i / 2) as isize)).offset((i % 2) as isize);
                    while !node.is_null() {
                        (*node).in_use = true;
                        node = (*node).tail;
                    }
                }
            }
            (*pool).next = (*pool).nodes;
        }
        if (*(*pool).next).in_use {
            break;
        }
        (*pool).next = (*pool).next.offset(1);
    }
    let free_node = (*pool).next;
    (*pool).next = (*pool).next.offset(1);
    free_node
}

/**
 * Performs a Boundary Package-Merge step. Puts a new chain in the given list. The
 * new chain is, depending on the weights, a leaf or a combination of two chains
 * from the previous list.
 * lists: The lists of chains.
 * maxbits: Number of lists.
 * leaves: The leaves, one per symbol.
 * numsymbols: Number of leaves.
 * pool: the node memory pool.
 * index: The index of the list in which a new chain or leaf is required.
 * final: Whether this is the last time this function is called. If it is then it
 *   is no more needed to recursively call self.
 */
unsafe fn boundary_pm(lists: *const *mut *mut Node, maxbits: i32, leaves: *const Node, numsymbols: i32, pool: *mut NodePool,
                      index: i32, is_final: bool) {
    let lastcount = (**(*lists.offset(index as isize)).offset(1)).count; // Count of last chain of list.

    if index == 0 && lastcount >= numsymbols {
        return;
    }

    let newchain = get_free_node(lists, maxbits, pool);
    let oldchain = *(*lists.offset(index as isize)).offset(1);

    // These are set up before the recursive calls below, so that there is a list
    // pointing to the new node, to let the garbage collection know it's in use.
    *(*lists.offset(index as isize)).offset(0) = oldchain;
    *(*lists.offset(index as isize)).offset(1) = newchain;

    if index == 0 {
        //New leaf node in list 0.
        init_node((*leaves.offset(lastcount as isize)).weight, lastcount + 1, null_mut(), newchain);
    } else {
        let sum = (**(*lists.offset((index - 1) as isize)).offset(0)).weight + (**(*lists.offset((index - 1) as isize)).offset(0)).weight;
        if lastcount < numsymbols && sum > (*leaves.offset(lastcount as isize)).weight {
            // New leaf inserted in list, so count is incremented.
            init_node((*leaves.offset(lastcount as isize)).weight, lastcount + 1, (*oldchain).tail, newchain);
        } else {
            init_node(sum, lastcount, *(*lists.offset((index - 1) as isize)).offset(1), newchain);
            if !is_final {
                // Two lookahead chains of previous list used up, create new ones.
                boundary_pm(lists, maxbits, leaves, numsymbols, pool, index - 1, false);
                boundary_pm(lists, maxbits, leaves, numsymbols, pool, index - 1, false);
            }
        }
    }
}

/// Initializes each list with as lookahead chains the two leaves with lowest weights.
unsafe fn init_lists(pool: *mut NodePool, leaves: *const Node, maxbits: i32, lists: *const *mut *mut Node) {
    let node0 = get_free_node(null(), maxbits, pool);
    let node1 = get_free_node(null(), maxbits, pool);
    init_node((*leaves.offset(0)).weight, 1, null_mut(), node0);
    init_node((*leaves.offset(1)).weight, 2, null_mut(), node1);
    for i in 0..maxbits {
        *(*lists.offset(i as isize)).offset(0) = node0;
        *(*lists.offset(i as isize)).offset(1) = node1;
    }
}

/**
 * Converts result of boundary package-merge to the bitlengths. The result in the
 * last chain of the last list contains the amount of active leaves in each list.
 * chain: Chain to extract the bit length from (last chain from last list).
 */
unsafe fn extract_bit_lengths(chain: *const Node, leaves: *const Node, bitlengths: *mut u32) {
    let mut node = chain;
    while node != null() {
        for i in 0..(*node).count {
            *bitlengths.offset((*leaves.offset(i as isize)).count as isize) = *bitlengths.offset((*leaves.offset(i as isize)).count as isize) + 1;
        }
        node = (*node).tail;
    }
}

/// Comparator for sorting the leaves. Has the function signature for qsort.
extern fn leaf_comparator(a: *const c_void, b: *const c_void) -> i32 {
    unsafe {
        let node_a: *const Node = a as *const Node;
        let node_b: *const Node = b as *const Node;
        (*node_a).weight as i32 - (*node_b).weight as i32
    }
}

#[link(name="c")]
extern {
    fn qsort(base: *mut c_void, nmemb: size_t, size: size_t, compar: extern fn(*const c_void, *const c_void) -> i32);
}

pub unsafe fn length_limited_code_lengths(frequencies: *const usize, n: i32, maxbits: i32, bitlengths: *mut u32) -> bool {
    // Amount of symbols with frequency > 0.
    let mut numsymbols = 0;

    // One leaf per symbol. Only numsymbols leaves will be used.
    let leaves: *mut Node = malloc((n as usize * mem::size_of::<Node>()) as size_t) as *mut Node;

    // Initialize all bitlengths at 0.
    for i in 0..n {
        *bitlengths.offset(i as isize) = 0;
    }

    // Count used symbols and place them in the leaves.
    for i in 0..n {
        if *frequencies.offset(i as isize) != 0 {
            (*leaves.offset(numsymbols)).weight = *frequencies.offset(i as isize);
            (*leaves.offset(numsymbols)).count = i;
            numsymbols = numsymbols + 1;
        }
    }

    // Check special cases and error conditions.
    if (1 << maxbits) < numsymbols {
        free(leaves as *mut c_void);
        return true; // Error, too few maxbits to represent symbols.
    }
    if numsymbols == 0 {
        free(leaves as *mut c_void);
        return false; // No symbols at all. OK.
    }
    if numsymbols == 1 {
        *bitlengths.offset((*leaves.offset(0)).count as isize) = 1;
        free(leaves as *mut c_void);
        return false; // Only one symbol, give it bitlength 1, not 0. OK.
    }

    // Sort the leaves from lightest to heaviest.
    qsort(leaves as *mut c_void, numsymbols as size_t, mem::size_of::<Node>() as size_t, leaf_comparator);

    // Initialize node memory pool.
    let pool_size = 2 * maxbits * (maxbits + 1);
    let pool_nodes = malloc((pool_size as usize * mem::size_of::<Node>()) as size_t) as *mut Node;
    let mut pool = NodePool { size: pool_size as u32, nodes: pool_nodes, next: pool_nodes };
    for i in 0..pool.size {
        (*pool.nodes.offset(i as isize)).in_use = false;
    }

    // Array of lists of chains. Each list requires only two lookahead chains at
    // a time, so each list is a array of two Node*'s.
    let lists: *const *mut *mut Node = malloc((maxbits as usize * mem::size_of::<*const *const Node>()) as size_t) as *const *mut *mut Node;
    init_lists(&mut pool, leaves, maxbits, lists);

    // In the last list, 2 * numsymbols - 2 active chains need to be created. Two
    // are already created in the initialization. Each BoundaryPM run creates one.
    let num_boundary_pm_runs = 2 * numsymbols - 4;
    for i in 0..num_boundary_pm_runs {
        let is_final = i == num_boundary_pm_runs - 1;
        boundary_pm(lists, maxbits, leaves, numsymbols as i32, &mut pool, maxbits - 1, is_final);
    }

    extract_bit_lengths(*(*lists.offset(maxbits as isize - 1)).offset(1), leaves, bitlengths);

    free(lists as *mut c_void);
    free(leaves as *mut c_void);
    free(pool.nodes as *mut c_void);
    false
}

#[cfg(test)]
mod tests {
    use std::mem::size_of;
    use libc::{c_void, size_t};

    use super::qsort;

    extern fn comparator(a: *const c_void, b: *const c_void) -> i32 {
        unsafe {
            *(a as *const i32) - *(b as *const i32)
        }
    }

    #[test]
    fn test_qsort() {
        unsafe {
            let mut a: [i32; 5] = [3, 2, 4, 1, 5];
            qsort(a.as_mut_ptr() as *mut c_void, a.len() as size_t, size_of::<i32>() as size_t, comparator);
            assert_eq!(a, [1, 2, 3, 4, 5]);
        }
    }
}
<|endoftext|>


<commit_before>/*
Module: map

A hashmap
*/

/* Section: Types */

/*
Type: hashfn

A function that returns a hash of a value.
The hash should concentrate entropy in the
lower bits.
*/
type hashfn<K> = fn(K) -> uint;

/*
Type: eqfn

Equality
*/
type eqfn<K> = fn(K, K) -> bool;

/*
Type: hashset

A convenience type to treat a hashmap as a set
*/
type hashset<K> = hashmap<K, ()>;

/*
Obj: hashmap
*/
type hashmap<K, V> = obj {
    /*
    Method: size

    Return the number of elements in the map
    */
    fn size() -> uint;
    /*
    Method: insert

    Add a value to the map. If the map already contains a value for
    the specified key then the original value is replaced.

    Returns:

    True if the key did not already exist in the map
    */
    fn insert(K, V) -> bool;
    /*
    Method: contains_key

    Returns true if the map contains a value for the specified key
    */
    fn contains_key(K) -> bool;
    /*
    Method: get

    Get the value for the specified key

    Failure:

    If the key does not exist in the map
    */
    fn get(K) -> V;
    /*
    Method: find

    Get the value for the specified key. If the key does not exist
    in the map then returns none.
    */
    fn find(K) -> option::t<V>;
    /*
    Method: remove

    Remove and return a value from the map. If the key does not exist
    in the map then returns none.
    */
    fn remove(K) -> option::t<V>;
    /*
    Method: rehash

    Force map growth and rehashing
    */
    fn rehash();
    /*
    Method: items

    Iterate over all the key/value pairs in the map
    */
    fn items(block(K, V));
    /*
    Method: keys

    Iterate over all the keys in the map
    */
    fn keys(block(K));
    /*
    Iterate over all the values in the map
    */
    fn values(block(V));
};

/* Section: Operations */

mod chained {
    type entry<copy K, copy V> = {
        hash: uint,
        key: K,
        mutable value: V,
        mutable next: chain<K, V>
    };

    tag chain<copy K, copy V> {
        present(@entry<K, V>);
        absent;
    }

    type t<copy K, copy V> = {
        mutable size: uint,
        mutable chains: [mutable chain<K,V>],
        hasher: hashfn<K>,
        eqer: eqfn<K>
    };

    tag search_result<copy K, copy V> {
        not_found;
        found_first(uint, @entry<K,V>);
        found_after(@entry<K,V>, @entry<K,V>);
    }

    fn search_rem<copy K, copy V>(tbl: t<K,V>,
                                  k: K,
                                  h: uint,
                                  idx: uint,
                                  e_root: @entry<K,V>) -> search_result<K,V> {
        let e0 = e_root;
        let comp = 1u;   // for logging
        while true {
            alt e0.next {
              absent. {
                log("search_tbl", "absent", "comparisons", comp,
                    "hash", h, "idx", idx);

                ret not_found;
              }
              present(e1) {
                comp += 1u;
                let e1_key = e1.key; // Satisfy alias checker.
                if e1.hash == h && tbl.eqer(e1_key, k) {
                    log("search_tbl", "present", "comparisons", comp,
                        "hash", h, "idx", idx);
                    ret found_after(e0, e1);
                } else {
                    e0 = e1;
                }
              }
            }
        }
        util::unreachable();
    }

    fn search_tbl<copy K, copy V>(
        tbl: t<K,V>, k: K, h: uint) -> search_result<K,V> {
        let idx = h % vec::len(tbl.chains);
        alt tbl.chains[idx] {
          absent. {
            log("search_tbl", "absent", "comparisons", 0u,
                "hash", h, "idx", idx);
            ret not_found;
          }
          present(e) {
            let e_key = e.key; // Satisfy alias checker.
            if e.hash == h && tbl.eqer(e_key, k) {
                log("search_tbl", "present", "comparisons", 1u,
                    "hash", h, "idx", idx);
                ret found_first(idx, e);
            } else {
                ret search_rem(tbl, k, h, idx, e);
            }
          }
        }
    }

    fn insert<copy K, copy V>(tbl: t<K,V>, k: K, v: V) -> bool {
        let hash = tbl.hasher(k);
        alt search_tbl(tbl, k, hash) {
          not_found. {
            tbl.size += 1u;
            let idx = hash % vec::len(tbl.chains);
            let old_chain = tbl.chains[idx];
            tbl.chains[idx] = present(@{
                hash: hash,
                key: k,
                mutable value: v,
                mutable next: old_chain});
            ret true;
          }
          found_first(_, entry) {
            entry.value = v;
            ret false;
          }
          found_after(_, entry) {
            entry.value = v;
            ret false
          }
        }
    }

    fn get<copy K, copy V>(tbl: t<K,V>, k: K) -> option::t<V> {
        alt search_tbl(tbl, k, tbl.hasher(k)) {
          not_found. {
            ret option::none;
          }

          found_first(_, entry) {
            ret option::some(entry.value);
          }

          found_after(_, entry) {
            ret option::some(entry.value);
          }
        }
    }

    fn remove<copy K, copy V>(tbl: t<K,V>, k: K) -> option::t<V> {
        alt search_tbl(tbl, k, tbl.hasher(k)) {
          not_found. {
            ret option::none;
          }

          found_first(idx, entry) {
            tbl.size -= 1u;
            tbl.chains[idx] = entry.next;
            ret option::some(entry.value);
          }

          found_after(eprev, entry) {
            tbl.size -= 1u;
            eprev.next = entry.next;
            ret option::some(entry.value);
          }
        }
    }

    fn chains<copy K, copy V>(nchains: uint) -> [mutable chain<K,V>] {
        ret vec::init_elt_mut(absent, nchains);
    }

    fn foreach_entry<copy K, copy V>(chain0: chain<K,V>,
                                     blk: block(@entry<K,V>)) {
        let chain = chain0;
        while true {
            alt chain {
              absent. { ret; }
              present(entry) {
                let next = entry.next;
                blk(entry); // may modify entry.next!
                chain = next;
              }
            }
        }
    }

    fn foreach_chain<copy K, copy V>(chains: [const chain<K,V>],
                                     blk: block(@entry<K,V>)) {
        let i = 0u, n = vec::len(chains);
        while i < n {
            foreach_entry(chains[i], blk);
            i += 1u;
        }
    }

    fn rehash<copy K, copy V>(tbl: t<K,V>) {
        let old_chains = tbl.chains;
        let n_old_chains = vec::len(old_chains);
        let n_new_chains: uint = uint::next_power_of_two(n_old_chains + 1u);
        tbl.chains = chains(n_new_chains);
        foreach_chain(old_chains) { |entry|
            let idx = entry.hash % n_new_chains;
            entry.next = tbl.chains[idx];
            tbl.chains[idx] = present(entry);
        }
    }

    fn items<copy K, copy V>(tbl: t<K,V>, blk: block(K,V)) {
        let tbl_chains = tbl.chains;  // Satisfy alias checker.
        foreach_chain(tbl_chains) { |entry|
            let key = entry.key;
            let value = entry.value;
            blk(key, value);
        }
    }

    obj o<copy K, copy V>(tbl: @t<K,V>,
                          lf: float) {
        fn size() -> uint {
            ret tbl.size;
        }

        fn insert(k: K, v: V) -> bool {
            let nchains = vec::len(tbl.chains);
            let load = (tbl.size + 1u as float) / (nchains as float);
            if load > lf {
                rehash(*tbl);
            }
            ret insert(*tbl, k, v);
        }

        fn contains_key(k: K) -> bool {
            ret option::is_some(get(*tbl, k));
        }

        fn get(k: K) -> V {
            ret option::get(get(*tbl, k));
        }

        fn find(k: K) -> option::t<V> {
            ret get(*tbl, k);
        }

        fn remove(k: K) -> option::t<V> {
            ret remove(*tbl, k);
        }

        fn rehash() {
            rehash(*tbl);
        }

        fn items(blk: block(K, V)) {
            items(*tbl, blk);
        }

        fn keys(blk: block(K)) {
            items(*tbl) { |k, _v| blk(k) }
        }

        fn values(blk: block(V)) {
            items(*tbl) { |_k, v| blk(v) }
        }
    }

    fn mk<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K,V> {
        let initial_capacity: uint = 32u; // 2^5
        let t = @{mutable size: 0u,
                  mutable chains: chains(initial_capacity),
                  hasher: hasher,
                  eqer: eqer};
        ret o(t, 0.75);
    }
}

/*
Function: mk_hashmap

Construct a hashmap.

Parameters:

hasher - The hash function for key type K
eqer - The equality function for key type K
*/
fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
    -> hashmap<K, V> {
    ret chained::mk(hasher, eqer);
}

/*
Function: new_str_hash

Construct a hashmap for string keys
*/
fn new_str_hash<copy V>() -> hashmap<str, V> {
    ret mk_hashmap(str::hash, str::eq);
}

/*
Function: new_int_hash

Construct a hashmap for int keys
*/
fn new_int_hash<copy V>() -> hashmap<int, V> {
    fn hash_int(&&x: int) -> uint { ret x as uint; }
    fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; }
    ret mk_hashmap(hash_int, eq_int);
}

/*
Function: new_uint_hash

Construct a hashmap for uint keys
*/
fn new_uint_hash<copy V>() -> hashmap<uint, V> {
    fn hash_uint(&&x: uint) -> uint { ret x; }
    fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; }
    ret mk_hashmap(hash_uint, eq_uint);
}

/*
Function: set_add

Convenience function for adding keys to a hashmap with nil type keys
*/
fn set_add<K>(set: hashset<K>, key: K) -> bool { ret set.insert(key, ()); }

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>use util::rational to work around bug w/ floats on win<commit_after>/*
Module: map

A hashmap
*/

/* Section: Types */

/*
Type: hashfn

A function that returns a hash of a value.
The hash should concentrate entropy in the
lower bits.
*/
type hashfn<K> = fn(K) -> uint;

/*
Type: eqfn

Equality
*/
type eqfn<K> = fn(K, K) -> bool;

/*
Type: hashset

A convenience type to treat a hashmap as a set
*/
type hashset<K> = hashmap<K, ()>;

/*
Obj: hashmap
*/
type hashmap<K, V> = obj {
    /*
    Method: size

    Return the number of elements in the map
    */
    fn size() -> uint;
    /*
    Method: insert

    Add a value to the map. If the map already contains a value for
    the specified key then the original value is replaced.

    Returns:

    True if the key did not already exist in the map
    */
    fn insert(K, V) -> bool;
    /*
    Method: contains_key

    Returns true if the map contains a value for the specified key
    */
    fn contains_key(K) -> bool;
    /*
    Method: get

    Get the value for the specified key

    Failure:

    If the key does not exist in the map
    */
    fn get(K) -> V;
    /*
    Method: find

    Get the value for the specified key. If the key does not exist
    in the map then returns none.
    */
    fn find(K) -> option::t<V>;
    /*
    Method: remove

    Remove and return a value from the map. If the key does not exist
    in the map then returns none.
    */
    fn remove(K) -> option::t<V>;
    /*
    Method: rehash

    Force map growth and rehashing
    */
    fn rehash();
    /*
    Method: items

    Iterate over all the key/value pairs in the map
    */
    fn items(block(K, V));
    /*
    Method: keys

    Iterate over all the keys in the map
    */
    fn keys(block(K));
    /*
    Iterate over all the values in the map
    */
    fn values(block(V));
};

/* Section: Operations */

mod chained {
    type entry<copy K, copy V> = {
        hash: uint,
        key: K,
        mutable value: V,
        mutable next: chain<K, V>
    };

    tag chain<copy K, copy V> {
        present(@entry<K, V>);
        absent;
    }

    type t<copy K, copy V> = {
        mutable size: uint,
        mutable chains: [mutable chain<K,V>],
        hasher: hashfn<K>,
        eqer: eqfn<K>
    };

    tag search_result<copy K, copy V> {
        not_found;
        found_first(uint, @entry<K,V>);
        found_after(@entry<K,V>, @entry<K,V>);
    }

    fn search_rem<copy K, copy V>(tbl: t<K,V>,
                                  k: K,
                                  h: uint,
                                  idx: uint,
                                  e_root: @entry<K,V>) -> search_result<K,V> {
        let e0 = e_root;
        let comp = 1u;   // for logging
        while true {
            alt e0.next {
              absent. {
                log("search_tbl", "absent", "comparisons", comp,
                    "hash", h, "idx", idx);

                ret not_found;
              }
              present(e1) {
                comp += 1u;
                let e1_key = e1.key; // Satisfy alias checker.
                if e1.hash == h && tbl.eqer(e1_key, k) {
                    log("search_tbl", "present", "comparisons", comp,
                        "hash", h, "idx", idx);
                    ret found_after(e0, e1);
                } else {
                    e0 = e1;
                }
              }
            }
        }
        util::unreachable();
    }

    fn search_tbl<copy K, copy V>(
        tbl: t<K,V>, k: K, h: uint) -> search_result<K,V> {
        let idx = h % vec::len(tbl.chains);
        alt tbl.chains[idx] {
          absent. {
            log("search_tbl", "absent", "comparisons", 0u,
                "hash", h, "idx", idx);
            ret not_found;
          }
          present(e) {
            let e_key = e.key; // Satisfy alias checker.
            if e.hash == h && tbl.eqer(e_key, k) {
                log("search_tbl", "present", "comparisons", 1u,
                    "hash", h, "idx", idx);
                ret found_first(idx, e);
            } else {
                ret search_rem(tbl, k, h, idx, e);
            }
          }
        }
    }

    fn insert<copy K, copy V>(tbl: t<K,V>, k: K, v: V) -> bool {
        let hash = tbl.hasher(k);
        alt search_tbl(tbl, k, hash) {
          not_found. {
            tbl.size += 1u;
            let idx = hash % vec::len(tbl.chains);
            let old_chain = tbl.chains[idx];
            tbl.chains[idx] = present(@{
                hash: hash,
                key: k,
                mutable value: v,
                mutable next: old_chain});
            ret true;
          }
          found_first(_, entry) {
            entry.value = v;
            ret false;
          }
          found_after(_, entry) {
            entry.value = v;
            ret false
          }
        }
    }

    fn get<copy K, copy V>(tbl: t<K,V>, k: K) -> option::t<V> {
        alt search_tbl(tbl, k, tbl.hasher(k)) {
          not_found. {
            ret option::none;
          }

          found_first(_, entry) {
            ret option::some(entry.value);
          }

          found_after(_, entry) {
            ret option::some(entry.value);
          }
        }
    }

    fn remove<copy K, copy V>(tbl: t<K,V>, k: K) -> option::t<V> {
        alt search_tbl(tbl, k, tbl.hasher(k)) {
          not_found. {
            ret option::none;
          }

          found_first(idx, entry) {
            tbl.size -= 1u;
            tbl.chains[idx] = entry.next;
            ret option::some(entry.value);
          }

          found_after(eprev, entry) {
            tbl.size -= 1u;
            eprev.next = entry.next;
            ret option::some(entry.value);
          }
        }
    }

    fn chains<copy K, copy V>(nchains: uint) -> [mutable chain<K,V>] {
        ret vec::init_elt_mut(absent, nchains);
    }

    fn foreach_entry<copy K, copy V>(chain0: chain<K,V>,
                                     blk: block(@entry<K,V>)) {
        let chain = chain0;
        while true {
            alt chain {
              absent. { ret; }
              present(entry) {
                let next = entry.next;
                blk(entry); // may modify entry.next!
                chain = next;
              }
            }
        }
    }

    fn foreach_chain<copy K, copy V>(chains: [const chain<K,V>],
                                     blk: block(@entry<K,V>)) {
        let i = 0u, n = vec::len(chains);
        while i < n {
            foreach_entry(chains[i], blk);
            i += 1u;
        }
    }

    fn rehash<copy K, copy V>(tbl: t<K,V>) {
        let old_chains = tbl.chains;
        let n_old_chains = vec::len(old_chains);
        let n_new_chains: uint = uint::next_power_of_two(n_old_chains + 1u);
        tbl.chains = chains(n_new_chains);
        foreach_chain(old_chains) { |entry|
            let idx = entry.hash % n_new_chains;
            entry.next = tbl.chains[idx];
            tbl.chains[idx] = present(entry);
        }
    }

    fn items<copy K, copy V>(tbl: t<K,V>, blk: block(K,V)) {
        let tbl_chains = tbl.chains;  // Satisfy alias checker.
        foreach_chain(tbl_chains) { |entry|
            let key = entry.key;
            let value = entry.value;
            blk(key, value);
        }
    }

    obj o<copy K, copy V>(tbl: @t<K,V>,
                          lf: util::rational) {
        fn size() -> uint {
            ret tbl.size;
        }

        fn insert(k: K, v: V) -> bool {
            let nchains = vec::len(tbl.chains);
            let load = {num:tbl.size + 1u as int, den:nchains as int};
            if !util::rational_leq(load, lf) {
                rehash(*tbl);
            }
            ret insert(*tbl, k, v);
        }

        fn contains_key(k: K) -> bool {
            ret option::is_some(get(*tbl, k));
        }

        fn get(k: K) -> V {
            ret option::get(get(*tbl, k));
        }

        fn find(k: K) -> option::t<V> {
            ret get(*tbl, k);
        }

        fn remove(k: K) -> option::t<V> {
            ret remove(*tbl, k);
        }

        fn rehash() {
            rehash(*tbl);
        }

        fn items(blk: block(K, V)) {
            items(*tbl, blk);
        }

        fn keys(blk: block(K)) {
            items(*tbl) { |k, _v| blk(k) }
        }

        fn values(blk: block(V)) {
            items(*tbl) { |_k, v| blk(v) }
        }
    }

    fn mk<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K,V> {
        let initial_capacity: uint = 32u; // 2^5
        let t = @{mutable size: 0u,
                  mutable chains: chains(initial_capacity),
                  hasher: hasher,
                  eqer: eqer};
        ret o(t, {num:3, den:4});
    }
}

/*
Function: mk_hashmap

Construct a hashmap.

Parameters:

hasher - The hash function for key type K
eqer - The equality function for key type K
*/
fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
    -> hashmap<K, V> {
    ret chained::mk(hasher, eqer);
}

/*
Function: new_str_hash

Construct a hashmap for string keys
*/
fn new_str_hash<copy V>() -> hashmap<str, V> {
    ret mk_hashmap(str::hash, str::eq);
}

/*
Function: new_int_hash

Construct a hashmap for int keys
*/
fn new_int_hash<copy V>() -> hashmap<int, V> {
    fn hash_int(&&x: int) -> uint { ret x as uint; }
    fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; }
    ret mk_hashmap(hash_int, eq_int);
}

/*
Function: new_uint_hash

Construct a hashmap for uint keys
*/
fn new_uint_hash<copy V>() -> hashmap<uint, V> {
    fn hash_uint(&&x: uint) -> uint { ret x; }
    fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; }
    ret mk_hashmap(hash_uint, eq_uint);
}

/*
Function: set_add

Convenience function for adding keys to a hashmap with nil type keys
*/
fn set_add<K>(set: hashset<K>, key: K) -> bool { ret set.insert(key, ()); }

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>