Example #1
0
void
StreamBuffer::pop(UInt32 n)
{
	// discard all chunks if n is greater than or equal to m_size
	if (n >= m_size) {
		m_size     = 0;
		m_headUsed = 0;
		m_chunks.clear();
		return;
	}

	// update size
	m_size -= n;

	// discard chunks until more than n bytes would've been discarded
	ChunkList::iterator scan = m_chunks.begin();
	assert(scan != m_chunks.end());
	while (scan->size() - m_headUsed <= n) {
		n         -= (UInt32)scan->size() - m_headUsed;
		m_headUsed = 0;
		scan       = m_chunks.erase(scan);
		assert(scan != m_chunks.end());
	}

	// remove left over bytes from the head chunk
	if (n > 0) {
		m_headUsed += n;
	}
}
Example #2
0
const void*
StreamBuffer::peek(UInt32 n)
{
	assert(n <= m_size);

	// if requesting no data then return NULL so we don't try to access
	// an empty list.
	if (n == 0) {
		return NULL;
	}

	// reserve space in first chunk
	ChunkList::iterator head = m_chunks.begin();
	head->reserve(n + m_headUsed);

	// consolidate chunks into the first chunk until it has n bytes
	ChunkList::iterator scan = head;
	++scan;
	while (head->size() - m_headUsed < n && scan != m_chunks.end()) {
		head->insert(head->end(), scan->begin(), scan->end());
		scan = m_chunks.erase(scan);
	}

	return reinterpret_cast<const void*>(&(head->begin()[m_headUsed]));
}
Example #3
0
void
StreamBuffer::write(const void* vdata, UInt32 n)
{
	assert(vdata != NULL);

	// ignore if no data, otherwise update size
	if (n == 0) {
		return;
	}
	m_size += n;

	// cast data to bytes
	const UInt8* data = reinterpret_cast<const UInt8*>(vdata);

	// point to last chunk if it has space, otherwise append an empty chunk
	ChunkList::iterator scan = m_chunks.end();
	if (scan != m_chunks.begin()) {
		--scan;
		if (scan->size() >= kChunkSize) {
			++scan;
		}
	}
	if (scan == m_chunks.end()) {
		scan = m_chunks.insert(scan, Chunk());
	}

	// append data in chunks
	while (n > 0) {
		// choose number of bytes for next chunk
		assert(scan->size() <= kChunkSize);
		UInt32 count = kChunkSize - (UInt32)scan->size();
		if (count > n)
			count = n;

		// transfer data
		scan->insert(scan->end(), data, data + count);
		n    -= count;
		data += count;

		// append another empty chunk if we're not done yet
		if (n > 0) {
			++scan;
			scan = m_chunks.insert(scan, Chunk());
		}
	}
}
Example #4
0
File: heap.cpp Project: gatgui/fbpg
bool Heap::deallocate(void *ptr, size_t sz) {
  if (ptr < mHeap || ptr >= end()) {
    return false;
  }
  
  mUsedSize -= sz;
  
  Chunk chunk = {ptr, sz};
  
  ChunkList::iterator it = std::lower_bound(mChunks.begin(), mChunks.end(), chunk);
  
  if (it != mChunks.begin()) {
    // have a previous chunk
    ChunkList::iterator pit = it;
    --pit;
    
    if (it == mChunks.end()) {
      // no next chunk
      if (pit->end() == ptr) {
        PrintDebug("Merge with prev free chunk");
        pit->size += sz;
        
      } else {
        PrintDebug("Add new free chunk");
        mChunks.insert(it, chunk);
      }
      
    } else {
      // also have next chunk
      if (pit->end() == ptr) {
        PrintDebug("Merge with prev free chunk");
        pit->size += sz;
        
        if (pit->end() == it->start) {
          PrintDebug("Merge with next free chunk");
          pit->size += it->size;
          mChunks.erase(it);
          
        }
        
      } else {
        if (offset(ptr, sz) == it->start) {
          PrintDebug("Merge with next free chunk");
          it->start = ptr;
          it->size += sz;
        
        } else {
          PrintDebug("Add new free chunk");
          mChunks.insert(it, chunk);
        }
      }
    }
    
  } else {
    // no previous chunk
    if (it == mChunks.end()) {
      // no next chunk
      PrintDebug("Add new free chunk");
      mChunks.insert(it, chunk);
      
    } else {
      // have next chunk
      if (offset(ptr, sz) == it->start) {
        PrintDebug("Merge with next free chunk");
        it->start = ptr;
        it->size += sz;
        
      } else {
        PrintDebug("Add new free chunk");
        mChunks.insert(it, chunk);
        
      }
    }
  }
  
  /*
  ChunkList::iterator it = std::lower_bound(mChunks.begin(), mChunks.end(), chunk);
  
  if (it != mChunks.begin()) {
    // have a previous chunk
    ChunkList::iterator pit = it;
    --pit;
    
    if (it == mChunks.end()) {
      // no next chunk
      
    } else {
      // also have next chunk
    }
    
  } else {
    // no previous chunk
    if (it == mChunks.end()) {
      // no next chunk
      
    } else {
      // have next chunk
    }
  }
  
  if (it != mChunks.end()) {
    // it points to next available chunk
    if (offset(ptr, sz) < it->start) {
      if (it != mChunks.begin()) {
        // theres also a previous chunck
        ChunkList::iterator pit = it;
        --pit;
        if (ptr > pit->end()) {
#ifdef _DEBUG
          std::cerr << "### Add new free chunk" << std::endl;
#endif
          mChunks.insert(it, chunk);
        } else {
#ifdef _DEBUG
          std::cerr << "### Merge with previous free chunk" << std::endl;
#endif
          // merge with prev
          pit->size += sz;
        }
      } else {
        mChunks.insert(it, chunk);
      }
    } else {
      // merge with next
#ifdef _DEBUG
      std::cerr << "### Merge with next free chunk" << std::endl;
#endif
      it->start = ptr;
      it->size += sz;
    }
  
  } else {
    ChunkList::iterator pit = it;
    --pit;
    if (ptr > pit->end()) {
#ifdef _DEBUG
      std::cerr << "### Add new free chunk" << std::endl;
#endif
      mChunks.insert(it, chunk);
    } else {
      // merge with prev
#ifdef _DEBUG
      std::cerr << "### Merge with previous free chunk" << std::endl;
#endif
      pit->size += sz;
    }
  }
  */
  
  return true;
}