パイプとかファイルディスクリプタとか、そーゆー低レイヤーのはなし | |
---|---|
boost::processの子プロセスの入力を閉じる | https://qiita.com/cielavenir/items/9219162170cf2dd8b144 |
サブプロセス処理をパイプを使わずに行う | https://qiita.com/cielavenir/items/0e69848b705fafec86e1 |
fstreamのファイルディスクリプタを取得する ムーブコンストラクタしかないクラスのprotectedメンバを呼び出す |
https://qiita.com/cielavenir/items/fe892c564e6b12983776 |
boost::processをコピーできないならこういう書き方もできると思います。ファイルを削除してもfdは生きるという特性に依存するのでUnix専用になりますが…。
// g++ zstd.cpp -lboost_thread -lboost_system -lboost_filesystem
// zstd < input_file | ./a.out (and compare printed string to original SHA1)
# include <iostream>
# include <fstream>
# include <boost/uuid/sha1.hpp>
# include <boost/algorithm/hex.hpp>
# include <boost/process/system.hpp>
# include <boost/process/io.hpp>
# include <boost/process/pipe.hpp>
# include <boost/iostreams/copy.hpp>
# include <boost/thread.hpp>
# include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
unsigned int byteswap32(unsigned int n){
const unsigned int m8=0x00ff00ff;
const unsigned int m16=0x0000ffff;
n=((n&m8)<<8)|((n>>8)&m8);
n=((n&m16)<<16)|((n>>16)&m16);
return n;
}
int _SubprocessFilterPushthread(const std::string &cmd, std::istream &in, std::ostream &out){
boost::process::opstream enc;
boost::process::ipstream dec;
boost::process::child c(cmd, boost::process::std_in < enc, boost::process::std_out > dec);
auto fpush = [&]{
/// write to enc ///
boost::iostreams::copy(in, enc);
/// flush enc ///
enc.flush(); // flush is immune to opstream::rdbuf() issue.
//enc.rdbuf()->sync();
enc.pipe().close();
};
boost::thread(boost::ref(fpush));
boost::iostreams::copy(dec, out);
c.wait();
return c.exit_code();
}
int _SubprocessFilterPopthread(const std::string &cmd, std::istream &in, std::ostream &out){
boost::process::opstream enc;
boost::process::ipstream dec;
boost::process::child c(cmd, boost::process::std_in < enc, boost::process::std_out > dec);
auto fpop = [&]{
boost::iostreams::copy(dec, out);
};
boost::thread(boost::ref(fpop));
boost::iostreams::copy(in, enc);
enc.flush();
enc.pipe().close();
c.wait();
return c.exit_code();
}
int _SubprocessFilterTmpfile(const std::string &cmd, std::istream &in, std::ostream &out, bool inIsFile){
FILE* ftmpwrite = NULL;
int fd = _GetFstreamFd(in);
if(fd<0){
ftmpwrite = tmpfile();
fd = fileno(ftmpwrite);
}
std::string writename = std::string("/dev/fd/")+std::to_string(fd);
if(ftmpwrite){
std::ofstream fw(writename.c_str(),std::ios::out);
boost::iostreams::copy(in, fw);
fw.close();
}
FILE* ftmpread = tmpfile();
std::string readname = std::string("/dev/fd/")+std::to_string(fileno(ftmpread));
int r = system((cmd+(inIsFile?" \"":" < \"")+writename+"\" > \""+readname+"\"").c_str());
std::ifstream fr(readname.c_str(),std::ios::in);
boost::iostreams::copy(fr, out);
fr.close();
fclose(ftmpread);
if(ftmpwrite){
fclose(ftmpwrite);
}
return r;
}
int main(){
std::stringstream ss;
//_SubprocessFilterPushthread("zstd -d",std::cin,ss);
//_SubprocessFilterPopthread("zstd -d",std::cin,ss);
_SubprocessFilterTmpfile("zstd -d",std::cin,ss);
{
boost::uuids::detail::sha1 hash;
unsigned int digest[5];
hash.process_bytes(ss.str().data(), ss.str().size());
hash.get_digest((boost::uuids::detail::sha1::digest_type)digest);
for(int i=0;i<5;i++)digest[i]=byteswap32(digest[i]);
std::string result;
boost::algorithm::hex((char*)digest, ((char*)digest) + 20, std::back_inserter(result));
std::cout << result << std::endl;
}
return 0;
}