/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef _DAI_FILECOMPARE_H_ #define _DAI_FILECOMPARE_H_ #include "OdString.h" #define STL_USING_VECTOR #define STL_USING_SET #define STL_USING_STREAM #define STL_USING_STRING #define STL_USING_MEMORY #include "OdaSTL.h" #include "TD_PackPush.h" namespace OdDAI { namespace utils { struct CompareInfo { std::string line; int lineIndex = 1; int charIndex = 0; }; class DefaultFilter { public: bool operator()(char symbolToCheck) { return symbolToCheck == '\t' || symbolToCheck == '\r' || symbolToCheck == ' ' || symbolToCheck == '\n'; } }; template bool readNextChar(std::istreambuf_iterator& marker, char& value, CompareInfo& cmpInfo) { std::istreambuf_iterator endValue; static SymbolFilter filter; while (marker != endValue && (filter(*marker) || *marker == '\n')) { if (*marker == '\n') { ++cmpInfo.lineIndex; cmpInfo.charIndex = 0; cmpInfo.line.clear(); } else { ++cmpInfo.charIndex; cmpInfo.line += *marker; } ++marker; } if (marker == endValue) { return false; } value = *marker; cmpInfo.line += *marker; ++cmpInfo.charIndex; ++marker; return true; } void prepareFailedCompareMessage(std::istreambuf_iterator& marker, CompareInfo& cmpInfo, std::ostream& errorOutput) { std::istreambuf_iterator endValue; while (marker != endValue) { if (*marker == '\n') { break; } else { cmpInfo.line += *marker; } ++marker; } errorOutput << "line: " << cmpInfo.lineIndex << std::endl << "char: " << cmpInfo.charIndex << std::endl << "string: " << cmpInfo.line << std::endl; } template bool compareFiles(const OdString& fileLeft, const OdString& fileRight, std::ostream& errorOutput) { std::ifstream leftStream(OdAnsiString(fileLeft), std::ifstream::binary | std::ifstream::ate); std::ifstream rightStream(OdAnsiString(fileRight), std::ifstream::binary | std::ifstream::ate); if (leftStream.fail()) { errorOutput << "The target file for comparison was not created\n"; return false; //file problem } if (rightStream.fail()) { errorOutput << "Benchmak for comparison was not found\n"; return false; //file problem } //seek back to beginning and use std::equal to compare contents leftStream.seekg(0, std::ifstream::beg); rightStream.seekg(0, std::ifstream::beg); std::istreambuf_iterator leftIterator(leftStream.rdbuf()); std::istreambuf_iterator rightIterator(rightStream.rdbuf()); CompareInfo leftCmpInfo; CompareInfo rightCmpInfo; while (true) { char leftCmpSymbol{}; char rightCmpSymbol{}; bool leftReadResult = readNextChar(leftIterator, leftCmpSymbol, leftCmpInfo); bool rightReadResult = readNextChar(rightIterator, rightCmpSymbol, rightCmpInfo); if (leftReadResult != rightReadResult || leftCmpSymbol != rightCmpSymbol) { errorOutput << "Benchmark difference detected:" << std::endl; errorOutput << "File - " << std::string(OdAnsiString(fileLeft).c_str()) << ": " << std::endl; prepareFailedCompareMessage(leftIterator, leftCmpInfo, errorOutput); errorOutput << std::endl << std::endl; errorOutput << "File - " << std::string(OdAnsiString(fileRight).c_str()) << ": " << std::endl; prepareFailedCompareMessage(rightIterator, rightCmpInfo, errorOutput); errorOutput << std::endl << std::endl; return false; } if (!leftReadResult) { break; } } return true; } } } #include "TD_PackPop.h" #endif // _DAI_FILECOMPARE_H_