コード例 #1
0
ファイル: filereader.cpp プロジェクト: heavilessrose/my-sync
long FileReader::FileSize(int Mode_)
{
  long StartPos_, CurPos_, Diff_;

  if ((Mode_ & ios::out) || (Mode_ & ios::app))
  {
    CurPos_ = tellp();
    seekp(0);
    StartPos_ = tellp();
    seekp(0, ios::end);
    Diff_ = tellp() - StartPos_;
    seekp(CurPos_);
  }
  else if (Mode_ & ios::in)
  {
    CurPos_ = tellg();
    seekg(0);
    StartPos_ = tellg();
    seekg(0, ios::end);
    Diff_ = tellg() - StartPos_;
    seekg(CurPos_);
  }

  return Diff_;
}
コード例 #2
0
ファイル: bitstream.cpp プロジェクト: JohanssonDaniel/Huffman
/* Member function obitstream::size
 * ------------------------------
 * Seek to file end and use tell to retrieve position.
 * In order to not disrupt writing, we also record cur streampos and
 * re-seek to there before returning.
 */
long obitstream::size() {
    if (!is_open()) {
        error("Cannot get size of stream which is not open.");
    }
    clear();					// clear any error state
    streampos cur = tellp();	// save current streampos
    seekp(0, ios::end);			// seek to end
    streampos end = tellp();	// get offset
    seekp(cur);					// seek back to original pos
    return long(end);
}
コード例 #3
0
        ostrstream::ostrstream(char * str, int size, int mode)
: ostream(_new_crt strstreambuf(str,size,str))
{
    delbuf(1);
    if (mode & (ios::app|ios::ate))
        seekp(strlen(str),ios::beg);
}
コード例 #4
0
ファイル: sql_query.cpp プロジェクト: royratcliffe/ta-lib
void SQLQuery::proc(SQLQueryParms& p) {
    seekg (0,ios::beg);
    seekp (0,ios::beg);
    char      num;
    SQLString *ss;
    SQLQueryParms *c;
    for (vector<SQLParseElement>::iterator i = parsed.begin();
            i != parsed.end(); i++) {
        *this << i->before;
        num    = i->num;
        if (num == -1) {
            // do nothing
        } else {
            if (num < (int)p.size()) c = &p;
            else if (num < (int)def.size()) c = &def;
            else {
                *this << " ERROR";
                throw SQLQueryNEParms("Not enough parameters to fill the template.");
            }
            ss = pprepare(i->option, (*c)[num], c->bound());
            *this << *ss;
            if (ss != &(*c)[num]) delete ss;
        }
    }
}
コード例 #5
0
ファイル: sql_query.cpp プロジェクト: royratcliffe/ta-lib
void SQLQuery::reset() {
    seekg (0L,ios::beg);
    seekp (0L,ios::beg);
    parsed.erase(parsed.begin(), parsed.end());
    def.clear();
    clear();
}
コード例 #6
0
ファイル: fstream.hpp プロジェクト: 4nh51rk/innoextract
inline void path_fstream<boost::iostreams::file_descriptor>
	::fix_open_mode(std::ios_base::openmode mode) {
	if((mode & std::ios_base::ate) && is_open()) {
		seekg(0, std::ios_base::end);
		seekp(0, std::ios_base::end);
	}
}
コード例 #7
0
ファイル: bitstream.cpp プロジェクト: JohanssonDaniel/Huffman
/* Member function obitstream::writeBit
 * ----------------------------------
 * If bits remain to be written in curByte, add bit into byte and increment pos
 * Else if end of curByte (or some other write happened), then start a fresh
 * byte at position 0.
 * We write the byte out for each bit (backing up to overwrite as needed), rather
 * than waiting for 8 bits.	 This is because the client might make
 * 3 writeBit calls and then start using << so we can't wait til full-byte
 * boundary to flush any partial-byte bits.
 */
void obitstream::writeBit(int bit) {
    if (bit != 0 && bit != 1) {
        error(string("writeBit must be passed an integer argument of 0 or 1.  You passed the integer ")
              + toPrintable(bit) + " (" + integerToString(bit) + ").");
    }
    if (!is_open()) {
        error("Cannot writeBit to stream which is not open.");
    }

    // if just filled curByte or if data written to stream after last writeBit()
    if (lastTell != tellp() || pos == NUM_BITS_IN_BYTE) {
        curByte = 0;   // zero out byte for next writes
        pos = 0;	   // start writing to first bit of new byte
    }

    if (bit) {
        // only need to change if bit needs to be 1 (byte starts already zeroed)
        SetNthBit(pos, curByte);
    }

    if (pos == 0 || bit) {   // only write if first bit in byte or changing 0 to 1
        if (pos != 0) {
            seekp(-1, ios::cur);   // back up to overwite if pos > 0
        }
        put(curByte);
    }

    pos++; // advance to next bit position for next write
    lastTell = tellp();
}
コード例 #8
0
        strstream::strstream(char * str, int size, int mode)
: iostream(_new_crt strstreambuf(str,size,str))
{
    istream::delbuf(1);
    ostream::delbuf(1);
    if ((mode & ostream::out)  && (mode & (ostream::app|ostream::ate)))
        seekp(strlen(str),ostream::beg);
//  rdbuf()->setg(rdbuf()->base(),rdbuf()->base(),rdbuf()->ebuf());
}
コード例 #9
0
ファイル: Query.cpp プロジェクト: chipitsine/ClickHouse
Query & Query::operator= (const Query & other)
{
    conn = other.conn;

    seekp(0);
    clear();
    *this << other.str();

    return *this;
}
コード例 #10
0
ファイル: query.cpp プロジェクト: ledusledus/meos
void
Query::reset()
{
	seekp(0);
	clear();
	sbuffer_.str("");

	parse_elems_.clear();
	def.clear();
}
コード例 #11
0
ファイル: filereader.cpp プロジェクト: heavilessrose/my-sync
Boolean FileReader::ChangeFileSize(int Mode_, long Size_)
{
  char Blank_ = 0;
  char EofMarker_ = EOF;

  if (!(Mode_ & ios::out) && !(Mode_ & ios::app))
    return FALSE;

  long CurPos_ = tellp();
  seekp(0, ios::end);
  write(&Blank_, 1);
  clear();

  seekp(Size_ + 1);
  write(&EofMarker_, 1);
  seekp(CurPos_);
  clear();

  return TRUE;
}
コード例 #12
0
ファイル: sql_query.cpp プロジェクト: royratcliffe/ta-lib
char * SQLQuery::preview_char() {
    *this << ends;
#ifdef __USLC__
    strstreambuf *tmpbuf = rdbuf();
    uint length = tmpbuf->pcount();
#else
    uint length = pcount();
#endif
    char *s = new char[length+1];
    get(s, length, '\0');
    seekg (0,ios::beg);
    seekp (-1,ios::cur);
    return s;
}
コード例 #13
0
ファイル: Query.cpp プロジェクト: chipitsine/ClickHouse
Query::Query(Connection * conn_, const std::string & query_string) : std::ostream(0), conn(conn_)
{
    /// Важно в случае, если Query используется не из того же потока, что Connection.
    mysql_thread_init();

    init(&query_buf);

    if (!query_string.empty())
    {
        query_buf.str(query_string);
        seekp(0, std::ios::end);
    }

    imbue(std::locale::classic());
}
コード例 #14
0
ファイル: static_streambuf.hpp プロジェクト: xzmagic/Bex
    virtual pos_type seekoff(off_type off
                             , ::std::ios_base::seekdir way
                             , ::std::ios_base::openmode which = ::std::ios_base::in | ::std::ios_base::out)
    {
        bool b_in = (which & ::std::ios_base::in) != 0;
        bool b_out = (which & ::std::ios_base::out) != 0;
        if (b_in && b_out)
        {
            if (way == ::std::ios_base::cur)
                return (::std::streampos)(::std::_BADOFF);

            return seekpg(off, way);
        }
        else if (b_in)
            return seekg(off, way);
        else if (b_out)
            return seekp(off, way);

        return (::std::streampos)(::std::_BADOFF);
    }
コード例 #15
0
ファイル: Query.cpp プロジェクト: chipitsine/ClickHouse
void Query::reset()
{
    seekp(0);
    clear();
    query_buf.str("");
}
コード例 #16
0
int main(int iArgC, char *cArgV[])
{
#ifdef __GLIBCXX__
	// Set a better exception handler
	std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
#endif

	// Disable stdin/printf/etc. sync for a speed boost
	std::ios_base::sync_with_stdio(false);

	// Declare the supported options.
	po::options_description poActions("Actions");
	poActions.add_options()
		("list,l",
			"list files in the archive")

		("extract-all,X",
			"extract all files in the archive")

		("extract,x", po::value<std::string>(),
			"extract a specific file")

		("add,a", po::value<std::string>(),
			"add a file at the end of the archive")

		("insert,i", po::value<std::string>(),
			"add a file at a specific point in the archive")

		("metadata,m",
			"list archive attributes/metadata")

		("set-metadata,e", po::value<std::string>(),
			"change archive attributes/metadata")

		("overwrite,o", po::value<std::string>(),
			"replace a file in the archive with new data")

		("rename,r", po::value<std::string>(),
			"rename a file inside the archive")

		("delete,d", po::value<std::string>(),
			"remove a file from the archive")

		("uncompressed-size,z", po::value<int>(),
			"[with -u only] specify the uncompressed size to use with -i")
	;

	po::options_description poOptions("Options");
	poOptions.add_options()
		("type,t", po::value<std::string>(),
			"specify the archive type (default is autodetect)")
		("list-types",
			"list available formats that can be passed to --type")
		("filetype,y", po::value<std::string>(),
			"specify the file type when inserting (default is generic file)")
		("attribute,b", po::value<std::string>(),
			"specify the file attributes when inserting (optional)")
		("unfiltered,u",
			"do not filter files (no encrypt/decrypt/compress/decompress)")
		("script,s",
			"format output suitable for script parsing")
		("force,f",
			"force open even if the archive is not in the given format")
		("create,c",
			"create a new archive file instead of opening an existing one")
	;

	po::options_description poHidden("Hidden parameters");
	poHidden.add_options()
		("archive", "archive file to manipulate")
		("help", "produce help message")
	;

	po::options_description poVisible("");
	poVisible.add(poActions).add(poOptions);

	po::options_description poComplete("Parameters");
	poComplete.add(poActions).add(poOptions).add(poHidden);
	po::variables_map mpArgs;

	std::string strFilename;
	std::string strType;

	bool bScript = false; // show output suitable for script parsing?
	bool bForceOpen = false; // open anyway even if archive not in given format?
	bool bCreate = false; // create a new archive?
	try {
		po::parsed_options pa = po::parse_command_line(iArgC, cArgV, poComplete);

		// Parse the global command line options
		for (std::vector<po::option>::iterator i = pa.options.begin(); i != pa.options.end(); i++) {
			if (i->string_key.empty()) {
				// If we've already got an archive filename, complain that a second one
				// was given (probably a typo.)
				if (!strFilename.empty()) {
					std::cerr << "Error: unexpected extra parameter (multiple archive "
						"filenames given?!)" << std::endl;
					return RET_BADARGS;
				}
				assert(i->value.size() > 0);  // can't have no values with no name!
				strFilename = i->value[0];
			} else if (i->string_key.compare("help") == 0) {
				std::cout <<
					"Copyright (C) 2010-2016 Adam Nielsen <*****@*****.**>\n"
					"This program comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
					"and you are welcome to change and redistribute it under certain conditions;\n"
					"see <http://www.gnu.org/licenses/> for details.\n"
					"\n"
					"Utility to manipulate archive files used by games to store data files.\n"
					"Build date " __DATE__ " " __TIME__ << "\n"
					"\n"
					"Usage: gamearch <archive> <action> [action...]\n" << poVisible << "\n"
					<< std::endl;
				return RET_OK;
			} else if (
				(i->string_key.compare("list-types") == 0)
			) {
				for (const auto& i : ga::ArchiveManager::formats()) {
					std::string code = i->code();
					std::cout << code;
					int len = code.length();
					if (len < 20) std::cout << std::string(20 - len, ' ');
					std::cout << ' ' << i->friendlyName() << '\n';
				}
				return RET_OK;
			} else if (
				(i->string_key.compare("t") == 0) ||
				(i->string_key.compare("type") == 0)
			) {
				if (i->value.size() == 0) {
					std::cerr << PROGNAME ": --type (-t) requires a parameter.  Use "
						"--list-types to see valid values." << std::endl;
					return RET_BADARGS;
				}
				strType = i->value[0];
			} else if (
				(i->string_key.compare("s") == 0) ||
				(i->string_key.compare("script") == 0)
			) {
				bScript = true;
			} else if (
				(i->string_key.compare("f") == 0) ||
				(i->string_key.compare("force") == 0)
			) {
				bForceOpen = true;
			} else if (
				(i->string_key.compare("u") == 0) ||
				(i->string_key.compare("unfiltered") == 0)
			) {
				bUseFilters = false;
			} else if (
				(i->string_key.compare("c") == 0) ||
				(i->string_key.compare("create") == 0)
			) {
				bCreate = true;
			}
		}

		if (strFilename.empty()) {
			std::cerr << "Error: no game archive filename given" << std::endl;
			return RET_BADARGS;
		}

		std::unique_ptr<stream::file> psArchive;
		if (bCreate && strType.empty()) {
			std::cerr << "Error: You must specify the --type of archive to create"
				<< std::endl;
			return RET_BADARGS;
		}
		std::cout << (bCreate ? "Creating " : "Opening ") << strFilename
			<< " as type " << (strType.empty() ? "<autodetect>" : strType)
			<< std::endl;
		try {
			psArchive = std::make_unique<stream::file>(strFilename, bCreate);
		} catch (const stream::open_error& e) {
			std::cerr << "Error " << (bCreate ? "creating" : "opening")
				<< " archive file " << strFilename << ": " << e.what() << std::endl;
			return RET_SHOWSTOPPER;
		}

		// Get the format handler for this file format
		ga::ArchiveManager::handler_t pArchType;
		if (strType.empty()) {
			// Need to autodetect the file format.
			for (const auto& i : ga::ArchiveManager::formats()) {
				ga::ArchiveType::Certainty cert = i->isInstance(*psArchive);
				switch (cert) {

					case ga::ArchiveType::Certainty::DefinitelyNo:
						// Don't print anything (TODO: Maybe unless verbose?)
						break;

					case ga::ArchiveType::Certainty::Unsure:
						std::cout << "File could be a " << i->friendlyName()
							<< " [" << i->code() << "]" << std::endl;
						// If we haven't found a match already, use this one
						if (!pArchType) pArchType = i;
						break;

					case ga::ArchiveType::Certainty::PossiblyYes:
						std::cout << "File is likely to be a " << i->friendlyName()
							<< " [" << i->code() << "]" << std::endl;
						// Take this one as it's better than an uncertain match
						pArchType = i;
						break;

					case ga::ArchiveType::Certainty::DefinitelyYes:
						std::cout << "File is definitely a " << i->friendlyName()
							<< " [" << i->code() << "]" << std::endl;
						pArchType = i;
						// Don't bother checking any other formats if we got a 100% match
						goto finishTesting;
				}
				if (cert != ga::ArchiveType::Certainty::DefinitelyNo) {
					// We got a possible match, see if it requires any suppdata
					auto suppList = i->getRequiredSupps(*psArchive, strFilename);
					if (suppList.size() > 0) {
						// It has suppdata, see if it's present
						std::cout << "  * This format requires supplemental files..."
							<< std::endl;
						bool bSuppOK = true;
						for (const auto& s : suppList) {
							try {
								stream::file test_presence(s.second, false);
							} catch (const stream::open_error&) {
								bSuppOK = false;
								std::cout << "  * Could not find/open " << s.second
									<< ", archive is probably not " << i->code() << std::endl;
								break;
							}
						}
						if (bSuppOK) {
							// All supp files opened ok
							std::cout << "  * All supp files present, archive is likely "
								<< i->code() << std::endl;
							// Set this as the most likely format
							pArchType = i;
						}
					}
				}
			}
finishTesting:
			if (!pArchType) {
				std::cerr << "Unable to automatically determine the file type.  Use "
					"the --type option to manually specify the file format." << std::endl;
				return RET_BE_MORE_SPECIFIC;
			}
		} else {
			auto pTestType = ga::ArchiveManager::byCode(strType);
			if (!pTestType) {
				std::cerr << "Unknown file type given to -t/--type: " << strType
					<< std::endl;
				return RET_BADARGS;
			}
			pArchType = pTestType;
		}

		assert(pArchType != NULL);

		if (!bCreate) {
			// Check to see if the file is actually in this format
			if (pArchType->isInstance(*psArchive) == ga::ArchiveType::Certainty::DefinitelyNo) {
				if (bForceOpen) {
					std::cerr << "Warning: " << strFilename << " is not a "
						<< pArchType->friendlyName() << ", open forced." << std::endl;
				} else {
					std::cerr << "Invalid format: " << strFilename << " is not a "
						<< pArchType->friendlyName() << "\n"
						<< "Use the -f option to try anyway." << std::endl;
					return RET_BE_MORE_SPECIFIC;
				}
			}
		}

		// See if the format requires any supplemental files
		auto suppList = pArchType->getRequiredSupps(*psArchive, strFilename);
		camoto::SuppData suppData;
		for (const auto& s : suppList) {
			try {
				std::cout << "Opening supplemental file " << s.second << std::endl;
				auto suppStream = std::make_unique<stream::file>(s.second, false);
				suppData[s.first] = std::move(suppStream);
			} catch (const stream::open_error& e) {
				std::cerr << "Error opening supplemental file " << s.second
					<< ": " << e.what() << std::endl;
				return RET_SHOWSTOPPER;
			}
		}

		// Open the archive file
		std::shared_ptr<ga::Archive> pArchive;
		try {
			if (bCreate) {
				pArchive = pArchType->create(std::move(psArchive), suppData);
			} else {
				pArchive = pArchType->open(std::move(psArchive), suppData);
			}
			assert(pArchive);
		} catch (const camoto::error& e) {
			std::cerr << "Error " << (bCreate ? "creating" : "opening")
				<< " archive file: " << e.what() << std::endl;
			return RET_SHOWSTOPPER;
		}

		// File type of inserted files defaults to empty, which means 'generic file'
		std::string strLastFiletype;

		// Last attribute value set with -b
		auto iLastAttr = ga::Archive::File::Attribute::Default;

		// Last value set with -z
		stream::len lenReal = 0;

		// Run through the actions on the command line
		for (auto& i : pa.options) {
			if (i.string_key.compare("list") == 0) {
				listFiles(std::string(), std::string(), *pArchive, bScript);

			} else if (i.string_key.compare("extract-all") == 0) {
				extractAll(pArchive, bScript);

			} else if (i.string_key.compare("metadata") == 0) {
				listAttributes(pArchive.get(), bScript);

			} else if (i.string_key.compare("set-metadata") == 0) {
				std::string strIndex, strValue;
				if (!split(i.value[0], '=', &strIndex, &strValue)) {
					std::cerr << PROGNAME ": -e/--set-metadata requires an index and "
						"a value (e.g. --set-metadata 0=example)" << std::endl;
					return RET_BADARGS;
				}
				unsigned int index = strtoul(strIndex.c_str(), nullptr, 0);
				setAttribute(pArchive.get(), bScript, index, strValue);

			} else if (i.string_key.compare("extract") == 0) {
				std::string strArchFile, strLocalFile;
				bool bAltDest = split(i.value[0], '=', &strArchFile, &strLocalFile);
				if (!bAltDest) sanitisePath(strLocalFile);

				std::cout << " extracting: " << strArchFile;
				if (strArchFile.compare(strLocalFile)) std::cout << " (into " << strLocalFile << ")";
				std::cout << std::flush;

				try {
					// Find the file
					auto destArch = pArchive;
					ga::Archive::FileHandle id;
					findFile(&destArch, &id, strArchFile);
					if (!id) {
						std::cout << " [failed; file not found]";
						iRet = RET_NONCRITICAL_FAILURE; // one or more files failed
					} else {
						// Found it, open on disk
						auto pfsIn = destArch->open(id, bUseFilters);
						try {
							auto fsOut = std::make_shared<stream::output_file>(strLocalFile, true);
							try {
								stream::copy(*fsOut, *pfsIn);
							} catch (const stream::error& e) {
								std::cout << " [failed; read/write error: " << e.what() << "]";
								iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way
							}
						} catch (const stream::error&) {
							std::cout << " [failed; unable to create output file]";
							iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way
						}
					}
				} catch (const stream::error& e) {
					std::cout << " [failed; " << e.what() << "]";
					iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way
				}
				std::cout << std::endl;

			} else if (i.string_key.compare("delete") == 0) {
				std::string& strArchFile = i.value[0];
				std::cout << "   deleting: " << strArchFile << std::flush;

				try {
					auto destArch = pArchive;
					ga::Archive::FileHandle id;
					findFile(&destArch, &id, strArchFile);
					if (!id) {
						std::cout << " [failed; file not found]";
						iRet = RET_NONCRITICAL_FAILURE; // one or more files failed
					} else {
						destArch->remove(id);
					}
				} catch (const stream::error& e) {
					std::cout << " [failed; " << e.what() << "]";
					iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way
				}
				std::cout << std::endl;

			} else if (i.string_key.compare("insert") == 0) {
				std::string strSource, strInsertBefore;
				if (!split(i.value[0], ':', &strSource, &strInsertBefore)) {
					std::cerr << PROGNAME ": -i/--insert requires a file to insert "
						"before (parameter should end with \":beforeme.xyz\")\n"
						"Or use --add instead." << std::endl;
					return RET_BADARGS;
				}

				std::string strArchFile, strLocalFile;
				bool bAltDest = split(strSource, '=', &strArchFile, &strLocalFile);

				std::cout << "  inserting: " << strArchFile;
				if (!strLastFiletype.empty()) std::cout << " as type " << strLastFiletype;
				std::cout << " (before "
					<< strInsertBefore;
				if (bAltDest) std::cout << ", from " << strLocalFile;
				std::cout << ")";
				if (lenReal != 0) std::cout << ", with uncompressed size " << lenReal;
				std::cout << std::flush;

				// Try to find strInsertBefore
				auto destArch = pArchive;
				ga::Archive::FileHandle idBeforeThis;
				findFile(&destArch, &idBeforeThis, strInsertBefore);
				if (!idBeforeThis) {
					std::cout << " [failed; could not find " << strInsertBefore << "]";
					iRet = RET_NONCRITICAL_FAILURE; // one or more files failed
					continue;
				}

				try {
					insertFile(destArch, strLocalFile, strArchFile, idBeforeThis,
						strLastFiletype, iLastAttr, lenReal);
				} catch (const stream::error& e) {
					std::cout << " [failed; " << e.what() << "]";
					iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way
				}

				std::cout << std::endl;

			// Remember --filetype/-y
			} else if (i.string_key.compare("filetype") == 0) {
			//} else if (i.string_key.compare("y") == 0) {
				strLastFiletype = i.value[0];

			// Remember --attributes/-b
			} else if (i.string_key.compare("attribute") == 0) {
			//} else if (i.string_key.compare("b") == 0) {
				std::string nextAttr = i.value[0];
				bool disable = (nextAttr[0] == '-');
				if (disable) nextAttr = nextAttr.substr(1);

				ga::Archive::File::Attribute next;
				if      (nextAttr.compare("empty")      == 0) next = ga::Archive::File::Attribute::Vacant;
				else if (nextAttr.compare("hidden")     == 0) next = ga::Archive::File::Attribute::Hidden;
				else if (nextAttr.compare("compressed") == 0) next = ga::Archive::File::Attribute::Compressed;
				else if (nextAttr.compare("encrypted")  == 0) next = ga::Archive::File::Attribute::Encrypted;
				else {
					std::cerr << "Unknown attribute " << nextAttr
						<< ", valid values are: empty hidden compressed encrypted"
						<< std::endl;
					iRet = RET_UNCOMMON_FAILURE;
					next = ga::Archive::File::Attribute::Default;
				}
				if (next != ga::Archive::File::Attribute::Default) {
					auto allowed = pArchive->getSupportedAttributes();
					if (allowed & next) {
						if (disable) iLastAttr &= ~next;
						else iLastAttr |= next;
					} else {
						std::cerr << "Warning: Attribute unsupported by archive format, "
							"ignoring: " << nextAttr << std::endl;
					}
				}

			// Remember --uncompressed-size/-z
			} else if (i.string_key.compare("uncompressed-size") == 0) {
			//} else if (i.string_key.compare("z") == 0) {
				if (bUseFilters) {
					std::cerr << PROGNAME ": -z/--uncompressed-size only needs to be "
						"specified when it can't be determined automatically (i.e. when "
						"-u/--unfiltered is in use.)" << std::endl;
					return RET_BADARGS;
				}
				lenReal = strtoul(i.value[0].c_str(), NULL, 0);

			// Ignore --type/-t
			} else if (i.string_key.compare("type") == 0) {
			} else if (i.string_key.compare("t") == 0) {
			// Ignore --script/-s
			} else if (i.string_key.compare("script") == 0) {
			} else if (i.string_key.compare("s") == 0) {
			// Ignore --force/-f
			} else if (i.string_key.compare("force") == 0) {
			} else if (i.string_key.compare("f") == 0) {

			} else if ((!i.string_key.empty()) && (i.value.size() > 0)) {
				// None of the above (single param) options matched, so it's probably
				// an option with up to two filenames (with an equal-sign as a
				// separator.)  It could also be the --type option, which we'll ignore.
				std::string& strParam = i.value[0];
				std::string strArchFile, strLocalFile;
				bool bAltDest = split(strParam, '=', &strArchFile, &strLocalFile);

				if (i.string_key.compare("add") == 0) {
					std::cout << "     adding: " << strArchFile;
					if (!strLastFiletype.empty()) std::cout << " as type " << strLastFiletype;
					if (bAltDest) std::cout << " (from " << strLocalFile << ")";
					if (lenReal != 0) std::cout << ", with uncompressed size set to " << lenReal;
					std::cout << std::endl;

					try {
						insertFile(pArchive, strLocalFile, strArchFile,
							nullptr, strLastFiletype, iLastAttr,
							lenReal);
					} catch (const stream::error& e) {
						std::cout << " [failed; " << e.what() << "]";
						iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way
					}

				} else if (i.string_key.compare("rename") == 0) {
					if ((!bAltDest) || (boost::equals(strArchFile, strLocalFile))) {
						std::cout << "ignoring attempt to rename " << strArchFile
							<< " into the same name" << std::endl;
					} else {
						std::cout << "   renaming: " << strArchFile << " to "
							<< strLocalFile << std::flush;

						try {
							auto destArch = pArchive;
							ga::Archive::FileHandle id;
							findFile(&destArch, &id, strArchFile);
							if (!id) {
								std::cout << " [failed; file not found inside archive]";
								iRet = RET_NONCRITICAL_FAILURE; // one or more files failed
							} else {
								destArch->rename(id, strLocalFile);
							}
						} catch (const stream::error& e) {
							std::cout << " [failed; " << e.what() << "]";
							iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a common way
						}
						std::cout << std::endl;
					}

				} else if (i.string_key.compare("overwrite") == 0) {
					std::cout << "overwriting: " << strArchFile;
					if (bAltDest) std::cout << " (from " << strLocalFile << ")";
					if (lenReal != 0) std::cout << ", with uncompressed size set to " << lenReal;
					std::cout << std::flush;

					try {
						// Find the file
						auto destArch = pArchive;
						ga::Archive::FileHandle id;
						findFile(&destArch, &id, strArchFile);
						if (!id) {
							std::cout << " [failed; file not found inside archive]";
							iRet = RET_NONCRITICAL_FAILURE; // one or more files failed
						} else {
							// Found it, open replacement file
							auto sSrc = std::make_shared<stream::input_file>(strLocalFile);
							stream::len lenSource = sSrc->size();

							// Note that we are opening the file into an output_sptr (instead
							// of an inout_sptr) as this is more efficient.  By foregoing read
							// access to the file, it means a compressed file won't be
							// decompressed in case we want to read it.  Which we don't,
							// because we're about to completely overwrite it.
							auto psDest = destArch->open(id, bUseFilters);

							// Set the size of the stream within the archive, so it exactly
							// holds the data we want to write.
							psDest->truncate(lenSource);

							if (!bUseFilters) {
								if (lenReal) {
									pArchive->resize(id, lenSource, lenReal);
								} else {
									// Leave the prefiltered/decompressed size unchanged
									pArchive->resize(id, lenSource, id->realSize);
								}
							}

							psDest->seekp(0, stream::start);
							stream::copy(*psDest, *sSrc);
							psDest->flush();
						}
					} catch (const stream::open_error&) {
						std::cout << " [failed; unable to open replacement file]";
						iRet = RET_NONCRITICAL_FAILURE; // one or more files failed
					} catch (const stream::error& e) {
						std::cout << " [failed; " << e.what() << "]";
						iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a common way
					}
					std::cout << std::endl;
				}
				// else it's the archive filename, but we already have that
			}
		} // for (all command line elements)
		pArchive->flush();
	} catch (const po::unknown_option& e) {
		std::cerr << PROGNAME ": " << e.what()
			<< ".  Use --help for help." << std::endl;
		return RET_BADARGS;
	} catch (const po::invalid_command_line_syntax& e) {
		std::cerr << PROGNAME ": " << e.what()
			<< ".  Use --help for help." << std::endl;
		return RET_BADARGS;
	}

	return iRet;
}