span_manager.cpp

Go to the documentation of this file.
00001 #ifndef SPAN_MANAGER_IMPLEMENTATION_FILE
00002 #define SPAN_MANAGER_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : span_manager                                                      *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1990-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "bit_vector.h"
00019 #include "span_manager.h"
00020 
00021 #include <basis/function.h>
00022 #include <basis/guards.h>
00023 #include <basis/istring.h>
00024 #include <basis/set.cpp>
00025 
00026 span_manager::span_manager(int packs)
00027 : _implementation(new bit_vector(packs))
00028 {}
00029 
00030 span_manager::span_manager(const span_manager &to_copy)
00031 : _implementation(new bit_vector(*to_copy._implementation))
00032 {}
00033 
00034 span_manager::~span_manager() { WHACK(_implementation); }
00035 
00036 span_manager &span_manager::operator =(const span_manager &to_copy)
00037 {
00038   if (this == &to_copy) return *this;
00039   *_implementation = *to_copy._implementation;
00040   return *this;
00041 }
00042 
00043 int span_manager::missing_sequence() const
00044 { return _implementation->find_first(0); }
00045 
00046 void span_manager::reset(int packs) { _implementation->resize(packs); }
00047 
00048 const bit_vector &span_manager::vector() const { return *_implementation; }
00049 
00050 bit_vector &span_manager::vector() { return *_implementation; }
00051 
00052 int span_manager::received_sequence() const
00053 {
00054   int recd_to = _implementation->find_first(0);
00055   if (negative(recd_to)) return _implementation->bits() - 1;
00056   return recd_to - 1;
00057 }
00058 
00059 void span_manager::make_received_list(int_array &to_make, int max_spans) const
00060 {
00061   to_make.reset(0);
00062   int zeros_start_at = _implementation->find_first(0);
00063   if (negative(zeros_start_at)) {
00064     // all bits are set in the vector, so the whole message is received.
00065     to_make.concatenate(0);
00066     to_make.concatenate(short(_implementation->bits() - 1));
00067     return;
00068   }
00069   zeros_start_at--;
00070   // the sequence of ones ends right before the first zero
00071   if (zeros_start_at >= 0) {
00072     to_make.concatenate(0);
00073     to_make.concatenate(short(zeros_start_at));
00074   }
00075 
00076   int ones_to_here;  // keeps track of the position of the ones.
00077 
00078   for (int outer_loop = zeros_start_at + 2;
00079       outer_loop < _implementation->bits(); ) {
00080     // the first zero is zeros_start_at + 1, so we start at the first
00081     // unknown bit.
00082     if (_implementation->on(outer_loop)) {
00083       // the bit is a one, so we are in a one-gathering mode.
00084       ones_to_here = outer_loop;
00085       int inner_loop = outer_loop + 1;
00086       while (inner_loop < _implementation->bits()) {
00087         if (_implementation->on(inner_loop)) ones_to_here=inner_loop;
00088         else break;  // a zero is found at this position, so leave loop.
00089         inner_loop++;
00090       }
00091       // the stretch of ones is entered in the array.
00092       to_make.concatenate(short(outer_loop));
00093       to_make.concatenate(short(ones_to_here));
00094       if ( (max_spans >= 0) && (to_make.length() >= 2 * max_spans) )
00095         return;
00096       outer_loop = ones_to_here + 1;
00097     } else {
00098       // the bit is a zero, so we are gathering zeros.
00099       int inner_loop = outer_loop + 1;
00100       ones_to_here = _implementation->bits();
00101       while (inner_loop < _implementation->bits()) {
00102         if (!_implementation->on(inner_loop)) inner_loop++;
00103         else {
00104           // ones_to_here is set to the first position of a one, actually.
00105           ones_to_here = inner_loop;
00106           break;
00107         }
00108       }
00109       // the loop variable is set to the first unknown position again.
00110       outer_loop = ones_to_here;
00111     }
00112   }
00113 }
00114 
00115 bool span_manager::update(const int_array &new_spans)
00116 {
00117   for (int i = 0; i < new_spans.length(); i += 2) {
00118     if ( (new_spans.get(i) >= _implementation->bits())
00119         || (new_spans.get(i+1) >= _implementation->bits()) )
00120       return false;
00121     for (int j = new_spans.get(i); j <= new_spans.get(i+1); j++)
00122       _implementation->light(j);
00123   }
00124   return true;
00125 }
00126 
00127 void span_manager::make_missing_list(int_array &to_make, int max_spans) const
00128 {
00129   to_make.reset(0);
00130   int ones_start_at = _implementation->find_first(1);
00131   if (negative(ones_start_at)) {
00132     // all bits are zero in the vector; no packets have been received.
00133     to_make.concatenate(0);
00134     to_make.concatenate(short(_implementation->bits() - 1));
00135     return;
00136   }
00137   ones_start_at--;
00138   // the sequence of zeros ends right before the first one
00139   if (ones_start_at >= 0) {
00140     to_make.concatenate(0);
00141     to_make.concatenate(short(ones_start_at));
00142   }
00143 
00144   int zeros_to_here;
00145   for (int outer_loop = ones_start_at + 2;
00146       outer_loop < _implementation->bits(); ) {
00147     int inner_loop;
00148     // the first one is ones_start_at+1, so we start at the first unknown bit
00149     if (!_implementation->on(outer_loop)) {
00150       // the bit is a zero, so we are in a zero-gathering mode.
00151       zeros_to_here = outer_loop;
00152       int inner_loop = outer_loop + 1;
00153       while (inner_loop < _implementation->bits()) {
00154         if (!_implementation->on(inner_loop)) zeros_to_here=inner_loop;
00155         else break;
00156           // a one is found at this position, so leave loop.
00157         inner_loop++;
00158       }
00159       // the stretch of zeros is entered in the array.
00160       to_make.concatenate(short(outer_loop));
00161       to_make.concatenate(short(zeros_to_here));
00162       if ( (max_spans >= 0) && (to_make.length() >= 2 * max_spans) ) return;
00163       outer_loop = zeros_to_here + 1;
00164     } else {
00165       // the bit is a one, so we are gathering ones.
00166       inner_loop = outer_loop + 1;
00167       zeros_to_here = _implementation->bits();
00168       while (inner_loop < _implementation->bits()) {
00169         if (_implementation->on(inner_loop))
00170           inner_loop++;
00171         else {
00172           // zeros_to_here is set to the first position of a zero, actually.
00173           zeros_to_here = inner_loop;
00174           break;
00175         }
00176       }
00177       // the loop variable is set to the first unknown position again.
00178       outer_loop = zeros_to_here;
00179     }
00180   }
00181 }
00182 
00183 istring span_manager::funky_print(const int_array &to_spew, int rec_seq) const
00184 {
00185   istring to_return(istring::SPRINTF, "through %d, [", rec_seq);
00186   for (int i = 0; i < to_spew.length(); i += 2) {
00187     to_return += istring(istring::SPRINTF, " %d-%d", to_spew.get(i),
00188         to_spew.get(i+1));
00189   }
00190   to_return += istring(" ] ");
00191   return to_return;
00192 }
00193 
00194 istring span_manager::print_received_list() const
00195 {
00196   int_array hold_info;
00197   make_received_list(hold_info);
00198   istring to_return("received ");
00199   to_return += funky_print(hold_info, received_sequence());
00200   return to_return;
00201 }
00202 
00203 istring span_manager::print_missing_list() const
00204 {
00205   int_array hold_info;
00206   make_missing_list(hold_info);
00207   istring to_return("missing ");
00208   to_return += funky_print(hold_info, received_sequence());
00209   return to_return;
00210 }
00211 
00212 
00213 #endif //SPAN_MANAGER_IMPLEMENTATION_FILE
00214 

Generated on Fri Nov 21 04:29:41 2008 for HOOPLE Libraries by  doxygen 1.5.1