Beispiel #1
0
/*
 * Takes two savestates and creates a patch that turns 'src' into 'dst'.
 * Both 'src' and 'dst' must be returned from state_manager_raw_alloc(), 
 * with the same 'len', and different 'uniq'.
 *
 * 'patch' must be size 'state_manager_raw_maxsize(len)' or more.
 * Returns the number of bytes actually written to 'patch'.
 */
static size_t state_manager_raw_compress(const void *src,
      const void *dst, size_t len, void *patch)
{
   const uint16_t  *old16 = (const uint16_t*)src;
   const uint16_t  *new16 = (const uint16_t*)dst;
   uint16_t *compressed16 = (uint16_t*)patch;
   size_t          num16s = (len + sizeof(uint16_t) - 1) 
      / sizeof(uint16_t);
   
   while (num16s)
   {
      size_t i, changed;
      size_t skip = find_change(old16, new16);
   
      if (skip >= num16s)
         break;
   
      old16  += skip;
      new16  += skip;
      num16s -= skip;
   
      if (skip > UINT16_MAX)
      {
         if (skip > UINT32_MAX)
         {
            /* This will make it scan the entire thing again, 
             * but it only hits on 8GB unchanged data anyways,
             * and if you're doing that, you've got bigger problems. */
            skip = UINT32_MAX;
         }
         *compressed16++ = 0;
         *compressed16++ = skip;
         *compressed16++ = skip >> 16;
         continue;
      }
   
      changed = find_same(old16, new16);
      if (changed > UINT16_MAX)
         changed = UINT16_MAX;
   
      *compressed16++ = changed;
      *compressed16++ = skip;
   
      for (i = 0; i < changed; i++)
         compressed16[i] = old16[i];
   
      old16 += changed;
      new16 += changed;
      num16s -= changed;
      compressed16 += changed;
   }
   
   compressed16[0] = 0;
   compressed16[1] = 0;
   compressed16[2] = 0;
   
   return (uint8_t*)(compressed16+3) - (uint8_t*)patch;
}
Beispiel #2
0
/**
 * @brief Compare two files (as earlier specified).
 * @return DIFFCODE as a result of compare.
 */
int DiffUtils::diffutils_compare_files()
{
	int bin_flag = 0;
	int bin_file = 0; // bitmap for binary files

	// Do the actual comparison (generating a change script)
	struct change *script = NULL;
	bool success = Diff2Files(&script, 0, &bin_flag, false, &bin_file);
	if (!success)
	{
		return DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::CMPERR;
	}
	UINT code = DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::SAME;

	// make sure to start counting diffs at 0
	// (usually it is -1 at this point, for unknown)
	m_ndiffs = 0;
	m_ntrivialdiffs = 0;

	if (script)
	{
		struct change *next = script;
		struct change *thisob = 0, *end = 0;

		String asLwrCaseExt;
		String LowerCaseExt = CA2T(m_inf[0].name);
		int PosOfDot = LowerCaseExt.rfind('.');
		if (PosOfDot != -1)
		{
			LowerCaseExt.erase(0, PosOfDot + 1);
			CharLower(&*LowerCaseExt.begin());
			asLwrCaseExt = LowerCaseExt;
		}

		while (next)
		{
			/* Find a set of changes that belong together.  */
			thisob = next;
			end = find_change(next);

			/* Disconnect them from the rest of the changes,
			making them a hunk, and remember the rest for next iteration.  */
			next = end->link;
			end->link = 0;
#ifdef _DEBUG
			debug_script(thisob);
#endif

			{
				/* Determine range of line numbers involved in each file.  */
				int first0 = 0, last0 = 0, first1 = 0, last1 = 0, deletes = 0, inserts = 0;
				analyze_hunk(thisob, &first0, &last0, &first1, &last1, &deletes, &inserts);
				if (deletes || inserts || thisob->trivial)
				{
					/* Print the lines that the first file has.  */
					int trans_a0 = 0, trans_b0 = 0, trans_a1 = 0, trans_b1 = 0;
					translate_range(&m_inf[0], first0, last0, &trans_a0, &trans_b0);
					translate_range(&m_inf[1], first1, last1, &trans_a1, &trans_b1);

					//Determine quantity of lines in this block for both sides
					int QtyLinesLeft = (trans_b0 - trans_a0);
					int QtyLinesRight = (trans_b1 - trans_a1);


					if(m_pOptions->m_filterCommentsLines || m_pOptions->m_bIgnoreBlankLines || m_pOptions->m_bIgnoreCase)
					{
						OP_TYPE op = OP_NONE;
						if (!deletes && !inserts)
							op = OP_TRIVIAL;
						else
							op = OP_DIFF;

						DIFFOPTIONS options = {0};
						options.nIgnoreWhitespace = m_pOptions->m_ignoreWhitespace;
						options.bIgnoreBlankLines = m_pOptions->m_bIgnoreBlankLines;
						options.bFilterCommentsLines = m_pOptions->m_filterCommentsLines;
						options.bIgnoreCase = m_pOptions->m_bIgnoreCase;
						options.bIgnoreEol = m_pOptions->m_bIgnoreEOLDifference;
						m_pDiffWrapper->SetOptions(&options);
  						m_pDiffWrapper->PostFilter(thisob->line0, QtyLinesLeft+1, thisob->line1, QtyLinesRight+1, op, *m_FilterCommentsManager, asLwrCaseExt.c_str());
						if(op == OP_TRIVIAL)
						{
							thisob->trivial = 1;
						}
					}

					// Match lines against regular expression filters
					// Our strategy is that every line in both sides must
					// match regexp before we mark difference as ignored.
					if(m_pFilterList && m_pFilterList->HasRegExps())
					{
						bool match2 = false;
						bool match1 = RegExpFilter(thisob->line0, thisob->line0 + QtyLinesLeft, 0);
						if (match1)
							match2 = RegExpFilter(thisob->line1, thisob->line1 + QtyLinesRight, 1);
						if (match1 && match2)
							thisob->trivial = 1;
					}

				}
				/* Reconnect the script so it will all be freed properly.  */
				end->link = next;
			}
		}
	}


	// Free change script (which we don't want)
	if (script != NULL)
	{
		struct change *p, *e;
		for (e = script; e; e = p)
		{
			if (!e->trivial)
				++m_ndiffs;
			else
				++m_ntrivialdiffs;
			p = e->link;
			free(e);
		}
		if (m_ndiffs > 0)
			code = code & ~DIFFCODE::SAME | DIFFCODE::DIFF;
	}

	// diff_2_files set bin_flag to -1 if different binary
	// diff_2_files set bin_flag to +1 if same binary

	if (bin_flag != 0)
	{
		// Clear text-flag, set binary flag
		// We don't know diff counts for binary files
		code = code & ~DIFFCODE::TEXT;
		switch (bin_file)
		{
		case BINFILE_SIDE1:
			code |= DIFFCODE::BINSIDE1;
			break;
		case BINFILE_SIDE2:
			code |= DIFFCODE::BINSIDE2;
			break;
		case BINFILE_SIDE1 | BINFILE_SIDE2:
			code |= DIFFCODE::BIN;
			break;
		default:
			_RPTF1(_CRT_ERROR, "Invalid bin_file value: %d", bin_file);
			break;
		}
		m_ndiffs = CDiffContext::DIFFS_UNKNOWN;
	}

	if (bin_flag < 0)
	{
		// Clear same-flag, set diff-flag
		code = code & ~DIFFCODE::SAME | DIFFCODE::DIFF;
	}

	return code;
}