istringstream_nocopy: Implement in a standards-compliant way.
Fixes the problem mentioned in e6a61b8da7
See #1135
			
			
This commit is contained in:
		
							parent
							
								
									1cf4801108
								
							
						
					
					
						commit
						4fc30922cf
					
				
					 4 changed files with 89 additions and 15 deletions
				
			
		|  | @ -152,7 +152,7 @@ static StringSet parseStrings(std::istream & str, bool arePaths) | ||||||
| static Derivation parseDerivation(const string & s) | static Derivation parseDerivation(const string & s) | ||||||
| { | { | ||||||
|     Derivation drv; |     Derivation drv; | ||||||
|     std::istringstream str(s); |     istringstream_nocopy str(s); | ||||||
|     expect(str, "Derive(["); |     expect(str, "Derive(["); | ||||||
| 
 | 
 | ||||||
|     /* Parse the list of outputs. */ |     /* Parse the list of outputs. */ | ||||||
|  |  | ||||||
|  | @ -117,17 +117,6 @@ S3Helper::DownloadResult S3Helper::getObject( | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #if __linux__ |  | ||||||
| 
 |  | ||||||
| struct istringstream_nocopy : public std::stringstream |  | ||||||
| { |  | ||||||
|     istringstream_nocopy(const std::string & s) |  | ||||||
|     { |  | ||||||
|         rdbuf()->pubsetbuf( |  | ||||||
|             (char *) s.data(), s.size()); |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore | struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore | ||||||
| { | { | ||||||
|     std::string bucketName; |     std::string bucketName; | ||||||
|  | @ -313,8 +302,6 @@ static RegisterStoreImplementation regStore([]( | ||||||
|     return store; |     return store; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -104,7 +104,7 @@ Hash parseHash(HashType ht, const string & s) | ||||||
|         string s2(s, i * 2, 2); |         string s2(s, i * 2, 2); | ||||||
|         if (!isxdigit(s2[0]) || !isxdigit(s2[1])) |         if (!isxdigit(s2[0]) || !isxdigit(s2[1])) | ||||||
|             throw BadHash(format("invalid hash ‘%1%’") % s); |             throw BadHash(format("invalid hash ‘%1%’") % s); | ||||||
|         std::istringstream str(s2); |         istringstream_nocopy str(s2); | ||||||
|         int n; |         int n; | ||||||
|         str >> std::hex >> n; |         str >> std::hex >> n; | ||||||
|         hash.hash[i] = n; |         hash.hash[i] = n; | ||||||
|  |  | ||||||
|  | @ -449,4 +449,91 @@ struct ReceiveInterrupts | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>> | ||||||
|  | class basic_istringbuf_nocopy : public std::basic_streambuf<CharT, Traits> | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     typedef std::basic_string<CharT, Traits, Allocator> string_type; | ||||||
|  | 
 | ||||||
|  |     typedef typename std::basic_streambuf<CharT, Traits>::off_type off_type; | ||||||
|  | 
 | ||||||
|  |     typedef typename std::basic_streambuf<CharT, Traits>::pos_type pos_type; | ||||||
|  | 
 | ||||||
|  |     typedef typename std::basic_streambuf<CharT, Traits>::int_type int_type; | ||||||
|  | 
 | ||||||
|  |     typedef typename std::basic_streambuf<CharT, Traits>::traits_type traits_type; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     const string_type & s; | ||||||
|  | 
 | ||||||
|  |     off_type off; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     basic_istringbuf_nocopy(const string_type & s) : s{s}, off{0} | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) | ||||||
|  |     { | ||||||
|  |         if (which & std::ios_base::in) { | ||||||
|  |             this->off = dir == std::ios_base::beg | ||||||
|  |                 ? off | ||||||
|  |                 : (dir == std::ios_base::end | ||||||
|  |                     ? s.size() + off | ||||||
|  |                     : this->off + off); | ||||||
|  |         } | ||||||
|  |         return pos_type(this->off); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pos_type seekpos(pos_type pos, std::ios_base::openmode which) | ||||||
|  |     { | ||||||
|  |         return seekoff(pos, std::ios_base::beg, which); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::streamsize showmanyc() | ||||||
|  |     { | ||||||
|  |         return s.size() - off; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int_type underflow() | ||||||
|  |     { | ||||||
|  |         if (typename string_type::size_type(off) == s.size()) | ||||||
|  |             return traits_type::eof(); | ||||||
|  |         return traits_type::to_int_type(s[off]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int_type uflow() | ||||||
|  |     { | ||||||
|  |         if (typename string_type::size_type(off) == s.size()) | ||||||
|  |             return traits_type::eof(); | ||||||
|  |         return traits_type::to_int_type(s[off++]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int_type pbackfail(int_type ch) | ||||||
|  |     { | ||||||
|  |         if (off == 0 || (ch != traits_type::eof() && ch != s[off - 1])) | ||||||
|  |             return traits_type::eof(); | ||||||
|  | 
 | ||||||
|  |         return traits_type::to_int_type(s[--off]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>> | ||||||
|  | class basic_istringstream_nocopy : public std::basic_iostream<CharT, Traits> | ||||||
|  | { | ||||||
|  |     typedef basic_istringbuf_nocopy<CharT, Traits, Allocator> buf_type; | ||||||
|  |     buf_type buf; | ||||||
|  | public: | ||||||
|  |     basic_istringstream_nocopy(const typename buf_type::string_type & s) : | ||||||
|  |         std::basic_iostream<CharT, Traits>(&buf), buf(s) {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* A variant of std::istringstream that doesn't its string
 | ||||||
|  |    argument. This is useful for large strings. The caller must ensure | ||||||
|  |    that the string object is not destroyed while it's referenced by | ||||||
|  |    this object. */ | ||||||
|  | typedef basic_istringstream_nocopy<char> istringstream_nocopy; | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue