mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-11-03 23:50:05 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			98 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include <scwx/util/vectorbuf.hpp>
 | 
						|
 | 
						|
namespace scwx
 | 
						|
{
 | 
						|
namespace util
 | 
						|
{
 | 
						|
 | 
						|
vectorbuf::vectorbuf(std::vector<char>& v) : v_(v)
 | 
						|
{
 | 
						|
   update_read_pointers(0);
 | 
						|
}
 | 
						|
 | 
						|
void vectorbuf::update_read_pointers(size_t size)
 | 
						|
{
 | 
						|
   setg(v_.data(), v_.data(), v_.data() + size);
 | 
						|
}
 | 
						|
 | 
						|
vectorbuf::pos_type vectorbuf::seekoff(std::streamoff          off,
 | 
						|
                                       std::ios_base::seekdir  way,
 | 
						|
                                       std::ios_base::openmode which)
 | 
						|
{
 | 
						|
   // Adapted from Microsoft stringbuf reference implementation
 | 
						|
   // Copyright (c) Microsoft Corporation.
 | 
						|
   // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
 | 
						|
   // Change position by off, according to way, which
 | 
						|
   const auto gptrOld  = gptr();
 | 
						|
   const auto pptrOld  = pptr();
 | 
						|
   const auto seekHigh = (pptrOld == nullptr) ? egptr() : pptr();
 | 
						|
 | 
						|
   const auto seekLow  = eback();
 | 
						|
   const auto seekDist = seekHigh - seekLow;
 | 
						|
   off_type   newOffset;
 | 
						|
   switch (way)
 | 
						|
   {
 | 
						|
   case std::ios_base::beg:
 | 
						|
      newOffset = 0;
 | 
						|
      break;
 | 
						|
   case std::ios_base::end:
 | 
						|
      newOffset = seekDist;
 | 
						|
      break;
 | 
						|
   case std::ios_base::cur:
 | 
						|
   {
 | 
						|
      constexpr auto BOTH = std::ios_base::in | std::ios_base::out;
 | 
						|
      if ((which & BOTH) != BOTH)
 | 
						|
      {
 | 
						|
         if (which & std::ios_base::in)
 | 
						|
         {
 | 
						|
            if (gptrOld || !seekLow)
 | 
						|
            {
 | 
						|
               newOffset = gptrOld - seekLow;
 | 
						|
               break;
 | 
						|
            }
 | 
						|
         }
 | 
						|
         else if ((which & std::ios_base::out) && (pptrOld || !seekLow))
 | 
						|
         {
 | 
						|
            newOffset = pptrOld - seekLow;
 | 
						|
            break;
 | 
						|
         }
 | 
						|
      }
 | 
						|
      return pos_type(off_type(-1));
 | 
						|
   }
 | 
						|
 | 
						|
   default:
 | 
						|
      return pos_type(off_type(-1));
 | 
						|
   }
 | 
						|
 | 
						|
   if (static_cast<unsigned long long>(off) + newOffset >
 | 
						|
       static_cast<unsigned long long>(seekDist))
 | 
						|
   {
 | 
						|
      return pos_type(off_type(-1));
 | 
						|
   }
 | 
						|
 | 
						|
   off += newOffset;
 | 
						|
   if (off != 0 && (((which & std::ios_base::in) && !gptrOld) ||
 | 
						|
                    ((which & std::ios_base::out) && !pptrOld)))
 | 
						|
   {
 | 
						|
      return pos_type(off_type(-1));
 | 
						|
   }
 | 
						|
 | 
						|
   const auto next = seekLow + off;
 | 
						|
   if ((which & std::ios_base::in) && gptrOld)
 | 
						|
   {
 | 
						|
      setg(seekLow, next, seekHigh);
 | 
						|
   }
 | 
						|
 | 
						|
   if ((which & std::ios_base::out) && pptrOld)
 | 
						|
   {
 | 
						|
      setp(seekLow, epptr());
 | 
						|
      // If offset is > 4 GB, this won't properly position the put pointer
 | 
						|
      pbump(static_cast<int>(off));
 | 
						|
   }
 | 
						|
 | 
						|
   return pos_type(off);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace util
 | 
						|
} // namespace scwx
 |