Skip to content

Commit 74b317d

Browse files
committed
modernize smallintmap
* switch to explicit self * get rid of the @ box * replace DVec with ~[] (to get rid of the mutable field) * implement the new container::Map trait
1 parent 348d770 commit 74b317d

File tree

3 files changed

+103
-142
lines changed

3 files changed

+103
-142
lines changed

src/libstd/smallintmap.rs

Lines changed: 94 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -15,77 +15,20 @@
1515
#[forbid(deprecated_mode)];
1616

1717
use core::container::{Container, Mutable, Map, Set};
18-
use core::dvec::DVec;
19-
use core::ops;
2018
use core::option::{Some, None};
21-
use core::option;
2219
use core::prelude::*;
2320

24-
// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that
25-
// requires this to be.
26-
struct SmallIntMap_<T> {
27-
v: DVec<Option<T>>,
28-
}
29-
30-
pub enum SmallIntMap<T> {
31-
SmallIntMap_(@SmallIntMap_<T>)
32-
}
33-
34-
/// Create a smallintmap
35-
pub fn mk<T: Copy>() -> SmallIntMap<T> {
36-
let v = DVec();
37-
SmallIntMap_(@SmallIntMap_ { v: v } )
38-
}
39-
40-
/**
41-
* Add a value to the map. If the map already contains a value for
42-
* the specified key then the original value is replaced.
43-
*/
44-
#[inline(always)]
45-
pub fn insert<T: Copy>(self: SmallIntMap<T>, key: uint, val: T) {
46-
//io::println(fmt!("%?", key));
47-
self.v.grow_set_elt(key, &None, Some(val));
48-
}
49-
50-
/**
51-
* Get the value for the specified key. If the key does not exist
52-
* in the map then returns none
53-
*/
54-
pub pure fn find<T: Copy>(self: SmallIntMap<T>, key: uint) -> Option<T> {
55-
if key < self.v.len() { return self.v.get_elt(key); }
56-
return None::<T>;
57-
}
58-
59-
/**
60-
* Get the value for the specified key
61-
*
62-
* # Failure
63-
*
64-
* If the key does not exist in the map
65-
*/
66-
pub pure fn get<T: Copy>(self: SmallIntMap<T>, key: uint) -> T {
67-
match find(self, key) {
68-
None => {
69-
error!("smallintmap::get(): key not present");
70-
fail;
71-
}
72-
Some(move v) => return v
73-
}
74-
}
75-
76-
/// Returns true if the map contains a value for the specified key
77-
pub pure fn contains_key<T: Copy>(self: SmallIntMap<T>, key: uint) -> bool {
78-
return !find(self, key).is_none();
21+
pub struct SmallIntMap<T> {
22+
priv v: ~[Option<T>],
7923
}
8024

8125
impl<V> SmallIntMap<V>: Container {
8226
/// Return the number of elements in the map
8327
pure fn len(&self) -> uint {
84-
let mut sz = 0u;
28+
let mut sz = 0;
8529
for self.v.each |item| {
86-
match *item {
87-
Some(_) => sz += 1u,
88-
_ => ()
30+
if item.is_some() {
31+
sz += 1;
8932
}
9033
}
9134
sz
@@ -96,118 +39,136 @@ impl<V> SmallIntMap<V>: Container {
9639
}
9740

9841
impl<V> SmallIntMap<V>: Mutable {
99-
fn clear(&mut self) { self.v.set(~[]) }
42+
/// Clear the map, removing all key-value pairs.
43+
fn clear(&mut self) { self.v.clear() }
10044
}
10145

102-
/// Implements the map::map interface for smallintmap
103-
impl<V: Copy> SmallIntMap<V> {
104-
#[inline(always)]
105-
fn insert(key: uint, value: V) -> bool {
106-
let exists = contains_key(self, key);
107-
insert(self, key, value);
108-
return !exists;
46+
impl<V> SmallIntMap<V>: Map<uint, V> {
47+
/// Return true if the map contains a value for the specified key
48+
pure fn contains_key(&self, key: &uint) -> bool {
49+
self.find(key).is_some()
10950
}
110-
fn remove(key: uint) -> bool {
111-
if key >= self.v.len() {
112-
return false;
51+
52+
/// Visit all key-value pairs
53+
pure fn each(&self, it: fn(key: &uint, value: &V) -> bool) {
54+
for uint::range(0, self.v.len()) |i| {
55+
match self.v[i] {
56+
Some(ref elt) => if !it(&i, elt) { break },
57+
None => ()
58+
}
11359
}
114-
let old = self.v.get_elt(key);
115-
self.v.set_elt(key, None);
116-
old.is_some()
11760
}
118-
pure fn contains_key(key: uint) -> bool {
119-
contains_key(self, key)
61+
62+
/// Visit all keys
63+
pure fn each_key(&self, blk: fn(key: &uint) -> bool) {
64+
self.each(|k, _| blk(k))
12065
}
121-
pure fn contains_key_ref(key: &uint) -> bool {
122-
contains_key(self, *key)
66+
67+
/// Visit all values
68+
pure fn each_value(&self, blk: fn(value: &V) -> bool) {
69+
self.each(|_, v| blk(v))
12370
}
124-
pure fn get(key: uint) -> V { get(self, key) }
125-
pure fn find(key: uint) -> Option<V> { find(self, key) }
12671

127-
fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool {
128-
match self.find(key) {
129-
None => return self.insert(key, val),
130-
Some(copy orig) => return self.insert(key, ff(key, orig, val)),
72+
/// Return the value corresponding to the key in the map
73+
pure fn find(&self, key: &uint) -> Option<&self/V> {
74+
if *key < self.v.len() {
75+
match self.v[*key] {
76+
Some(ref value) => Some(value),
77+
None => None
78+
}
79+
} else {
80+
None
13181
}
13282
}
13383

134-
fn update(key: uint, newval: V, ff: fn(V, V) -> V) -> bool {
135-
return self.update_with_key(key, newval, |_k, v, v1| ff(v,v1));
84+
/// Insert a key-value pair into the map. An existing value for a
85+
/// key is replaced by the new value. Return true if the key did
86+
/// not already exist in the map.
87+
fn insert(&mut self, key: uint, value: V) -> bool {
88+
let exists = self.contains_key(&key);
89+
let len = self.v.len();
90+
if len <= key {
91+
vec::grow_fn(&mut self.v, key - len + 1, |_| None);
92+
}
93+
self.v[key] = Some(value);
94+
!exists
13695
}
13796

138-
pure fn each(it: fn(key: uint, value: V) -> bool) {
139-
self.each_ref(|k, v| it(*k, *v))
140-
}
141-
pure fn each_key(it: fn(key: uint) -> bool) {
142-
self.each_ref(|k, _v| it(*k))
143-
}
144-
pure fn each_value(it: fn(value: V) -> bool) {
145-
self.each_ref(|_k, v| it(*v))
146-
}
147-
pure fn each_ref(it: fn(key: &uint, value: &V) -> bool) {
148-
let mut idx = 0u, l = self.v.len();
149-
while idx < l {
150-
match self.v.get_elt(idx) {
151-
Some(ref elt) => if !it(&idx, elt) { break },
152-
None => ()
153-
}
154-
idx += 1u;
97+
/// Remove a key-value pair from the map. Return true if the key
98+
/// was present in the map, otherwise false.
99+
fn remove(&mut self, key: &uint) -> bool {
100+
if *key >= self.v.len() {
101+
return false;
155102
}
103+
let removed = self.v[*key].is_some();
104+
self.v[*key] = None;
105+
removed
156106
}
157-
pure fn each_key_ref(blk: fn(key: &uint) -> bool) {
158-
self.each_ref(|k, _v| blk(k))
159-
}
160-
pure fn each_value_ref(blk: fn(value: &V) -> bool) {
161-
self.each_ref(|_k, v| blk(v))
107+
}
108+
109+
pub impl<V> SmallIntMap<V> {
110+
/// Create an empty SmallIntMap
111+
static pure fn new() -> SmallIntMap<V> { SmallIntMap{v: ~[]} }
112+
113+
pure fn get(&self, key: &uint) -> &self/V {
114+
self.find(key).expect("key not present")
162115
}
163116
}
164117

165-
impl<V: Copy> SmallIntMap<V>: ops::Index<uint, V> {
166-
pure fn index(&self, key: uint) -> V {
167-
unsafe {
168-
get(*self, key)
118+
pub impl<V: Copy> SmallIntMap<V> {
119+
// FIXME: #4733, remove after the next snapshot
120+
#[cfg(stage2)]
121+
fn update_with_key(&mut self, key: uint, val: V,
122+
ff: fn(uint, V, V) -> V) -> bool {
123+
match self.find(&key) {
124+
None => self.insert(key, val),
125+
Some(orig) => self.insert(key, ff(key, copy *orig, val)),
169126
}
170127
}
128+
129+
// FIXME: #4733, remove after the next snapshot
130+
#[cfg(stage2)]
131+
fn update(&mut self, key: uint, newval: V, ff: fn(V, V) -> V) -> bool {
132+
self.update_with_key(key, newval, |_k, v, v1| ff(v,v1))
133+
}
171134
}
172135

173136
#[cfg(test)]
174137
mod tests {
175-
use super::{mk, SmallIntMap};
176-
177-
use core::option::None;
138+
use super::SmallIntMap;
178139

179140
#[test]
180141
fn test_len() {
181-
let mut map = mk();
142+
let mut map = SmallIntMap::new();
182143
assert map.len() == 0;
183144
assert map.is_empty();
184-
map.insert(5, 20);
145+
assert map.insert(5, 20);
185146
assert map.len() == 1;
186147
assert !map.is_empty();
187-
map.insert(11, 12);
148+
assert map.insert(11, 12);
188149
assert map.len() == 2;
189150
assert !map.is_empty();
190-
map.insert(14, 22);
151+
assert map.insert(14, 22);
191152
assert map.len() == 3;
192153
assert !map.is_empty();
193154
}
194155

195156
#[test]
196157
fn test_clear() {
197-
let mut map = mk();
198-
map.insert(5, 20);
199-
map.insert(11, 12);
200-
map.insert(14, 22);
158+
let mut map = SmallIntMap::new();
159+
assert map.insert(5, 20);
160+
assert map.insert(11, 12);
161+
assert map.insert(14, 22);
201162
map.clear();
202163
assert map.is_empty();
203-
assert map.find(5).is_none();
204-
assert map.find(11).is_none();
205-
assert map.find(14).is_none();
164+
assert map.find(&5).is_none();
165+
assert map.find(&11).is_none();
166+
assert map.find(&14).is_none();
206167
}
207168

208169
#[test]
209170
fn test_insert_with_key() {
210-
let map: SmallIntMap<uint> = mk();
171+
let mut map = SmallIntMap::new();
211172

212173
// given a new key, initialize it with this new count, given
213174
// given an existing key, add more to its count
@@ -227,11 +188,11 @@ mod tests {
227188
map.update_with_key(3, 2, addMoreToCount);
228189

229190
// check the total counts
230-
assert map.find(3).get() == 10;
231-
assert map.find(5).get() == 3;
232-
assert map.find(9).get() == 1;
191+
assert map.find(&3).get() == &10;
192+
assert map.find(&5).get() == &3;
193+
assert map.find(&9).get() == &1;
233194

234195
// sadly, no sevens were counted
235-
assert None == map.find(7);
196+
assert map.find(&7).is_none();
236197
}
237198
}

src/libstd/std.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pub mod list;
8282
pub mod map;
8383
pub mod priority_queue;
8484
pub mod rope;
85+
pub mod smallintmap;
8586
pub mod oldsmallintmap;
8687
pub mod sort;
8788
pub mod treemap;

src/test/bench/std-smallintmap.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,21 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// Microbenchmark for the oldsmallintmap library
11+
// Microbenchmark for the smallintmap library
1212

1313
extern mod std;
14-
use std::oldsmallintmap;
15-
use std::oldsmallintmap::SmallIntMap;
14+
use std::smallintmap::SmallIntMap;
1615
use io::WriterUtil;
1716

18-
fn append_sequential(min: uint, max: uint, map: SmallIntMap<uint>) {
17+
fn append_sequential(min: uint, max: uint, map: &mut SmallIntMap<uint>) {
1918
for uint::range(min, max) |i| {
2019
map.insert(i, i + 22u);
2120
}
2221
}
2322

24-
fn check_sequential(min: uint, max: uint, map: SmallIntMap<uint>) {
23+
fn check_sequential(min: uint, max: uint, map: &SmallIntMap<uint>) {
2524
for uint::range(min, max) |i| {
26-
assert map.get(i) == i + 22u;
25+
assert *map.get(&i) == i + 22u;
2726
}
2827
}
2928

@@ -43,11 +42,11 @@ fn main() {
4342
let mut appendf = 0.0;
4443

4544
for uint::range(0u, rep) |_r| {
46-
let map = oldsmallintmap::mk();
45+
let mut map = SmallIntMap::new();
4746
let start = std::time::precise_time_s();
48-
append_sequential(0u, max, map);
47+
append_sequential(0u, max, &mut map);
4948
let mid = std::time::precise_time_s();
50-
check_sequential(0u, max, map);
49+
check_sequential(0u, max, &map);
5150
let end = std::time::precise_time_s();
5251

5352
checkf += (end - mid) as float;

0 commit comments

Comments
 (0)