1 /** 2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 10 This file contains the plumbing for generating a unique sequence of numbers 11 that is tightly packed. 12 */ 13 module dextool.plugin.fuzzer.backend.unique_sequence; 14 15 import logger = std.experimental.logger; 16 17 /// The first number of the sequence will be skipped. 18 /// It is okey. 19 struct Sequence(NumT) { 20 @disable this(this); 21 22 /// Put a number into the pool or adjust `n` to a valid value. 23 void putOrAdjust(ref NumT n) { 24 if (n <= last_num) { 25 n = next; 26 } else if (auto v = n in used_pool) { 27 n = next; 28 } else { 29 used_pool[n] = true; 30 } 31 32 if (n % 100 == 0) { 33 vacuumPool; 34 } 35 } 36 37 NumT next() { 38 while (++last_num in used_pool) { 39 } 40 return last_num; 41 } 42 43 void vacuumPool() { 44 bool[NumT] new_pool; 45 46 foreach (n; used_pool) { 47 if (n >= last_num) 48 new_pool[n] = true; 49 } 50 51 used_pool = new_pool; 52 } 53 54 private: 55 bool[NumT] used_pool; 56 NumT last_num; 57 } 58 59 version (unittest) { 60 import unit_threaded : shouldEqual; 61 } 62 63 @("Shall be a list of numbers for the holes in the initialized sequence") 64 unittest { 65 Sequence!ulong seq; 66 67 ulong[] input = [0, 2, 4, 7]; 68 69 foreach (i; 0 .. input.length) 70 seq.putOrAdjust(input[i]); 71 72 ulong[] output; 73 foreach (i; 0 .. 5) 74 output ~= seq.next; 75 76 input.shouldEqual([1, 2, 4, 7]); 77 output.shouldEqual([3, 5, 6, 8, 9]); 78 }