void AnalyzeTask::parseProperty(const QString &value, const MI_propertyId_t propertyIdx, AudioFileModel &audioFile, QString &coverMimeType) { #if MUTILS_DEBUG qDebug("Property #%d = \"%s\"", propertyIdx, MUTILS_UTF8(value.left(24))); #endif switch (propertyIdx) { case propertyId_container: audioFile.techInfo().setContainerType(value); return; case propertyId_container_profile: audioFile.techInfo().setContainerProfile(value); return; case propertyId_duration: SET_OPTIONAL(double, parseFloat(value, _tmp), audioFile.techInfo().setDuration(qRound(_tmp))); return; case propertyId_title: audioFile.metaInfo().setTitle(value); return; case propertyId_artist: audioFile.metaInfo().setArtist(value); return; case propertyId_album: audioFile.metaInfo().setAlbum(value); return; case propertyId_genre: audioFile.metaInfo().setGenre(value); return; case propertyId_released_date: SET_OPTIONAL(quint32, parseYear(value, _tmp), audioFile.metaInfo().setYear(_tmp)); return; case propertyId_track_position: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.metaInfo().setPosition(_tmp)); return; case propertyId_comment: audioFile.metaInfo().setComment(value); return; case propertyId_format: audioFile.techInfo().setAudioType(value); return; case propertyId_format_version: audioFile.techInfo().setAudioVersion(value); return; case propertyId_format_profile: audioFile.techInfo().setAudioProfile(value); return; case propertyId_channel_s_: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.techInfo().setAudioChannels(_tmp)); return; case propertyId_samplingrate: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.techInfo().setAudioSamplerate(_tmp)); return; case propertyId_bitdepth: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.techInfo().setAudioBitdepth(_tmp)); return; case propertyId_bitrate: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.techInfo().setAudioBitrate(DIV_RND(_tmp, 1000U))); return; case propertyId_bitrate_mode: SET_OPTIONAL(quint32, parseRCMode(value, _tmp), audioFile.techInfo().setAudioBitrateMode(_tmp)); return; case propertyId_encoded_library: audioFile.techInfo().setAudioEncodeLib(cleanAsciiStr(value)); return; case propertyId_cover_mime: coverMimeType = value; return; case propertyId_cover_data: retrieveCover(audioFile, coverMimeType, value); return; default: MUTILS_THROW_FMT("Invalid property ID: %d", propertyIdx); } }
unsigned long Properties::getUnsigned(const std::string& key, unsigned long defaultValue, bool terse) const { unsigned long result; const_iterator iter = find(key); if (iter == end()) { if (terse) { Log::log(logID, Log::LOG_MAX_DEBUG, "No value specified for key %s, using default value.", key.c_str()); } result = defaultValue; } else { try { result = parseUnsigned(key, iter->second); } catch (...) { if (terse) { Log::log(logID, Log::LOG_MAX_DEBUG, "Invalid value specified for key %s, using default value.", key.c_str()); } result = defaultValue; } } return result; }
// parse minikmer length from string and correct it as necessary static inline unsigned getMiniKmerLength(char *h) { unsigned minikmer_length = parseUnsigned(h); #ifdef PART_MINIKMER_BITS unsigned limit = g__FULLKMER_LENGTH * 2; if (minikmer_length > limit) { fprintf(stderr,"WARNING: mini k-mer bits cannot be larger than double the full k-mer length %u! Using mini k-mer bits of %u instead.\n", g__FULLKMER_LENGTH, limit); minikmer_length = limit; } #else unsigned limit = g__FULLKMER_LENGTH; if (minikmer_length > limit) { fprintf(stderr,"WARNING: mini k-mers cannot be larger than the full k-mer length %u! Using mini k-mer length of %u instead.\n", g__FULLKMER_LENGTH, limit); minikmer_length = limit; } #endif #ifdef PART_MIDDLE_MINIKMER if (minikmer_length % 2 == 0) { fprintf(stderr,"WARNING: mini k-mers can't be of even length, such as %u. Using mini k-mer length of %u instead.\n", minikmer_length, minikmer_length-1); -- minikmer_length; } #endif return minikmer_length; }
// parse partition count from string and correct (round-up) to power-of-4 static inline unsigned getNumPartitions(char *h) { unsigned numPartitions = parseUnsigned(h); // FIXME: is this only for metis? #ifdef PART_POWEROF4 if( !is_power_of_4(numPartitions) ) { unsigned tmp = round_up_power_of_2(numPartitions); unsigned pow4 = tmp & 0x55555555UL ? tmp : tmp << 1; fprintf(stderr,"WARNING: partitions specified %u is not a power of 4. Using %u instead.\n", numPartitions, pow4); numPartitions = pow4; } #endif unsigned maxPartitions = (1 << (8 * sizeof(color_t))) - 2; #ifdef PART_POWEROF4 if (numPartitions > maxPartitions) { unsigned tmp = numPartitions >> 2; fprintf(stderr,"WARNING: partitions %u is too large. Using %u instead.\n", numPartitions, tmp); numPartitions = tmp; }
/* Throws * std::invalid_argument if a value for key is not found * std::range_error if value is too small or large. * std::domain_error if valid is invalid otherwise. */ unsigned long Properties::getUnsigned(const std::string& key) const { const_iterator iter = find(key); if (iter == end()) { throw std::invalid_argument(key + " not found"); } return parseUnsigned(key, iter->second); }
time_t gbParseChkDate(char* dateStr, boolean* isOk) /* parse a date, in YYYY-MM-DD format, converting it to a unix time (as * returned by time()). Sets isOk to false if an error */ { struct tm tm; time_t numTime; ZeroVar(&tm); *isOk = TRUE; if (!((strlen(dateStr) == 10) && (dateStr[4] == '-') && (dateStr[7] == '-'))) *isOk = FALSE; tm.tm_year = parseUnsigned(dateStr, 0, 4, isOk)-1900; /* since 1900 */ tm.tm_mon = parseUnsigned(dateStr, 5, 2, isOk)-1; /* since jan */ tm.tm_mday = parseUnsigned(dateStr, 8, 2, isOk); /* 1-31 */ /* convert */ if ((numTime = mktime(&tm)) == -1) *isOk = FALSE; return numTime; }
static time_t gbParseHumanTimeStamp(char *col, boolean *isOkRet) /* Parse a time stamp, in "2004-11-01 01:06:18" format, as returned * by mysql timestamp columns 4.1 or later. */ { boolean isOk = TRUE; struct tm tm; time_t numTime; ZeroVar(&tm); if (strlen(col) != 19) isOk = FALSE; tm.tm_year = parseUnsigned(col, 0, 4, &isOk)-1900; if (col[4] != '-') isOk = FALSE; tm.tm_mon = parseUnsigned(col, 5, 2, &isOk); if (col[7] != '-') isOk = FALSE; tm.tm_mday = parseUnsigned(col, 8, 2, &isOk); if (col[10] != ' ') isOk = FALSE; tm.tm_hour = parseUnsigned(col, 11, 2, &isOk); if (col[13] != ':') isOk = FALSE; tm.tm_min = parseUnsigned(col, 14, 2, &isOk); if (col[16] != ':') isOk = FALSE; tm.tm_sec = parseUnsigned(col, 17, 2, &isOk); /* convert */ if ((numTime = mktime(&tm)) == -1) isOk = FALSE; *isOkRet = isOk; return numTime; }
// parse kmer_length from string and correct to make odd and less than 32 bases long static inline unsigned getKmerLength(char *h) { unsigned kmer_length = parseUnsigned(h); if (kmer_length > 31) { fprintf(stderr,"WARNING: Velour can't handle k-mers as long as %u! Using k-mer length of 31 instead.\n", kmer_length); kmer_length = 31; } else if (kmer_length % 2 == 0) { fprintf(stderr,"WARNING: Velour can't work with even length k-mers, such as %u. Using k-mer length of %u instead.\n", kmer_length, kmer_length - 1); kmer_length--; } return kmer_length; }
bool AnalyzeTask::parseYear(const QString &str, quint32 &value) { if (str.startsWith(QLatin1String("UTC"), Qt::CaseInsensitive)) { const QDate date = QDate::fromString(str.mid(3).trimmed().left(10), QLatin1String("yyyy-MM-dd")); if (date.isValid()) { value = date.year(); return true; } return false; } else { return parseUnsigned(str, value); } }
static time_t gbParseNumTimeStamp(char *col, boolean *isOkRet) /* Parse a time stamp, in "YYYYMMDDHHMMSS" format, as returned * by mysql timestamp columns before 4.1. */ { boolean isOk = TRUE; struct tm tm; time_t numTime; ZeroVar(&tm); if (strlen(col) != 14) isOk = FALSE; tm.tm_year = parseUnsigned(col, 0, 4, &isOk)-1900; tm.tm_mon = parseUnsigned(col, 4, 2, &isOk); tm.tm_mday = parseUnsigned(col, 6, 2, &isOk); tm.tm_hour = parseUnsigned(col, 8, 2, &isOk); tm.tm_min = parseUnsigned(col, 10, 2, &isOk); tm.tm_sec = parseUnsigned(col, 12, 2, &isOk); /* convert */ if ((numTime = mktime(&tm)) == -1) isOk = FALSE; *isOkRet = isOk; return numTime; }
bool AnalyzeTask::analyzeAvisynthFile(const QString &filePath, AudioFileModel &info) { QProcess process; MUtils::init_process(process, QFileInfo(m_avs2wavBin).absolutePath()); process.start(m_avs2wavBin, QStringList() << QDir::toNativeSeparators(filePath) << "?"); if(!process.waitForStarted()) { qWarning("AVS2WAV process failed to create!"); qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData()); process.kill(); process.waitForFinished(-1); return false; } bool bInfoHeaderFound = false; while(process.state() != QProcess::NotRunning) { if(MUTILS_BOOLIFY(m_abortFlag)) { process.kill(); qWarning("Process was aborted on user request!"); break; } if(!process.waitForReadyRead()) { if(process.state() == QProcess::Running) { qWarning("AVS2WAV time out. Killing process and skipping file!"); process.kill(); process.waitForFinished(-1); return false; } } while(process.canReadLine()) { const QString line = QString::fromUtf8(process.readLine().constData()).simplified(); if(!line.isEmpty()) { if(bInfoHeaderFound) { const qint32 index = line.indexOf(':'); if (index > 0) { const QString key = line.left(index).trimmed(); const QString val = line.mid(index + 1).trimmed(); if (!(key.isEmpty() || val.isEmpty())) { switch (m_avisynthIdx.value(key.toLower(), MI_propertyId_t(-1))) { case propertyId_duration: SET_OPTIONAL(quint32, parseUnsigned(val, _tmp), info.techInfo().setDuration(_tmp)); break; case propertyId_samplingrate: SET_OPTIONAL(quint32, parseUnsigned(val, _tmp), info.techInfo().setAudioSamplerate(_tmp)); break; case propertyId_channel_s_: SET_OPTIONAL(quint32, parseUnsigned(val, _tmp), info.techInfo().setAudioChannels(_tmp)); break; case propertyId_bitdepth: SET_OPTIONAL(quint32, parseUnsigned(val, _tmp), info.techInfo().setAudioBitdepth(_tmp)); break; } } } } else { if(line.contains("[Audio Info]", Qt::CaseInsensitive)) { info.techInfo().setAudioType("Avisynth"); info.techInfo().setContainerType("Avisynth"); bInfoHeaderFound = true; } } } } } process.waitForFinished(); if(process.state() != QProcess::NotRunning) { process.kill(); process.waitForFinished(-1); } //Check exit code switch(process.exitCode()) { case 0: qDebug("Avisynth script was analyzed successfully."); return true; break; case -5: qWarning("It appears that Avisynth is not installed on the system!"); return false; break; default: qWarning("Failed to open the Avisynth script, bad AVS file?"); return false; break; } }
std::string PropertyParser::parseTemplateType() { std::string Result; int ParensLevel = 0; bool MoveConstToFront = true; bool HasConst = false; clang::CXXScopeSpec SS; do { switch(+CurrentTok.getKind()) { case clang::tok::eof: return {}; case clang::tok::greatergreater: if (ParensLevel > 0) break; CurrentTok.setKind(clang::tok::greater); PrevToken.setKind(clang::tok::greater); if (Result[Result.size()-1] == '>') Result += " "; Result += ">"; return Result; case clang::tok::greater: if (ParensLevel > 0) break; if (Result[Result.size()-1] == '>') Result += " "; Result += ">"; Consume(); return Result; case clang::tok::less: if (ParensLevel > 0 ) break; Result += "<"; Consume(); Result += parseTemplateType(); if (!PrevToken.is(clang::tok::greater)) return {}; MoveConstToFront = false; continue; case clang::tok::l_square: case clang::tok::l_paren: case clang::tok::l_brace: ++ParensLevel; break; case clang::tok::r_square: case clang::tok::r_paren: case clang::tok::r_brace: --ParensLevel; if (ParensLevel < 0) return {}; break; case clang::tok::comma: if (ParensLevel > 0) break; Result += ","; Consume(); return Result + parseTemplateType(); case clang::tok::kw_const: if (MoveConstToFront) { HasConst = true; continue; } break; case clang::tok::kw_unsigned: if (IsIdentChar(Result[Result.size()])) Result+=" "; Result += parseUnsigned(); continue; case clang::tok::amp: case clang::tok::ampamp: case clang::tok::star: MoveConstToFront = false; break; case clang::tok::identifier: { clang::LookupResult Found(Sema, CurrentTok.getIdentifierInfo(), OriginalLocation(CurrentTok.getLocation()), clang::Sema::LookupNestedNameSpecifierName); Sema.LookupParsedName(Found, Sema.getScopeForContext(RD), &SS); clang::CXXRecordDecl* D = Found.getAsSingle<clang::CXXRecordDecl>(); if (D && !D->hasDefinition()) IsPossiblyForwardDeclared = true; Found.suppressDiagnostics(); break; } case clang::tok::coloncolon: if (PrevToken.getIdentifierInfo()) SS.Extend(Sema.getASTContext(), PrevToken.getIdentifierInfo(), OriginalLocation(), OriginalLocation(CurrentTok.getLocation())); break; } Consume(); auto Sp = Spelling(); char Last = Result[Result.size()]; if ((Last == '<' && Sp[0] == ':') || (IsIdentChar(Last) && IsIdentChar(Sp[0]))) Result += " "; Result += Sp; } while (true); if (HasConst) Result = "const " + Result; return Result; }
std::string PropertyParser::parseType(bool SupressDiagnostics) { std::string Result; bool HasConst = Test(clang::tok::kw_const); bool HasVolatile = Test(clang::tok::kw_volatile); bool NoTemplates = true; Test(clang::tok::kw_enum) || Test(clang::tok::kw_class) || Test(clang::tok::kw_struct); if (Test(clang::tok::kw_unsigned)) { Result += parseUnsigned(); } else if (Test(clang::tok::kw_signed)) { Result += "signed"; while (true) { switch(+CurrentTok.getKind()) { case clang::tok::kw_int: case clang::tok::kw_long: case clang::tok::kw_short: case clang::tok::kw_char: Consume(); Result += " " + Spelling(); continue; } break; } } else { while(Test(clang::tok::kw_int) || Test(clang::tok::kw_long) || Test(clang::tok::kw_short) || Test(clang::tok::kw_char) || Test(clang::tok::kw_void) || Test(clang::tok::kw_bool) || Test(clang::tok::kw_double) || Test(clang::tok::kw_float)) { if (!Result.empty()) Result += " "; Result += Spelling(); } } if (Result.empty()) { clang::CXXScopeSpec SS; if (Test(clang::tok::coloncolon)) { SS.MakeGlobal(Sema.getASTContext(), OriginalLocation()); Result += Spelling(); } do { if (!Test(clang::tok::identifier)) { PP.getDiagnostics().Report(OriginalLocation(CurrentTok.getLocation()), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Invalid token while parsing type")); return {}; } Result += Spelling(); if (Test(clang::tok::less)) { NoTemplates = false; Result += "<"; Result += parseTemplateType(); if (!PrevToken.is(clang::tok::greater)) { PP.getDiagnostics().Report(OriginalLocation(CurrentTok.getLocation()), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "parse error in type")); return {}; //error; } } clang::Token IdentTok = PrevToken; if (!Test(clang::tok::coloncolon)) break; if (NoTemplates && !SupressDiagnostics) { if (Sema.ActOnCXXNestedNameSpecifier(Sema.getScopeForContext(RD), *IdentTok.getIdentifierInfo(), OriginalLocation(IdentTok.getLocation()), OriginalLocation(CurrentTok.getLastLoc()), {}, false, SS)) SS.SetInvalid({OriginalLocation(IdentTok.getLocation()), OriginalLocation(CurrentTok.getLastLoc())}); } Result += Spelling(); } while (true); if (NoTemplates && !SupressDiagnostics) { IsEnum = true; // That's how moc does it. if (SS.isNotEmpty() && SS.isValid()) { Extra = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(Sema.computeDeclContext(SS)); clang::LookupResult Found(Sema, PrevToken.getIdentifierInfo(), OriginalLocation(), clang::Sema::LookupNestedNameSpecifierName); /*if (SS.isEmpty()) Sema.LookupQualifiedName(Found, RD); else {*/ clang::DeclContext* DC = Sema.computeDeclContext(SS); Sema.LookupQualifiedName(Found, DC ? DC : RD); //} clang::EnumDecl* R = Found.getAsSingle<clang::EnumDecl>(); /*if (!R) { if (clang::TypedefDecl *TD = Found.getAsSingle<clang::TypedefDecl>()) { const clang::TemplateSpecializationType* TDR = TD->getUnderlyingType()->getAs<clang::TemplateSpecializationType>(); if(TDR && TDR->getNumArgs() == 1 && TDR->getTemplateName().getAsTemplateDecl()->getName() == "QFlags") { if (const clang::EnumType* ET = TDR->getArg(0).getAsType()->getAs<clang::EnumType>()) R = ET->getDecl(); } }*/ /*if (!R) IsEnum = false;*/ if(Extra) { bool isQObjectOrQGadget = false; for (auto it = Extra->decls_begin(); it != Extra->decls_end(); ++it) { auto ND = llvm::dyn_cast<clang::NamedDecl>(*it); if (ND && ND->getIdentifier() && ND->getName() == "staticMetaObject") { isQObjectOrQGadget = true; break; } } if (!isQObjectOrQGadget) Extra = nullptr; } if (!R) { clang::CXXRecordDecl* D = Found.getAsSingle<clang::CXXRecordDecl>(); if (D && !D->hasDefinition()) IsPossiblyForwardDeclared = true; } } else if (SS.isEmpty()) { clang::LookupResult Found(Sema, PrevToken.getIdentifierInfo(), OriginalLocation(), clang::Sema::LookupNestedNameSpecifierName); Sema.LookupName(Found, Sema.getScopeForContext(RD)); clang::CXXRecordDecl* D = Found.getAsSingle<clang::CXXRecordDecl>(); if (D && !D->hasDefinition()) { IsPossiblyForwardDeclared = true; } Found.suppressDiagnostics(); } } } if (NoTemplates && Test(clang::tok::kw_const)) { // The official moc don't move the const if there are templates HasConst = true; } while (Test(clang::tok::kw_volatile) || Test(clang::tok::star) || Test(clang::tok::kw_const)) { Extra = nullptr; IsEnum = false; Result += Spelling(); } if (Test(clang::tok::amp)) { if (HasConst) HasConst = false; // remove const reference else Result += Spelling(); } else { Test(clang::tok::ampamp); // skip rvalue ref } if (HasVolatile) Result = "volatile " + Result; if (HasConst) Result = "const " + Result; return Result; }
void Service::GetParams(xmlNodePtr n) { xmlChar* s=xmlNodeGetContent(n); string v; if(s){ v = (char*)s; xmlFree(s); } if(!xmlStrcmp(n->name, BAD_CAST "label")) { // careful, UTF-8, max 16 visible characters! service_label = v; } if(!xmlStrcmp(n->name,BAD_CAST "service_identifier")) { parseHexBinary(n, "service_identifier", service_identifier); size_t len=service_identifier.size(); if(len>3) misconfiguration=true; if(len<3){ bytev::iterator theIterator = service_identifier.begin(); service_identifier.insert( theIterator, 3-len, 0); } } if(!xmlStrcmp(n->name,BAD_CAST "country")) { country = v; if(country.size()!=2) misconfiguration=true; } parseUnsigned(n, "language", &language); if(!xmlStrcmp(n->name,BAD_CAST "language_long")) { language_long = v; if(language_long.size()!=3) misconfiguration=true; } parseUnsigned(n, "service_descriptor", &service_descriptor); if(!xmlStrcmp(n->name,BAD_CAST "conditional_access")) { for(xmlNodePtr d=n->children; d; d=d->next){ if(d->type==XML_ELEMENT_NODE){ parseUnsigned(d, "ca_system_identifer", &ca_system_identifier); parseHexBinary(d, "ca_data", ca_data); /* TODO (jfbc#2#): ca data can't be more than 126 bytes - check */ } } } parseIDREF(n, "audio_ref", audio_ref); parseIDREF(n, "data_ref", data_ref); if(xmlStrEqual(n->name,BAD_CAST "afs_refs")) { for(xmlNodePtr d=n->children; d; d=d->next){ if(d->type==XML_ELEMENT_NODE){ string r; parseIDREF(d, "afs_ref", r); afs_ref.push_back(r); } } } if(xmlStrEqual(n->name,BAD_CAST "announcements")) { for(xmlNodePtr d=n->children; d; d=d->next){ if(d->type==XML_ELEMENT_NODE){ Announcement a; a.ReConfigure(d); announcement.push_back(a); } } } }
Options::Status Options::parse(int argc, const char **argv) { bool test = false; bool recursive = false; bool ultra = false; bool forceStdout = false; // Local copy of input files, which are pointers into argv. std::vector<const char *> localInputFiles; for (int i = 1; i < argc; ++i) { const char *arg = argv[i]; // Protect against empty arguments if (arg[0] == 0) { continue; } // Everything after "--" is an input file if (!std::strcmp(arg, "--")) { ++i; std::copy(argv + i, argv + argc, std::back_inserter(localInputFiles)); break; } // Long arguments that don't have a short option { bool isLongOption = true; if (!std::strcmp(arg, "--rm")) { keepSource = false; } else if (!std::strcmp(arg, "--ultra")) { ultra = true; maxWindowLog = 0; } else if (!std::strcmp(arg, "--no-check")) { checksum = false; } else if (!std::strcmp(arg, "--sparse")) { writeMode = WriteMode::Sparse; notSupported("Sparse mode"); return Status::Failure; } else if (!std::strcmp(arg, "--no-sparse")) { writeMode = WriteMode::Regular; notSupported("Sparse mode"); return Status::Failure; } else if (!std::strcmp(arg, "--dictID")) { notSupported(arg); return Status::Failure; } else if (!std::strcmp(arg, "--no-dictID")) { notSupported(arg); return Status::Failure; } else { isLongOption = false; } if (isLongOption) { continue; } } // Arguments with a short option simply set their short option. const char *options = nullptr; if (!std::strcmp(arg, "--processes")) { options = "p"; } else if (!std::strcmp(arg, "--version")) { options = "V"; } else if (!std::strcmp(arg, "--help")) { options = "h"; } else if (!std::strcmp(arg, "--decompress")) { options = "d"; } else if (!std::strcmp(arg, "--force")) { options = "f"; } else if (!std::strcmp(arg, "--stdout")) { options = "c"; } else if (!std::strcmp(arg, "--keep")) { options = "k"; } else if (!std::strcmp(arg, "--verbose")) { options = "v"; } else if (!std::strcmp(arg, "--quiet")) { options = "q"; } else if (!std::strcmp(arg, "--check")) { options = "C"; } else if (!std::strcmp(arg, "--test")) { options = "t"; } else if (arg[0] == '-' && arg[1] != 0) { options = arg + 1; } else { localInputFiles.emplace_back(arg); continue; } assert(options != nullptr); bool finished = false; while (!finished && *options != 0) { // Parse the compression level if (*options >= '0' && *options <= '9') { compressionLevel = parseUnsigned(&options); continue; } switch (*options) { case 'h': case 'H': usage(); return Status::Message; case 'V': std::fprintf(stderr, "PZSTD version: %s.\n", ZSTD_VERSION_STRING); return Status::Message; case 'p': { finished = true; const char *optionArgument = getArgument(options, argv, i, argc); if (optionArgument == nullptr) { return Status::Failure; } if (*optionArgument < '0' || *optionArgument > '9') { std::fprintf(stderr, "Option -p expects a number, but %s provided\n", optionArgument); return Status::Failure; } numThreads = parseUnsigned(&optionArgument); if (*optionArgument != 0) { std::fprintf(stderr, "Option -p expects a number, but %u%s provided\n", numThreads, optionArgument); return Status::Failure; } break; } case 'o': { finished = true; const char *optionArgument = getArgument(options, argv, i, argc); if (optionArgument == nullptr) { return Status::Failure; } outputFile = optionArgument; break; } case 'C': checksum = true; break; case 'k': keepSource = true; break; case 'd': decompress = true; break; case 'f': overwrite = true; forceStdout = true; break; case 't': test = true; decompress = true; break; #ifdef UTIL_HAS_CREATEFILELIST case 'r': recursive = true; break; #endif case 'c': outputFile = kStdOut; forceStdout = true; break; case 'v': ++verbosity; break; case 'q': --verbosity; // Ignore them for now break; // Unsupported options from Zstd case 'D': case 's': notSupported("Zstd dictionaries."); return Status::Failure; case 'b': case 'e': case 'i': case 'B': notSupported("Zstd benchmarking options."); return Status::Failure; default: std::fprintf(stderr, "Invalid argument: %s\n", arg); return Status::Failure; } if (!finished) { ++options; } } // while (*options != 0); } // for (int i = 1; i < argc; ++i); // Input file defaults to standard input if not provided. if (localInputFiles.empty()) { localInputFiles.emplace_back(kStdIn); } // Check validity of input files if (localInputFiles.size() > 1) { const auto it = std::find(localInputFiles.begin(), localInputFiles.end(), std::string{kStdIn}); if (it != localInputFiles.end()) { std::fprintf( stderr, "Cannot specify standard input when handling multiple files\n"); return Status::Failure; } } if (localInputFiles.size() > 1 || recursive) { if (!outputFile.empty() && outputFile != nullOutput) { std::fprintf( stderr, "Cannot specify an output file when handling multiple inputs\n"); return Status::Failure; } } // Translate input files/directories into files to (de)compress if (recursive) { char *scratchBuffer = nullptr; unsigned numFiles = 0; const char **files = UTIL_createFileList(localInputFiles.data(), localInputFiles.size(), &scratchBuffer, &numFiles); if (files == nullptr) { std::fprintf(stderr, "Error traversing directories\n"); return Status::Failure; } auto guard = makeScopeGuard([&] { UTIL_freeFileList(files, scratchBuffer); }); if (numFiles == 0) { std::fprintf(stderr, "No files found\n"); return Status::Failure; } inputFiles.resize(numFiles); std::copy(files, files + numFiles, inputFiles.begin()); } else { inputFiles.resize(localInputFiles.size()); std::copy(localInputFiles.begin(), localInputFiles.end(), inputFiles.begin()); } localInputFiles.clear(); assert(!inputFiles.empty()); // If reading from standard input, default to standard output if (inputFiles[0] == kStdIn && outputFile.empty()) { assert(inputFiles.size() == 1); outputFile = "-"; } if (inputFiles[0] == kStdIn && IS_CONSOLE(stdin)) { assert(inputFiles.size() == 1); std::fprintf(stderr, "Cannot read input from interactive console\n"); return Status::Failure; } if (outputFile == "-" && IS_CONSOLE(stdout) && !(forceStdout && decompress)) { std::fprintf(stderr, "Will not write to console stdout unless -c or -f is " "specified and decompressing\n"); return Status::Failure; } // Check compression level { unsigned maxCLevel = ultra ? ZSTD_maxCLevel() : kMaxNonUltraCompressionLevel; if (compressionLevel > maxCLevel || compressionLevel == 0) { std::fprintf(stderr, "Invalid compression level %u.\n", compressionLevel); return Status::Failure; } } // Check that numThreads is set if (numThreads == 0) { std::fprintf(stderr, "Invalid arguments: # of threads not specified " "and unable to determine hardware concurrency.\n"); return Status::Failure; } // Modify verbosity // If we are piping input and output, turn off interaction if (inputFiles[0] == kStdIn && outputFile == kStdOut && verbosity == 2) { verbosity = 1; } // If we are in multi-file mode, turn off interaction if (inputFiles.size() > 1 && verbosity == 2) { verbosity = 1; } // Set options for test mode if (test) { outputFile = nullOutput; keepSource = true; } return Status::Success; }