OSDN Git Service

Add libsvn_diff
[tortoisegit/TortoiseGitJp.git] / src / TortoiseMerge / libsvn_diff / diff.c
diff --git a/src/TortoiseMerge/libsvn_diff/diff.c b/src/TortoiseMerge/libsvn_diff/diff.c
new file mode 100644 (file)
index 0000000..627cec3
--- /dev/null
@@ -0,0 +1,146 @@
+/*\r
+ * diff.c :  routines for doing diffs\r
+ *\r
+ * ====================================================================\r
+ * Copyright (c) 2000-2004 CollabNet.  All rights reserved.\r
+ *\r
+ * This software is licensed as described in the file COPYING, which\r
+ * you should have received as part of this distribution.  The terms\r
+ * are also available at http://subversion.tigris.org/license-1.html.\r
+ * If newer versions of this license are posted there, you may use a\r
+ * newer version instead, at your option.\r
+ *\r
+ * This software consists of voluntary contributions made by many\r
+ * individuals.  For exact contribution history, see the revision\r
+ * history and logs, available at http://subversion.tigris.org/.\r
+ * ====================================================================\r
+ */\r
+\r
+\r
+#include <apr.h>\r
+#include <apr_pools.h>\r
+#include <apr_general.h>\r
+\r
+#include "svn_pools.h"\r
+#include "svn_error.h"\r
+#include "svn_diff.h"\r
+#include "svn_types.h"\r
+\r
+#include "diff.h"\r
+\r
+\r
+svn_diff_t *\r
+svn_diff__diff(svn_diff__lcs_t *lcs,\r
+               apr_off_t original_start, apr_off_t modified_start,\r
+               svn_boolean_t want_common,\r
+               apr_pool_t *pool)\r
+{\r
+  svn_diff_t *diff;\r
+  svn_diff_t **diff_ref = &diff;\r
+\r
+  while (1)\r
+    {\r
+      if (original_start < lcs->position[0]->offset\r
+          || modified_start < lcs->position[1]->offset)\r
+      {\r
+          (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref));\r
+\r
+          (*diff_ref)->type = svn_diff__type_diff_modified;\r
+          (*diff_ref)->original_start = original_start - 1;\r
+          (*diff_ref)->original_length =\r
+            lcs->position[0]->offset - original_start;\r
+          (*diff_ref)->modified_start = modified_start - 1;\r
+          (*diff_ref)->modified_length =\r
+            lcs->position[1]->offset - modified_start;\r
+          (*diff_ref)->latest_start = 0;\r
+          (*diff_ref)->latest_length = 0;\r
+\r
+          diff_ref = &(*diff_ref)->next;\r
+      }\r
+\r
+      /* Detect the EOF */\r
+      if (lcs->length == 0)\r
+          break;\r
+\r
+      original_start = lcs->position[0]->offset;\r
+      modified_start = lcs->position[1]->offset;\r
+\r
+      if (want_common)\r
+        {\r
+          (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref));\r
+\r
+          (*diff_ref)->type = svn_diff__type_common;\r
+          (*diff_ref)->original_start = original_start - 1;\r
+          (*diff_ref)->original_length = lcs->length;\r
+          (*diff_ref)->modified_start = modified_start - 1;\r
+          (*diff_ref)->modified_length = lcs->length;\r
+          (*diff_ref)->latest_start = 0;\r
+          (*diff_ref)->latest_length = 0;\r
+\r
+          diff_ref = &(*diff_ref)->next;\r
+        }\r
+\r
+      original_start += lcs->length;\r
+      modified_start += lcs->length;\r
+\r
+      lcs = lcs->next;\r
+    }\r
+\r
+  *diff_ref = NULL;\r
+\r
+  return diff;\r
+}\r
+\r
+\r
+svn_error_t *\r
+svn_diff_diff(svn_diff_t **diff,\r
+              void *diff_baton,\r
+              const svn_diff_fns_t *vtable,\r
+              apr_pool_t *pool)\r
+{\r
+  svn_diff__tree_t *tree;\r
+  svn_diff__position_t *position_list[2];\r
+  svn_diff__lcs_t *lcs;\r
+  apr_pool_t *subpool;\r
+  apr_pool_t *treepool;\r
+\r
+  *diff = NULL;\r
+\r
+  subpool = svn_pool_create(pool);\r
+  treepool = svn_pool_create(pool);\r
+\r
+  svn_diff__tree_create(&tree, treepool);\r
+\r
+  /* Insert the data into the tree */\r
+  SVN_ERR(svn_diff__get_tokens(&position_list[0],\r
+                               tree,\r
+                               diff_baton, vtable,\r
+                               svn_diff_datasource_original,\r
+                               subpool));\r
+\r
+  SVN_ERR(svn_diff__get_tokens(&position_list[1],\r
+                               tree,\r
+                               diff_baton, vtable,\r
+                               svn_diff_datasource_modified,\r
+                               subpool));\r
+\r
+  /* The cool part is that we don't need the tokens anymore.\r
+   * Allow the app to clean them up if it wants to.\r
+   */\r
+  if (vtable->token_discard_all != NULL)\r
+    vtable->token_discard_all(diff_baton);\r
+\r
+  /* We don't need the nodes in the tree either anymore, nor the tree itself */\r
+  svn_pool_destroy(treepool);\r
+\r
+  /* Get the lcs */\r
+  lcs = svn_diff__lcs(position_list[0], position_list[1], subpool);\r
+\r
+  /* Produce the diff */\r
+  *diff = svn_diff__diff(lcs, 1, 1, TRUE, pool);\r
+\r
+  /* Get rid of all the data we don't have a use for anymore */\r
+  svn_pool_destroy(subpool);\r
+\r
+  return SVN_NO_ERROR;\r
+}\r