Widget2 * get_previous_focus(Widget2 * w, bool loop) { CompositeContainer::iterator iter; if (!w) { REDASSERT(!loop); if ((iter = this->impl->get_last()) == reinterpret_cast<CompositeContainer::iterator>(CompositeContainer::invalid_iterator)) { return nullptr; } w = this->impl->get(iter); if ((w->tab_flag != Widget2::IGNORE_TAB) && (w->focus_flag != Widget2::IGNORE_FOCUS)) { return w; } } else { iter = this->impl->find(w); REDASSERT(iter != reinterpret_cast<CompositeContainer::iterator>(CompositeContainer::invalid_iterator)); } CompositeContainer::iterator future_focus_iter; while ((future_focus_iter = this->impl->get_previous(iter, loop)) != reinterpret_cast<CompositeContainer::iterator>(CompositeContainer::invalid_iterator)) { Widget2 * future_focus_w = this->impl->get(future_focus_iter); if ((future_focus_w->tab_flag != Widget2::IGNORE_TAB) && (future_focus_w->focus_flag != Widget2::IGNORE_FOCUS)) { return future_focus_w; } if (future_focus_w == w) { break; } iter = future_focus_iter; } return nullptr; }
void * set_meta_data(uint16_t row_index, uint16_t column_index, void * meta_data) { REDASSERT(column_index <= this->nb_columns); REDASSERT(row_index <= GRID_NB_ROWS_MAX); void * res = this->meta_data[column_index][row_index]; this->meta_data[column_index][row_index] = meta_data; return res; }
void compress(const uint8_t * const data, size_t data_length, bool end) { if (this->verbose) { LOG(LOG_INFO, "GZipCompressionOutTransport::compress: uncompressed_data_length=%u", data_length); } if (this->verbose & 0x4) { LOG(LOG_INFO, "GZipCompressionOutTransport::compress: end=%s", (end ? "true" : "false")); } const int flush = (end ? Z_FINISH : Z_NO_FLUSH); this->compression_stream.avail_in = data_length; this->compression_stream.next_in = const_cast<uint8_t *>(data); uint8_t temp_compressed_data[GZIP_COMPRESSION_TRANSPORT_BUFFER_LENGTH]; do { this->compression_stream.avail_out = sizeof(temp_compressed_data); this->compression_stream.next_out = reinterpret_cast<unsigned char *>(temp_compressed_data); int ret = ::deflate(&this->compression_stream, flush); if (this->verbose & 0x2) { LOG(LOG_INFO, "GZipCompressionOutTransport::compress: deflate return %d", ret); } (void)ret; REDASSERT(ret != Z_STREAM_ERROR); if (this->verbose & 0x2) { LOG( LOG_INFO , "GZipCompressionOutTransport::compress: compressed_data_capacity=%u avail_out=%u" , sizeof(temp_compressed_data), this->compression_stream.avail_out); } const size_t temp_compressed_data_length = sizeof(temp_compressed_data) - this->compression_stream.avail_out; if (this->verbose) { LOG( LOG_INFO , "GZipCompressionOutTransport::compress: temp_compressed_data_length=%u" , temp_compressed_data_length); } for (size_t number_of_bytes_copied = 0; number_of_bytes_copied < temp_compressed_data_length; ) { const size_t number_of_bytes_to_copy = std::min<size_t>( sizeof(this->compressed_data) - this->compressed_data_length , temp_compressed_data_length - number_of_bytes_copied); ::memcpy( this->compressed_data + this->compressed_data_length , temp_compressed_data + number_of_bytes_copied , number_of_bytes_to_copy); this->compressed_data_length += number_of_bytes_to_copy; number_of_bytes_copied += number_of_bytes_to_copy; if (this->compressed_data_length == sizeof(this->compressed_data)) { this->send_to_target(); } } } while (this->compression_stream.avail_out == 0); REDASSERT(this->compression_stream.avail_in == 0); }
/** @brief Determine the block number of an inode. @param ulInode The inode number. @param bWhich Which copy of the inode. @return The block number of the inode. */ static uint32_t InodeBlock( uint32_t ulInode, uint8_t bWhich) { REDASSERT(INODE_IS_VALID(ulInode)); REDASSERT(bWhich <= 1U); return gpRedCoreVol->ulInodeTableStartBN + ((ulInode - INODE_FIRST_VALID) * 2U) + bWhich; }
explicit SnappyCompressionOutTransport(Transport & tt, uint32_t verbose = 0) : Transport() , target_transport(tt) , uncompressed_data() , uncompressed_data_length(0) { this->verbose = verbose; REDASSERT(::snappy_max_compressed_length(MAX_UNCOMPRESSED_DATA_LENGTH) <= SNAPPY_COMPRESSION_TRANSPORT_BUFFER_LENGTH); REDASSERT(MAX_UNCOMPRESSED_DATA_LENGTH <= 0xFFFF); // 0xFFFF (for uint16_t) }
Widget2 * set_widget(uint16_t row_index, uint16_t column_index, Widget2 * w, void * meta_data = nullptr) { REDASSERT(column_index <= this->nb_columns); REDASSERT(row_index <= GRID_NB_ROWS_MAX); Widget2 * res = this->widgets[column_index][row_index]; this->widgets[column_index][row_index] = w; this->meta_data[column_index][row_index] = meta_data; return res; }
void remove(const Widget2 * w) override { REDASSERT(w); REDASSERT(this->children_count); auto last = this->child_table + this->children_count; auto it = std::find(&this->child_table[0], last, w); REDASSERT(it != last); if (it != last) { auto new_last = std::copy(it+1, last, it); *new_last = nullptr; this->children_count--; } }
/** @brief Convert a hexadecimal ASCII number into a D_UINT64 value. The function processes all hex digits up to a NUL-terminator, or to the first non-hex character. Only hexadecimal digits are processed, so leading white space, or a leading "0x" prefix are not allowed. If pachNum points to an empty string (points to a NUL), this function will return NULL, and the value at *pulNum will not be modified. @note This function does not check for overflow. If there are more significant digits than can be represented in a uint64_t variable, the output is unspecified. @param pszNum A pointer to a constant array of hex characters. @param pullNum A pointer to the location in which to store the uint64_t result. Upon return, this value will be modified ONLY if the function succeeds and the returned pointer is valid (not NULL). @return A pointer to the byte following the converted number, or NULL to indicate failure. */ const char *RedHtoULL( const char *pszNum, uint64_t *pullNum) { uint64_t ullValue = 0U; const char *pszReturn = NULL; uint32_t ulIdx = 0U; REDASSERT(pszNum != NULL); REDASSERT(pullNum != NULL); while(pszNum[ulIdx] != '\0') { char cDigit = pszNum[ulIdx]; if(ISDIGIT(cDigit)) { cDigit -= '0'; } else if(ISHEXDIGITU(cDigit)) { cDigit -= ('A' - 10); } else if(ISHEXDIGITL(cDigit)) { cDigit -= ('a' - 10); } else { break; } REDASSERT((ullValue & UINT64_SUFFIX(0xF000000000000000)) == 0U); ullValue <<= 4U; ullValue += cDigit; ulIdx++; pszReturn = &pszNum[ulIdx]; } /* Modify the number returned only if we found one or more valid hex digits. */ if(pszReturn != NULL) { *pullNum = ullValue; } return pszReturn; }
/** @brief Calculate the block number of the imap node location indicated by the given metaroot. An imap node has two locations on disk. A bit in the metaroot bitmap indicates which location is the valid one, according to that metaroot. This function returns the block number of the imap node which is valid in the given metaroot. @param bMR Which metaroot to examine. @param ulImapNode The imap node for which to calculate the block number. @return Block number of the imap node, as indicated by the given metaroot. */ uint32_t RedImapNodeBlock( uint8_t bMR, uint32_t ulImapNode) { uint32_t ulBlock; REDASSERT(ulImapNode < gpRedCoreVol->ulImapNodeCount); ulBlock = gpRedCoreVol->ulImapStartBN + (ulImapNode * 2U); if(bMR > 1U) { REDERROR(); } else if(RedBitGet(gpRedCoreVol->aMR[bMR].abEntries, ulImapNode)) { /* Bit is set, so point ulBlock at the second copy of the node. */ ulBlock++; } else { /* ulBlock already points at the first copy of the node. */ } return ulBlock; }
inline static char * in_place_windows_to_linux_newline_convert(char * s) { char * src, * dest; REDASSERT(s); src = dest = s; char * p; while ((p = strstr(src, "\r\n"))) { const size_t n = p - src; if ((dest != src) && n) { memmove(dest, src, n); } dest += n; src = p + 2; *dest = '\n'; dest++; } memmove(dest, src, strlen(src) + 1); return s; }
void configure_wait_object(wait_obj & wait_object) const override { REDASSERT(!wait_object.waked_up_by_time); wait_object.object_and_time = true; wait_object.set(1000000); }
/** @brief Write out a dirty buffer. @param bIdx The index of the buffer to write. @return A negated ::REDSTATUS code indicating the operation result. @retval 0 Operation was successful. @retval -RED_EIO A disk I/O error occurred. @retval -RED_EINVAL Invalid parameters. */ static REDSTATUS BufferWrite( uint8_t bIdx) { REDSTATUS ret = 0; if(bIdx < REDCONF_BUFFER_COUNT) { const BUFFERHEAD *pHead = &gBufCtx.aHead[bIdx]; REDASSERT((pHead->uFlags & BFLAG_DIRTY) != 0U); if((pHead->uFlags & BFLAG_META) != 0U) { ret = BufferFinalize(gBufCtx.b.aabBuffer[bIdx], pHead->bVolNum, pHead->uFlags); } if(ret == 0) { ret = RedIoWrite(pHead->bVolNum, pHead->ulBlock, 1U, gBufCtx.b.aabBuffer[bIdx]); #ifdef REDCONF_ENDIAN_SWAP BufferEndianSwap(gBufCtx.b.aabBuffer[bIdx], pHead->uFlags); #endif } } else { REDERROR(); ret = -RED_EINVAL; } return ret; }
bool run(const wait_obj & wait_object) override { if (this->data_length <= CHANNELS::CHANNEL_CHUNK_LENGTH) { this->to_server_sender(this->data_length, this->flags, this->data.get(), this->data_length); this->remaining_number_of_bytes_to_send = 0; return false; } REDASSERT(this->remaining_number_of_bytes_to_send); uint32_t out_flags = this->flags; if (this->remaining_number_of_bytes_to_send != this->data_length) { out_flags &= ~CHANNELS::CHANNEL_FLAG_FIRST; } uint32_t number_of_bytes_sent = this->data_length - this->remaining_number_of_bytes_to_send; uint32_t number_of_bytes_to_send = std::min<uint32_t>(this->remaining_number_of_bytes_to_send, CHANNELS::CHANNEL_CHUNK_LENGTH); if (number_of_bytes_to_send != this->remaining_number_of_bytes_to_send) { out_flags &= ~CHANNELS::CHANNEL_FLAG_LAST; } this->to_server_sender(this->data_length, out_flags, this->data.get() + number_of_bytes_sent, number_of_bytes_to_send); this->remaining_number_of_bytes_to_send -= number_of_bytes_to_send; return (this->remaining_number_of_bytes_to_send != 0); }
/** @brief Retrieve the size of a file. @param bVolNum The volume number of the file whose size is being read. @param ulFileNum The file number of the file whose size is being read. @return The size of the file (nonnegative) or a negated ::REDSTATUS code indicating the operation result (negative). @retval >=0 The size of the file. @retval -RED_EBADF @p ulFileNum is not a valid file number. @retval -RED_EINVAL @p bVolNum is an invalid volume number or not mounted. @retval -RED_EIO A disk I/O error occurred. */ int64_t RedFseSizeGet( uint8_t bVolNum, uint32_t ulFileNum) { int64_t ret; ret = FseEnter(bVolNum); if(ret == 0) { uint64_t ullSize; ret = RedCoreFileSizeGet(ulFileNum, &ullSize); FseLeave(); if(ret == 0) { /* Unless there is an on-disk format change, the maximum file size is guaranteed to be less than INT64_MAX, and so it can be safely returned in an int64_t. */ REDASSERT(ullSize < (uint64_t)INT64_MAX); ret = (int64_t)ullSize; } } return ret; }
uint16_t set_nb_rows(uint16_t nb_rows) { REDASSERT(nb_rows < GRID_NB_ROWS_MAX); uint16_t old_nb_rows = this->nb_rows; this->nb_rows = nb_rows; return old_nb_rows; }
WidgetGrid(gdi::GraphicApi & drawable, const Rect & rect, Widget2 & parent, NotifyApi * notifier, uint16_t nb_rows, uint16_t nb_columns, uint32_t bg_color_1, uint32_t fg_color_1, uint32_t bg_color_2, uint32_t fg_color_2, uint32_t bg_color_focus, uint32_t fg_color_focus, uint32_t bg_color_selection, uint32_t fg_color_selection, uint16_t border = 0, int group_id = 0) : Widget2(drawable, rect, parent, notifier, group_id) , widgets() , meta_data() , nb_rows(nb_rows) , nb_columns(nb_columns) , column_width() , row_height() , bg_color_1(bg_color_1) , fg_color_1(fg_color_1) , bg_color_2(bg_color_2) , fg_color_2(fg_color_2) , bg_color_focus(bg_color_focus) , fg_color_focus(fg_color_focus) , bg_color_selection(bg_color_selection) , fg_color_selection(fg_color_selection) , border(border) , selection_y(static_cast<uint16_t>(-1u)) , click_interval() { REDASSERT(nb_columns <= GRID_NB_COLUMNS_MAX); }
/** @brief Leave the file system driver. */ static void FseLeave(void) { REDASSERT(gfFseInited); #if REDCONF_TASK_COUNT > 1U RedOsMutexRelease(); #endif }
// A multi-sz contains a sequence of null-terminated strings, // terminated by an empty string (\0) so that the last two // characters are both null terminators. inline static void SOHSeparatedStringsToMultiSZ(char * dest, size_t dest_size, const char * src) { REDASSERT(dest_size > 1); char const * e = src + dest_size - 2; for (; src != e && *src; ++dest, ++src) { *dest = ('\x01' == *src) ? '\0' : *src; } memset(dest, 0, e-src + 2); }
virtual void do_recv(char ** pbuffer, size_t len) { char * temp_buffer = *pbuffer; size_t temp_length = len; while (temp_length) { if (this->uncompressed_data_size) { REDASSERT(this->uncompressed_data); const size_t data_length = std::min<size_t>(temp_length, this->uncompressed_data_size); ::memcpy(temp_buffer, this->uncompressed_data, data_length); this->uncompressed_data += data_length; this->uncompressed_data_size -= data_length; temp_buffer += data_length; temp_length -= data_length; } else { this->uncompressed_buffer_stream.reset(); this->source_transport.recv( &this->uncompressed_buffer_stream.end , 4 // reset_compressor((1) + compressed_type(1) + data_size(2) ); if (this->uncompressed_buffer_stream.in_uint8() == 1) { this->mppc_dec.~rdp_mppc_61_dec(); new (&this->mppc_dec) rdp_mppc_61_dec; } uint8_t compressed_type = this->uncompressed_buffer_stream.in_uint8(); uint16_t data_size = this->uncompressed_buffer_stream.in_uint16_le(); //LOG(LOG_INFO, "do_recv: data_size=%u", data_size); this->compressed_buffer_stream.reset(); this->source_transport.recv(&this->compressed_buffer_stream.end, data_size); this->uncompressed_buffer_stream.reset(); if (compressed_type & PACKET_COMPRESSED) { this->uncompressed_data = this->uncompressed_buffer_stream.get_data(); this->mppc_dec.decompress(this->compressed_buffer_stream.get_data(), data_size, compressed_type, this->uncompressed_data, this->uncompressed_data_size); } else { this->uncompressed_data = this->compressed_buffer_stream.get_data(); this->uncompressed_data_size = data_size; } } } (*pbuffer) = (*pbuffer) + len; }
bool run(const wait_obj & wait_object) override { REDASSERT(this->chunked_data_length <= CHANNELS::CHANNEL_CHUNK_LENGTH); this->to_server_sender(this->total_length, this->flags, this->chunked_data.get(), this->chunked_data_length); return false; }
virtual void draw_children(const Rect & clip) { CompositeContainer::iterator iter_w_current = this->impl->get_first(); while (iter_w_current != reinterpret_cast<CompositeContainer::iterator>(CompositeContainer::invalid_iterator)) { Widget2 * w = this->impl->get(iter_w_current); REDASSERT(w); w->refresh(clip.intersect(w->rect)); iter_w_current = this->impl->get_next(iter_w_current); } }
void set_widget_focus(Widget2 * new_focused, int reason) { REDASSERT(new_focused); if (new_focused != this->current_focus) { if (this->current_focus) { this->current_focus->blur(); } this->current_focus = new_focused; } this->current_focus->focus(reason); }
/** @brief Release a buffer. @param pBuffer The buffer to release. */ void RedBufferPut( const void *pBuffer) { uint8_t bIdx; if(!BufferToIdx(pBuffer, &bIdx)) { REDERROR(); } else { REDASSERT(gBufCtx.aHead[bIdx].bRefCount > 0U); gBufCtx.aHead[bIdx].bRefCount--; if(gBufCtx.aHead[bIdx].bRefCount == 0U) { REDASSERT(gBufCtx.uNumUsed > 0U); gBufCtx.uNumUsed--; } } }
inline void get_match_length(const uint8_t * output_data, uint16_t output_data_size, const uint8_t * history_data, uint32_t history_data_size, uint16_t & MatchLength, uint32_t & MatchHistoryOffset) { MatchLength = 0; MatchHistoryOffset = 0; if (history_data_size < RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH) { return; } REDASSERT(output_data_size >= RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH); const uint8_t * history_data_begin = history_data; const uint8_t * history_data_end = history_data_begin + history_data_size - (RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH - 1); while (history_data_begin != history_data_end) { REDASSERT(history_data_begin <= history_data_end); if (memcmp(output_data, history_data_begin, RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH)) { history_data_begin++; continue; } uint16_t CurrentMatchLength = RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH; const uint8_t * o = output_data + CurrentMatchLength; const uint8_t * h = history_data_begin + CurrentMatchLength; for (; (o < output_data + output_data_size) && (h < history_data + history_data_size) && (*o == *h); o++, h++, CurrentMatchLength++); if (CurrentMatchLength > MatchLength) { if (MatchLength > 0) { history_data_end = history_data + history_data_size - (CurrentMatchLength - 1); } MatchLength = CurrentMatchLength; MatchHistoryOffset = history_data_begin - history_data; } history_data_begin++; } }
/** @brief Discard a buffer, releasing it and marking it invalid. @param pBuffer The buffer to discard. */ void RedBufferDiscard( const void *pBuffer) { uint8_t bIdx; if(!BufferToIdx(pBuffer, &bIdx)) { REDERROR(); } else { REDASSERT(gBufCtx.aHead[bIdx].bRefCount == 1U); REDASSERT(gBufCtx.uNumUsed > 0U); gBufCtx.aHead[bIdx].bRefCount = 0U; gBufCtx.aHead[bIdx].ulBlock = BBLK_INVALID; gBufCtx.uNumUsed--; BufferMakeLRU(bIdx); } }
/** @brief Branch a buffer, marking it dirty and assigning a new block number. @param pBuffer The buffer to branch. @param ulBlockNew The new block number for the buffer. */ void RedBufferBranch( const void *pBuffer, uint32_t ulBlockNew) { uint8_t bIdx; if( !BufferToIdx(pBuffer, &bIdx) || (ulBlockNew >= gpRedVolume->ulBlockCount)) { REDERROR(); } else { BUFFERHEAD *pHead = &gBufCtx.aHead[bIdx]; REDASSERT(pHead->bRefCount > 0U); REDASSERT((pHead->uFlags & BFLAG_DIRTY) == 0U); pHead->uFlags |= BFLAG_DIRTY; pHead->ulBlock = ulBlockNew; } }
void do_recv(char ** pbuffer, size_t len) override { uint8_t * temp_data = reinterpret_cast<uint8_t *>(*pbuffer); size_t temp_data_length = len; while (temp_data_length) { if (this->uncompressed_data_length) { REDASSERT(this->uncompressed_data); const size_t data_length = std::min<size_t>(temp_data_length, this->uncompressed_data_length); ::memcpy(temp_data, this->uncompressed_data, data_length); this->uncompressed_data += data_length; this->uncompressed_data_length -= data_length; temp_data += data_length; temp_data_length -= data_length; } else { BStream data_stream(SNAPPY_COMPRESSION_TRANSPORT_BUFFER_LENGTH); this->source_transport.recv(&data_stream.end, sizeof(uint16_t)); // compressed_data_length(2); const uint16_t compressed_data_length = data_stream.in_uint16_le(); if (this->verbose) { LOG(LOG_INFO, "SnappyCompressionInTransport::do_recv: compressed_data_length=%u", compressed_data_length); } data_stream.reset(); this->source_transport.recv(&data_stream.end, compressed_data_length); this->uncompressed_data = this->uncompressed_data_buffer; this->uncompressed_data_length = sizeof(this->uncompressed_data_buffer); snappy_status status = ::snappy_uncompress( reinterpret_cast<char *>(data_stream.get_data()) , data_stream.size() , reinterpret_cast<char *>(this->uncompressed_data), &this->uncompressed_data_length); if (this->verbose & 0x2 || (status != SNAPPY_OK)) { LOG( ((status != SNAPPY_OK) ? LOG_ERR : LOG_INFO) , "SnappyCompressionInTransport::do_recv: snappy_uncompress return %d", status); } if (this->verbose) { LOG( LOG_INFO, "SnappyCompressionInTransport::do_recv: uncompressed_data_length=%u" , this->uncompressed_data_length); } } } (*pbuffer) = (*pbuffer) + len; }
virtual void find_match(const uint8_t * historyBuffer, uint32_t historyOffset, uint16_t uncompressed_data_size) { if (uncompressed_data_size < RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH) return; this->match_details_stream.reset(); uint32_t history_data_size = historyOffset; uint16_t output_data_length = uncompressed_data_size; const uint8_t * output_data_begin = historyBuffer + historyOffset; const uint8_t * output_data_end = output_data_begin + uncompressed_data_size - (RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH - 1); while (output_data_begin < output_data_end) { REDASSERT(output_data_length >= RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH); uint16_t MatchLength; uint32_t MatchHistoryOffset; this->get_match_length(output_data_begin, output_data_length, historyBuffer, history_data_size, MatchLength, MatchHistoryOffset); if (MatchLength) { REDASSERT(MatchLength >= RDP_61_COMPRESSOR_MINIMUM_MATCH_LENGTH); this->match_details_stream.out_uint16_le(MatchLength); //LOG(LOG_INFO, "MatchLength=%d", MatchLength); this->match_details_stream.out_uint16_le(output_data_begin - (historyBuffer + historyOffset)); this->match_details_stream.out_uint32_le(MatchHistoryOffset); history_data_size += MatchLength; output_data_length -= MatchLength; output_data_begin += MatchLength; } else { history_data_size++; output_data_length--; output_data_begin++; } } this->match_details_stream.mark_end(); }
uint16_t add_line(const char ** entries) { REDASSERT(this->nb_rows <= GRID_NB_ROWS_MAX); for (int i = 0; i < this->nb_columns; i++) { bool odd = this->nb_rows & 1; WidgetLabel * label = new WidgetLabel(this->drawable, 0, 0, *this, this, entries[i], true, this->group_id, odd ? this->fg_color_1 : this->fg_color_2, odd ? this->bg_color_1 : this->bg_color_2, this->font, x_padding_label, y_padding_label); label->tool = true; this->set_widget(this->nb_rows, i, label); this->toDelete[i][this->nb_rows] = true; } return this->nb_rows++; }
void move_xy(int16_t x, int16_t y) { CompositeContainer::iterator iter_w_first = this->impl->get_first(); if (iter_w_first != reinterpret_cast<CompositeContainer::iterator>(CompositeContainer::invalid_iterator)) { CompositeContainer::iterator iter_w_current = iter_w_first; do { Widget2 * w = this->impl->get(iter_w_current); REDASSERT(w); w->set_xy(x + w->dx(), y + w->dy()); iter_w_current = this->impl->get_next(iter_w_current); } while ((iter_w_current != iter_w_first) && (iter_w_current != reinterpret_cast<CompositeContainer::iterator>(CompositeContainer::invalid_iterator))); } }