From 186db0c54bcb0caf4a6df1fcc60b8158bc11ab92 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 5 May 2009 07:03:24 -0700 Subject: [PATCH] range-set: New function range_set_allocate_fully. --- src/libpspp/range-set.c | 32 ++++++++++++++++++- src/libpspp/range-set.h | 4 ++- tests/libpspp/range-set-test.c | 57 +++++++++++++++++++++++++++++++++- 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/libpspp/range-set.c b/src/libpspp/range-set.c index c13fc33f..78253be6 100644 --- a/src/libpspp/range-set.c +++ b/src/libpspp/range-set.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -274,6 +274,36 @@ range_set_allocate (struct range_set *rs, unsigned long int request, return true; } +/* Scans RS for and deletes the first contiguous run of REQUEST + 1-bits. If successful, sets *START to the position of the + first 1-bit deleted and returns true If RS does not contain a + run of REQUEST or more contiguous 1-bits, returns false and + does not modify RS. */ +bool +range_set_allocate_fully (struct range_set *rs, unsigned long int request, + unsigned long int *start) +{ + struct range_set_node *node; + + assert (request > 0); + + for (node = first_node (rs); node != NULL; node = next_node (rs, node)) + { + unsigned long int node_width = node->end - node->start; + if (node_width >= request) + { + *start = node->start; + if (node_width > request) + node->start += request; + else + delete_node (rs, node); + rs->cache_end = 0; + return true; + } + } + return false; +} + /* Returns true if there is a 1-bit at the given POSITION in RS, false otherwise. */ bool diff --git a/src/libpspp/range-set.h b/src/libpspp/range-set.h index 83e5db6f..665447f6 100644 --- a/src/libpspp/range-set.h +++ b/src/libpspp/range-set.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,6 +39,8 @@ void range_set_delete (struct range_set *, unsigned long int start, unsigned long int width); bool range_set_allocate (struct range_set *, unsigned long int request, unsigned long int *start, unsigned long int *width); +bool range_set_allocate_fully (struct range_set *, unsigned long int request, + unsigned long int *start); bool range_set_contains (const struct range_set *, unsigned long int position); bool range_set_is_empty (const struct range_set *); diff --git a/tests/libpspp/range-set-test.c b/tests/libpspp/range-set-test.c index 894c6797..b0eb7abb 100644 --- a/tests/libpspp/range-set-test.c +++ b/tests/libpspp/range-set-test.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -288,6 +288,60 @@ test_allocate (void) } } +/* Tests all possible full allocations in all possible range sets + (up to a small maximum number of bits). */ +static void +test_allocate_fully (void) +{ + const int positions = 9; + unsigned int init_pat; + int request; + + for (init_pat = 0; init_pat < (1u << positions); init_pat++) + for (request = 1; request <= positions + 1; request++) + { + struct range_set *rs; + unsigned long int start, expect_start; + bool success, expect_success; + unsigned int final_pat; + int i; + + /* Figure out expected results. */ + expect_success = false; + expect_start = 0; + final_pat = init_pat; + for (i = 0; i < positions - request + 1; i++) + { + int j; + + final_pat = init_pat; + for (j = i; j < i + request; j++) + { + if (!(init_pat & (1u << j))) + goto next; + final_pat &= ~(1u << j); + } + + expect_success = true; + expect_start = i; + break; + next: + final_pat = init_pat; + } + + /* Test. */ + rs = make_pattern (init_pat); + success = range_set_allocate_fully (rs, request, &start); + check_pattern (rs, final_pat); + range_set_destroy (rs); + + /* Check results. */ + check (success == expect_success); + if (expect_success) + check (start == expect_start); + } +} + /* Tests freeing a range set through a pool. */ static void test_pool (void) @@ -329,6 +383,7 @@ main (void) run_test (test_insert, "insert"); run_test (test_delete, "delete"); run_test (test_allocate, "allocate"); + run_test (test_allocate_fully, "allocate_fully"); run_test (test_pool, "pool"); putchar ('\n'); -- 2.30.2