mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 07:30:04 +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
 | 
