// file: $isip/class/algo/Mask/mask_06.cc // version: $Id: mask_06.cc 7547 2001-12-21 19:43:18Z gao $ // // isip include files // #include "Mask.h" // method: set // // arguments: // const String& source: (input) mask string // // return: a bool8 value indicating status // // this method converts a string into a mask vector // bool8 Mask::set(const String& source_a) { // count the number of sub-strings separated by ',' // int32 tokens = source_a.countTokens(L','); // get all the sub-strings separated by ',' // String vals[tokens]; for (int32 i = 0, pos = 0; i < tokens; i++) { source_a.tokenize(vals[i], pos, L","); } // compute the number of all the digits in input string // int32 num = 0; for (int32 i = 0; i < tokens; i++) { num += vals[i].countTokens(L'-'); } // allocate the space for these digits // VectorLong vec(num); // declare the local variables // int32 k; int32 key = 0; String str[2]; int32 val1 = 0; int32 val2 = 0; // loop through all the sub-strings // for (int32 i = 0; i < tokens; i++) { k = vals[i].countTokens(L'-'); // input a range of the masked 1's // if (k == 2) { int32 pos = 0; vals[i].tokenize(str[0], pos, L'-'); vals[i].tokenize(str[1], pos, L'-'); str[0].get(val1); vec(key++) = val1; str[1].get(val2); vec(key++) = val2; } // input a single mask flag 1 // else if (k == 1) { vals[i].get(val1); vec(key++) = val1; } else { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } } // allocate space // mask_d.setLength(vec.max() + 1); // pad with all OFF's // mask_d.assign((byte8)OFF); // loop through all the sub-strings // for (int32 i = 0; i < tokens; i++) { k = vals[i].countTokens(L'-'); int32 pos = 0; // a range of masked ON's // if (k == 2) { vals[i].tokenize(str[0], pos, L'-'); vals[i].tokenize(str[1], pos, L'-'); str[0].get(val1); str[1].get(val2); // put the preserved mask flag ON's // if (val1 > val2) { insert(mask_d, val2, val1 - val2 + 1, ON); } else if (val1 < val2) { insert(mask_d, val1, val2 - val1 + 1, ON); } } // k = 1: single index // else if (k == 1) { vals[i].get(val1); mask_d(val1) = ON; } else { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } } // assign the mask string // source_d.assign(source_a); // exit gracefully // return true; } // method: set // // arguments: // const VectorByte& mask: (input) mask vector // // return: a bool8 value indicating status // // this method sets the mask and converts it into a mask string // bool8 Mask::set(const VectorByte& mask_a) { // set the mask // mask_d.assign(mask_a); // convert to a string // return convert(source_d, mask_d); } // method: convert // // arguments: // String& out: (output) mask string // const VectorByte& in: (input) mask vector // // return: a bool8 value indicating status // // this method converts a byte-oriented mask to a string // bool8 Mask::convert(String& out_a, const VectorByte& in_a) { // clear the output and determine the length of the input // out_a.clear(); int32 len = in_a.length(); // define our state machine // enum STATE {ZERO, ONE}; STATE state = ZERO; bool8 first = true; // keep track of the number of 1's in a row // int32 cur_len = 0; // the loop variable is kept outside the scope of the loop so we can // use it at the end // int32 index; for (index = 0; index < len; index++) { // detect a change from zero to one // if ((state == ZERO) && (in_a(index) != OFF)) { state = ONE; // for all but the first output we need a delimiter // if (first) { first = false; } else { out_a.concat(L","); } out_a.concat(index); cur_len = 1; } // for state 1, either increment the count if we get another ON or // transition to state 0 if we get a OFF. // else if (state == ONE) { if (in_a(index) == ON) { cur_len++; } // detect a change from one to zero // else { state = ZERO; // if there was more than one ON in a row we need to output the range // if (cur_len > 1) { out_a.concat(L"-"); out_a.concat(index - 1); } } } } // if there was more than one ON in a row at the end we need to // output the range // if ((state == ONE) && (cur_len > 1)) { out_a.concat(L"-"); out_a.concat(index - 1); } // exit gracefully // return true; } // method: insert // // arguments: // VectorByte& mask: (input/output) mask vector // int32 start_index: (input) start index // int32 num_elem: (input) number of elements // byte mode: (input) byte mode (0 or, 1) // // return: a bool8 value indicating status // // this method inserts given byte mode (OFF or ON) in mask vector // bool8 Mask::insert(VectorByte& mask_a, int32 start_index_a, int32 num_elem_a, byte8 mode_a) { int32 len = mask_a.length(); int32 end_index = start_index_a + num_elem_a; // check the argument // if (end_index > len) { return Error::handle(name(), L"insert", Error::ARG, __FILE__, __LINE__); } for (int32 i = start_index_a; i < end_index; i++) { mask_a(i) = mode_a; } // exit gracefully // return true; }