Пример #1
0
std::string runAndCapture(int (* mainFunc)(),
                          const std::string& cinInput,
                          const std::string& outputFileName) {
    // run the 'main' function, possibly feeding it cin, input, and capture its cout output
    if (!cinInput.empty()) {
        ioutils::redirectStdinBegin(cinInput);
    }
    
    ioutils::setConsoleOutputLimit(MAX_STUDENT_OUTPUT);   // prevent infinite output by student
    ioutils::captureStdoutBegin();
    
    mainFunc();
    
    std::string output = ioutils::captureStdoutEnd();
    if (!cinInput.empty()) {
        ioutils::redirectStdinEnd();
    }

    // return the output as a string (and also possibly write it to a file)
    if (!outputFileName.empty()) {
        writeEntireFile(outputFileName, output);
    }
    return output;
}
Пример #2
0
bool SearchContext::searchFile(int id, const std::string &filename, RegexList &filespecRegexes, pcre *matchRegex)
{
    bool matchesOneFilespec = false;
    for(RegexList::iterator it = filespecRegexes.begin(); it != filespecRegexes.end(); ++it)
    {
        pcre *regex = *it;
        if(pcre_exec(regex, NULL, filename.c_str(), filename.length(), 0, 0, NULL, 0) >= 0)
        {
            matchesOneFilespec = true;
            break;
        }
    }
    if(!matchesOneFilespec)
        return false;

    std::string contents;
    if(!readEntireFile(filename, contents, params_.maxFileSize))
        return false;

    std::string workBuffer = contents;
    std::string updatedContents;

    bool atLeastOneMatch = false;

    int lineNumber = 1;
    char *p = &workBuffer[0];
    char *line;
    while((line = nextToken(&p, '\n')) != NULL)
    {
        char *originalLine = line;
        std::string replacedLine;
		SearchEntry entry;
        int ovector[100];
        do
        {
            bool matches = false;
            int matchPos;
            int matchLen;

            if(matchRegex)
            {
                int rc;
                if(rc = pcre_exec(matchRegex, 0, line, strlen(line), 0, 0, ovector, sizeof(ovector)) >= 0)
                {
                    matches = true;
                    matchPos = ovector[0];
                    matchLen = ovector[1] - ovector[0];
                }
            }
            else
            {
                char *match;
                if(params_.flags & SF_MATCH_CASE_SENSITIVE)
                    match = strstr(line, params_.match.c_str());
                else
                    match = strstri(line, params_.match.c_str());
                if(match != NULL)
                {
                    matches = true;
                    matchPos = match - line;
                    matchLen = params_.match.length();
                }
            }

            if(params_.flags & SF_REPLACE)
            {
                if(matches)
                {
                    replacedLine.append(line, matchPos);
					entry.highlights_.push_back(Highlight(replacedLine.length(), params_.replace.length()));
                    replacedLine.append(params_.replace);
                    line += matchPos + matchLen;
                }
                else
                {
                    break;
                }
            }
            else
            {
                if(matches)
                {
                    entry.filename_ = filename;
                    entry.match_ = originalLine;
                    entry.line_ = lineNumber;
					entry.highlights_.push_back(Highlight(matchPos + (line - originalLine), matchLen));
					line += matchPos + matchLen;
                }
				else
				{
					break;
				}
            }

            if(matches)
                hits_++;
        }
        while(*line);

        if(!entry.filename_.empty())
        {
            linesWithHits_++;
            atLeastOneMatch = true;
        }

        if(params_.flags & SF_REPLACE)
        {
            if(line && *line)
                replacedLine += line;
            if(replacedLine != originalLine)
            {
                entry.filename_ = filename;
                entry.match_ = replacedLine;
                entry.line_ = lineNumber;
                append(id, entry);
            }
            replacedLine += "\n";
            updatedContents += replacedLine;
        }
		else
		{
			if(!entry.filename_.empty())
				append(id, entry);
		}
		lineNumber++;
    }
    if(atLeastOneMatch)
        filesWithHits_++;
    if(params_.flags & SF_REPLACE)
    {
        if((contents != updatedContents))
        {
			bool overwriteFile = true;
			if(params_.flags & SF_BACKUP)
			{
				std::string backupFilename = filename;
				backupFilename += ".";
				backupFilename += params_.backupExtension;

				if(!writeEntireFile(backupFilename, contents))
				{
					std::string err = "WARNING: Couldn't write backup file (skipping replacement): ";
					err += backupFilename;
					err += "\n";
					poke(id, err.c_str(), HighlightList(), 0, false);

					overwriteFile = false;
				}
			}

			if(overwriteFile)
			{
				if(writeEntireFile(filename, updatedContents))
				{
					return true;
				}
				else
				{
					std::string err = "WARNING: Couldn't write to file: ";
					err += filename;
					err += "\n";
					poke(id, err.c_str(), HighlightList(), 0, false);
				}
			}
        }
        return false;
    }
    return true;
}
Пример #3
0
bool SearchContext::searchFile(int id, const std::string &filename, RegexList &filespecRegexes, pcre *matchRegex)
{
    bool matchesOneFilespec = false;
    for(RegexList::iterator it = filespecRegexes.begin(); it != filespecRegexes.end(); ++it)
    {
        pcre *regex = *it;
        if(pcre_exec(regex, NULL, filename.c_str(), filename.length(), 0, 0, NULL, 0) >= 0)
        {
            matchesOneFilespec = true;
            break;
        }
    }
    if(!matchesOneFilespec)
        return false;

    std::string contents;
    if(!readEntireFile(filename, contents, params_.maxFileSize))
        return false;

    std::string workBuffer = contents;
    std::string updatedContents;

    std::deque<char *> contextLines;

    bool atLeastOneMatch = false;

    int trailingContextLines = 0;
    int lineNumber = 1;
    char *p = &workBuffer[0];
    char *line;
    while((line = nextToken(&p, '\n')) != NULL)
    {
        char *originalLine = line;
        std::string replacedLine;
        SearchEntry entry;
        int ovector[100];

        // Strip newline, but remember exactly what kind it was
        bool hasCarriageReturn = false;
        int lineLen = strlen(line);
        if(lineLen && (line[lineLen - 1] == '\r'))
        {
            line[lineLen - 1] = 0;
            hasCarriageReturn = true;
        }

        // Matching loop (we might find our string a few times on a single line)
        bool lineMatched = false;
        do
        {
            bool matches = false;
            int matchPos;
            int matchLen;

            // The actual match. Either invoke PCRE or do a boring strstr
            if(matchRegex)
            {
                int rc;
                if(rc = pcre_exec(matchRegex, 0, line, strlen(line), 0, 0, ovector, sizeof(ovector)) >= 0)
                {
                    matches = true;
                    matchPos = ovector[0];
                    matchLen = ovector[1] - ovector[0];
                }
            }
            else
            {
                char *match;
                if(params_.flags & SF_MATCH_CASE_SENSITIVE)
                    match = strstr(line, params_.match.c_str());
                else
                    match = strstri(line, params_.match.c_str());
                if(match != NULL)
                {
                    matches = true;
                    matchPos = match - line;
                    matchLen = params_.match.length();
                }
            }

            if(matches)
                lineMatched = true;

            // Handle the match. For replace or find, we:
            // * Add output explaining the match
            // * Advance the line pointer for another match attempt
            // ... or ...
            // * "break", which leaves the matching loop
            if(params_.flags & SF_REPLACE)
            {
                if(matches)
                {
                    std::string temp(line, matchPos);
                    replacedLine.append(temp);
                    replacedLine.append(params_.replace);
                    entry.textBlocks.addBlock(temp, config_.textColor_);
                    entry.textBlocks.addBlock(params_.replace, config_.highlightColor_, true);
                    line += matchPos + matchLen;
                }
                else
                {
                    break;
                }
            }
            else
            {
                if(matches)
                {
                    entry.textBlocks.addHighlightedBlock(originalLine, matchPos + (line - originalLine), matchLen, config_.textColor_, config_.highlightColor_, true);
                    line += matchPos + matchLen;
                }
                else
                {
                    break;
                }
            }

            if(matches)
                hits_++;
        }
        while(*line); // end of matching loop

        // If we're doing a replace, finish the line and append to the final updated contents
        if(params_.flags & SF_REPLACE)
        {
            if(line && *line)
            {
                replacedLine += line;
                entry.textBlocks.addBlock(line, config_.textColor_);
            }
            if(hasCarriageReturn)
            {
                replacedLine += "\r";
            }
            replacedLine += "\n";
            updatedContents += replacedLine;
        }

        bool outputMatch = false;
        if(lineMatched)
        {
            // keep stats
            linesWithHits_++;
            atLeastOneMatch = true;

            // If we matched, consider notifying the user. We'll always say something
            // unless the replaced text doesn't actually change the line.
            outputMatch = ( !(params_.flags & SF_REPLACE) ) || (replacedLine != originalLine);

            if(outputMatch)
            {
                entry.filename_ = filename;
                entry.line_ = lineNumber;

                // output all existing context lines
                if(contextLines.size())
                {
                    SearchEntry contextEntry;
                    contextEntry.filename_ = entry.filename_;
                    contextEntry.contextOnly_ = true;
                    int currLine = entry.line_ - contextLines.size();
                    for(std::deque<char *>::iterator it = contextLines.begin(); it != contextLines.end(); ++it)
                    {
                        TextBlockList textBlocks;
                        textBlocks.addBlock(*it, config_.textColor_);
                        contextEntry.textBlocks.swap(textBlocks);
                        contextEntry.line_ = currLine++;
                        append(id, contextEntry);
                    }

                    contextLines.clear();
                }

                append(id, entry);
            }

            // Remember that we'd like the next few lines, even if they don't match
            trailingContextLines = config_.contextLines_;
        }

        if(!outputMatch)
        {
            // Didn't output a match. Keep track or output the line anyway for contextual reasons.

            if(trailingContextLines > 0)
            {
                // A recent match wants to see this line in the output anyway

                SearchEntry trailingEntry;
                trailingEntry.filename_ = filename;
                trailingEntry.line_ = lineNumber;
                trailingEntry.contextOnly_ = true;
                trailingEntry.textBlocks.addBlock(originalLine, config_.textColor_);
                append(id, trailingEntry);
                trailingContextLines--;
            }
            else
            {
                // didn't output a match, and wasn't output as context. stash it in contextLines

                contextLines.push_back(originalLine);
                if((int)contextLines.size() > config_.contextLines_)
                    contextLines.pop_front();
            }
        }

        lineNumber++;
    } // end of line loop (done reading file)

    if(atLeastOneMatch)
        filesWithHits_++;

    if(params_.flags & SF_REPLACE)
    {
        if((contents != updatedContents))
        {
            bool overwriteFile = true;
            if(params_.flags & SF_BACKUP)
            {
                std::string backupFilename = filename;
                backupFilename += ".";
                backupFilename += params_.backupExtension;

                if(!writeEntireFile(backupFilename, contents))
                {
                    std::string err = "WARNING: Couldn't write backup file (skipping replacement): ";
                    err += backupFilename;
                    err += "\n";
                    sendError(id, err);

                    overwriteFile = false;
                }
            }

            if(overwriteFile)
            {
                if(writeEntireFile(filename, updatedContents))
                {
                    return true;
                }
                else
                {
                    std::string err = "WARNING: Couldn't write to file: ";
                    err += filename;
                    err += "\n";
                    sendError(id, err);
                }
            }
        }
        return false;
    }
    return true;
}