X-Git-Url: https://projects.mako.cc/source/wikiq/blobdiff_plain/a8bbe4703654e6d6131368c0c42995f8933b3dce..26c05eec96c89590ddf4d516ae0cf9fc6bdbec82:/dtl/Diff3.hpp diff --git a/dtl/Diff3.hpp b/dtl/Diff3.hpp new file mode 100644 index 0000000..1740ec4 --- /dev/null +++ b/dtl/Diff3.hpp @@ -0,0 +1,245 @@ +/** + dtl-1.12 -- Diff Template Library + + In short, Diff Template Library is distributed under so called "BSD license", + + Copyright (c) 2008-2011 Tatsuhiko Kubo + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* If you use this library, you must include dtl.hpp only. */ + +#ifndef DTL_DIFF3_H +#define DTL_DIFF3_H + +namespace dtl { + + /** + * diff3 class template + * sequence must support random_access_iterator. + */ + template , typename comparator = Compare< elem > > + class Diff3 + { + private: + dtl_typedefs(elem, sequence) + sequence A; + sequence B; + sequence C; + sequence S; + Diff< elem, sequence, comparator > diff_ba; + Diff< elem, sequence, comparator > diff_bc; + bool conflict; + elem csepabegin; + elem csepa; + elem csepaend; + public : + Diff3 () {} + Diff3 (const sequence& a, + const sequence& b, + const sequence& c) : A(a), B(b), C(c), + diff_ba(b, a), diff_bc(b, c), + conflict(false) {} + + ~Diff3 () {} + + bool isConflict () const { + return conflict; + } + + sequence getMergedSequence () const { + return S; + } + + /** + * merge changes B and C to A + */ + bool merge () { + if (diff_ba.getEditDistance() == 0) { // A == B + if (diff_bc.getEditDistance() == 0) { // A == B == C + S = B; + return true; + } + S = C; + return true; + } else { // A != B + if (diff_bc.getEditDistance() == 0) { // A != B == C + S = A; + return true; + } else { // A != B != C + S = merge_(); + if (isConflict()) { // conflict occured + return false; + } + } + } + return true; + } + + /** + * compose differences + */ + void compose () { + diff_ba.compose(); + diff_bc.compose(); + } + + private : + /** + * merge implementation + */ + sequence merge_ () { + elemVec seq; + Ses< elem > ses_ba = diff_ba.getSes(); + Ses< elem > ses_bc = diff_bc.getSes(); + sesElemVec ses_ba_v = ses_ba.getSequence(); + sesElemVec ses_bc_v = ses_bc.getSequence(); + sesElemVec_iter ba_it = ses_ba_v.begin(); + sesElemVec_iter bc_it = ses_bc_v.begin(); + sesElemVec_iter ba_end = ses_ba_v.end(); + sesElemVec_iter bc_end = ses_bc_v.end(); + + while (!isEnd(ba_end, ba_it) || !isEnd(bc_end, bc_it)) { + while (true) { + if (!isEnd(ba_end, ba_it) && + !isEnd(bc_end, bc_it) && + ba_it->first == bc_it->first && + ba_it->second.type == SES_COMMON && + bc_it->second.type == SES_COMMON) { + // do nothing + } else { + break; + } + if (!isEnd(ba_end, ba_it)) seq.push_back(ba_it->first); + else if (!isEnd(bc_end, bc_it)) seq.push_back(bc_it->first); + forwardUntilEnd(ba_end, ba_it); + forwardUntilEnd(bc_end, bc_it); + } + if (isEnd(ba_end, ba_it) || isEnd(bc_end, bc_it)) break; + if ( ba_it->second.type == SES_COMMON + && bc_it->second.type == SES_DELETE) { + forwardUntilEnd(ba_end, ba_it); + forwardUntilEnd(bc_end, bc_it); + } else if (ba_it->second.type == SES_COMMON && + bc_it->second.type == SES_ADD) { + seq.push_back(bc_it->first); + forwardUntilEnd(bc_end, bc_it); + } else if (ba_it->second.type == SES_DELETE && + bc_it->second.type == SES_COMMON) { + forwardUntilEnd(ba_end, ba_it); + forwardUntilEnd(bc_end, bc_it); + } else if (ba_it->second.type == SES_DELETE && + bc_it->second.type == SES_DELETE) { + if (ba_it->first == bc_it->first) { + forwardUntilEnd(ba_end, ba_it); + forwardUntilEnd(bc_end, bc_it); + } else { + // conflict + conflict = true; + return B; + } + } else if (ba_it->second.type == SES_DELETE && + bc_it->second.type == SES_ADD) { + // conflict + conflict = true; + return B; + } else if (ba_it->second.type == SES_ADD && + bc_it->second.type == SES_COMMON) { + seq.push_back(ba_it->first); + forwardUntilEnd(ba_end, ba_it); + } else if (ba_it->second.type == SES_ADD && + bc_it->second.type == SES_DELETE) { + // conflict + conflict = true; + return B; + } else if (ba_it->second.type == SES_ADD && + bc_it->second.type == SES_ADD) { + if (ba_it->first == bc_it->first) { + seq.push_back(ba_it->first); + forwardUntilEnd(ba_end, ba_it); + forwardUntilEnd(bc_end, bc_it); + } else { + // conflict + conflict = true; + return B; + } + } + } + + if (isEnd(ba_end, ba_it)) { + addDecentSequence(bc_end, bc_it, seq); + } else if (isEnd(bc_end, bc_it)) { + addDecentSequence(ba_end, ba_it, seq); + } + + sequence mergedSeq(seq.begin(), seq.end()); + return mergedSeq; + } + + /** + * join elem vectors + */ + void inline joinElemVec (elemVec& s1, elemVec& s2) const { + if (!s2.empty()) { + for (elemVec_iter vit=s2.begin();vit!=s2.end();++vit) { + s1.push_back(*vit); + } + } + } + + /** + * check sequence is end + */ + template + bool inline isEnd (const T_iter& end, const T_iter& it) const { + return it == end ? true : false; + } + + /** + * increment iterator until iterator is end + */ + template + void inline forwardUntilEnd (const T_iter& end, T_iter& it) const { + if (!isEnd(end, it)) ++it; + } + + /** + * add elements which SES's type is ADD + */ + void inline addDecentSequence (const sesElemVec_iter& end, sesElemVec_iter& it, elemVec& seq) const { + while (!isEnd(end, it)) { + if (it->second.type == SES_ADD) seq.push_back(it->first); + ++it; + } + } + + }; +} + +#endif // DTL_DIFF3_H