fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / registry / tools / regcompare.cxx
blob8d4d4221bc5d9df1a1c2a6c330a4e4bfe6befb57
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "registry/registry.hxx"
22 #include "registry/reader.hxx"
23 #include "registry/version.h"
24 #include "fileurl.hxx"
25 #include "options.hxx"
27 #include <rtl/ustring.hxx>
28 #include <osl/diagnose.h>
30 #include <stdio.h>
31 #include <string.h>
33 #include <set>
34 #include <vector>
35 #include <string>
37 using namespace registry::tools;
39 typedef std::set< OUString > StringSet;
41 class Options_Impl : public Options
43 public:
44 explicit Options_Impl(char const * program)
45 : Options(program),
46 m_bFullCheck(false),
47 m_bForceOutput(false),
48 m_bUnoTypeCheck(false),
49 m_checkUnpublished(false)
52 std::string const & getRegName1() const { return m_regName1; }
53 std::string const & getRegName2() const { return m_regName2; }
55 bool isStartKeyValid() const { return !m_startKey.isEmpty(); }
56 OUString const & getStartKey() const { return m_startKey; }
57 bool matchedWithExcludeKey( const OUString& keyName) const;
59 bool fullCheck() const { return m_bFullCheck; }
60 bool forceOutput() const { return m_bForceOutput; }
61 bool unoTypeCheck() const { return m_bUnoTypeCheck; }
62 bool checkUnpublished() const { return m_checkUnpublished; }
64 protected:
65 bool setRegName_Impl(char c, std::string const & param);
67 virtual void printUsage_Impl() const SAL_OVERRIDE;
68 virtual bool initOptions_Impl (std::vector< std::string > & rArgs) SAL_OVERRIDE;
70 std::string m_regName1;
71 std::string m_regName2;
72 OUString m_startKey;
73 StringSet m_excludeKeys;
74 bool m_bFullCheck;
75 bool m_bForceOutput;
76 bool m_bUnoTypeCheck;
77 bool m_checkUnpublished;
80 #define U2S( s ) OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr()
82 inline OUString makeOUString (std::string const & s)
84 return OUString(s.c_str(), s.size(), RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
87 inline OUString shortName(OUString const & fullName)
89 return fullName.copy(fullName.lastIndexOf('/') + 1);
92 bool Options_Impl::setRegName_Impl(char c, std::string const & param)
94 bool one = (c == '1'), two = (c == '2');
95 if (one)
96 m_regName1 = param;
97 if (two)
98 m_regName2 = param;
99 return (one || two);
102 //virtual
103 void Options_Impl::printUsage_Impl() const
105 std::string const & rProgName = getProgramName();
106 fprintf(stderr,
107 "Usage: %s -r1<filename> -r2<filename> [-options] | @<filename>\n", rProgName.c_str()
109 fprintf(stderr,
110 " -r1<filename> = filename specifies the name of the first registry.\n"
111 " -r2<filename> = filename specifies the name of the second registry.\n"
112 " @<filename> = filename specifies a command file.\n"
113 "Options:\n"
114 " -s<name> = name specifies the name of a start key. If no start key\n"
115 " |S<name> is specified the comparison starts with the root key.\n"
116 " -x<name> = name specifies the name of a key which won't be compared. All\n"
117 " |X<name> subkeys won't be compared also. This option can be used more than once.\n"
118 " -f|F = force the detailed output of any diffenrences. Default\n"
119 " is that only the number of differences is returned.\n"
120 " -c|C = make a complete check, that means any differences will be\n"
121 " detected. Default is only a compatibility check that means\n"
122 " only UNO typelibrary entries will be checked.\n"
123 " -t|T = make an UNO type compatibility check. This means that registry 2\n"
124 " will be checked against registry 1. If a interface in r2 contains\n"
125 " more methods or the methods are in a different order as in r1, r2 is\n"
126 " incompatible to r1. But if a service in r2 supports more properties as\n"
127 " in r1 and the new properties are 'optional' it is compatible.\n"
128 " -u|U = additionally check types that are unpublished in registry 1.\n"
129 " -h|-? = print this help message and exit.\n"
131 fprintf(stderr,
132 "\n%s Version 1.0\n\n", rProgName.c_str()
136 // virtual
137 bool Options_Impl::initOptions_Impl (std::vector< std::string > & rArgs)
139 std::vector< std::string >::const_iterator first = rArgs.begin(), last = rArgs.end();
140 for (; first != last; ++first)
142 if ((*first)[0] != '-')
144 return badOption("invalid", (*first).c_str());
146 switch ((*first)[1])
148 case 'r':
149 case 'R':
151 if (!((++first != last) && ((*first)[0] != '-')))
153 return badOption("invalid", (*first).c_str());
156 std::string option(*first), param;
157 if (option.size() == 1)
159 // "-r<n><space><param>"
160 if (!((++first != last) && ((*first)[0] != '-')))
162 return badOption("invalid", (*first).c_str());
164 param = (*first);
166 else
168 // "-r<n><param>"
169 param = std::string(&(option[1]), option.size() - 1);
171 if (!setRegName_Impl(option[0], param))
173 return badOption("invalid", option.c_str());
175 break;
177 case 's':
178 case 'S':
180 if (!((++first != last) && ((*first)[0] != '-')))
182 return badOption("invalid", (*first).c_str());
184 m_startKey = makeOUString(*first);
185 break;
187 case 'x':
188 case 'X':
190 if (!((++first != last) && ((*first)[0] != '-')))
192 return badOption("invalid", (*first).c_str());
194 m_excludeKeys.insert(makeOUString(*first));
195 break;
197 case 'f':
198 case 'F':
200 if ((*first).size() > 2)
202 return badOption("invalid", (*first).c_str());
204 m_bForceOutput = true;
205 break;
207 case 'c':
208 case 'C':
210 if ((*first).size() > 2)
212 return badOption("invalid", (*first).c_str());
214 m_bFullCheck = true;
215 break;
217 case 't':
218 case 'T':
220 if ((*first).size() > 2)
222 return badOption("invalid", (*first).c_str());
224 m_bUnoTypeCheck = true;
225 break;
227 case 'u':
228 case 'U':
230 if ((*first).size() > 2)
232 return badOption("invalid", (*first).c_str());
234 m_checkUnpublished = true;
235 break;
237 case 'h':
238 case '?':
240 if ((*first).size() > 2)
242 return badOption("invalid", (*first).c_str());
244 return printUsage();
246 default:
248 return badOption("unknown", (*first).c_str());
253 if ( m_regName1.empty() )
255 return badOption("missing", "-r1");
257 if ( m_regName2.empty() )
259 return badOption("missing", "-r2");
261 return true;
264 bool Options_Impl::matchedWithExcludeKey( const OUString& keyName) const
266 if (!m_excludeKeys.empty())
268 StringSet::const_iterator first = m_excludeKeys.begin(), last = m_excludeKeys.end();
269 for (; first != last; ++first)
271 if (keyName.startsWith(*first))
272 return true;
275 return false;
278 static char const * getTypeClass(RTTypeClass typeClass)
280 switch (typeClass)
282 case RT_TYPE_INTERFACE:
283 return "INTERFACE";
284 case RT_TYPE_MODULE:
285 return "MODULE";
286 case RT_TYPE_STRUCT:
287 return "STRUCT";
288 case RT_TYPE_ENUM:
289 return "ENUM";
290 case RT_TYPE_EXCEPTION:
291 return "EXCEPTION";
292 case RT_TYPE_TYPEDEF:
293 return "TYPEDEF";
294 case RT_TYPE_SERVICE:
295 return "SERVICE";
296 case RT_TYPE_OBJECT:
297 return "OBJECT";
298 case RT_TYPE_CONSTANTS:
299 return "CONSTANTS";
300 default:
301 return "INVALID";
305 static OString getFieldAccess(RTFieldAccess fieldAccess)
307 OString ret;
308 if ( (fieldAccess & RTFieldAccess::INVALID) == RTFieldAccess::INVALID )
310 ret += OString("INVALID");
312 if ( (fieldAccess & RTFieldAccess::READONLY) == RTFieldAccess::READONLY )
314 ret += OString(ret.isEmpty() ? "READONLY" : ",READONLY");
316 if ( (fieldAccess & RTFieldAccess::OPTIONAL) == RTFieldAccess::OPTIONAL )
318 ret += OString(ret.isEmpty() ? "OPTIONAL" : ",OPTIONAL");
320 if ( (fieldAccess & RTFieldAccess::MAYBEVOID) == RTFieldAccess::MAYBEVOID )
322 ret += OString(ret.isEmpty() ? "MAYBEVOID" : ",MAYBEVOID");
324 if ( (fieldAccess & RTFieldAccess::BOUND) == RTFieldAccess::BOUND )
326 ret += OString(ret.isEmpty() ? "BOUND" : ",BOUND");
328 if ( (fieldAccess & RTFieldAccess::CONSTRAINED) == RTFieldAccess::CONSTRAINED )
330 ret += OString(ret.isEmpty() ? "CONSTRAINED" : ",CONSTRAINED");
332 if ( (fieldAccess & RTFieldAccess::TRANSIENT) == RTFieldAccess::TRANSIENT )
334 ret += OString(ret.isEmpty() ? "TRANSIENT" : ",TRANSIENT");
336 if ( (fieldAccess & RTFieldAccess::MAYBEAMBIGUOUS) == RTFieldAccess::MAYBEAMBIGUOUS )
338 ret += OString(ret.isEmpty() ? "MAYBEAMBIGUOUS" : ",MAYBEAMBIGUOUS");
340 if ( (fieldAccess & RTFieldAccess::MAYBEDEFAULT) == RTFieldAccess::MAYBEDEFAULT )
342 ret += OString(ret.isEmpty() ? "MAYBEDEFAULT" : ",MAYBEDEFAULT");
344 if ( (fieldAccess & RTFieldAccess::REMOVABLE) == RTFieldAccess::REMOVABLE )
346 ret += OString(ret.isEmpty() ? "REMOVABLE" : ",REMOVABLE");
348 if ( (fieldAccess & RTFieldAccess::ATTRIBUTE) == RTFieldAccess::ATTRIBUTE )
350 ret += OString(ret.isEmpty() ? "ATTRIBUTE" : ",ATTRIBUTE");
352 if ( (fieldAccess & RTFieldAccess::PROPERTY) == RTFieldAccess::PROPERTY )
354 ret += OString(ret.isEmpty() ? "PROPERTY" : ",PROPERTY");
356 if ( (fieldAccess & RTFieldAccess::CONST) == RTFieldAccess::CONST )
358 ret += OString(ret.isEmpty() ? "CONST" : ",CONST");
360 if ( (fieldAccess & RTFieldAccess::READWRITE) == RTFieldAccess::READWRITE )
362 ret += OString(ret.isEmpty() ? "READWRITE" : ",READWRITE");
364 return ret;
367 static char const * getConstValueType(RTConstValue& constValue)
369 switch (constValue.m_type)
371 case RT_TYPE_BOOL:
372 return "sal_Bool";
373 case RT_TYPE_BYTE:
374 return "sal_uInt8";
375 case RT_TYPE_INT16:
376 return "sal_Int16";
377 case RT_TYPE_UINT16:
378 return "sal_uInt16";
379 case RT_TYPE_INT32:
380 return "sal_Int32";
381 case RT_TYPE_UINT32:
382 return "sal_uInt32";
383 // case RT_TYPE_INT64:
384 // return "sal_Int64";
385 // case RT_TYPE_UINT64:
386 // return "sal_uInt64";
387 case RT_TYPE_FLOAT:
388 return "float";
389 case RT_TYPE_DOUBLE:
390 return "double";
391 case RT_TYPE_STRING:
392 return "sal_Unicode*";
393 default:
394 return "NONE";
398 static void printConstValue(RTConstValue& constValue)
400 switch (constValue.m_type)
402 case RT_TYPE_NONE:
403 fprintf(stdout, "none");
404 break;
405 case RT_TYPE_BOOL:
406 fprintf(stdout, "%s", constValue.m_value.aBool ? "TRUE" : "FALSE");
407 break;
408 case RT_TYPE_BYTE:
409 fprintf(stdout, "%d", constValue.m_value.aByte);
410 break;
411 case RT_TYPE_INT16:
412 fprintf(stdout, "%d", constValue.m_value.aShort);
413 break;
414 case RT_TYPE_UINT16:
415 fprintf(stdout, "%d", constValue.m_value.aUShort);
416 break;
417 case RT_TYPE_INT32:
418 fprintf(
419 stdout, "%ld",
420 sal::static_int_cast< long >(constValue.m_value.aLong));
421 break;
422 case RT_TYPE_UINT32:
423 fprintf(
424 stdout, "%lu",
425 sal::static_int_cast< unsigned long >(
426 constValue.m_value.aULong));
427 break;
428 // case RT_TYPE_INT64:
429 // fprintf(stdout, "%d", constValue.m_value.aHyper);
430 // case RT_TYPE_UINT64:
431 // fprintf(stdout, "%d", constValue.m_value.aUHyper);
432 case RT_TYPE_FLOAT:
433 fprintf(stdout, "%f", constValue.m_value.aFloat);
434 break;
435 case RT_TYPE_DOUBLE:
436 fprintf(stdout, "%f", constValue.m_value.aDouble);
437 break;
438 case RT_TYPE_STRING:
439 fprintf(
440 stdout, "%s",
441 (OUStringToOString(
442 constValue.m_value.aString, RTL_TEXTENCODING_UTF8).
443 getStr()));
444 break;
445 default:
446 break;
450 static void dumpTypeClass(bool & rbDump, RTTypeClass typeClass, OUString const & keyName)
452 if (rbDump)
453 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
454 rbDump = false;
457 static sal_uInt32 checkConstValue(Options_Impl const & options,
458 const OUString& keyName,
459 RTTypeClass typeClass,
460 bool & bDump,
461 RTConstValue& constValue1,
462 RTConstValue& constValue2,
463 sal_uInt16 index1)
465 switch (constValue1.m_type)
467 case RT_TYPE_NONE:
468 break;
469 case RT_TYPE_BOOL:
470 if (constValue1.m_value.aBool != constValue2.m_value.aBool)
472 if ( options.forceOutput() && !options.unoTypeCheck() )
474 dumpTypeClass(bDump, typeClass, keyName);
475 fprintf(stdout, " Field %d: Value1 = %s != Value2 = %s\n", index1,
476 constValue1.m_value.aBool ? "TRUE" : "FALSE",
477 constValue2.m_value.aBool ? "TRUE" : "FALSE");
479 return 1;
481 break;
482 case RT_TYPE_BYTE:
483 if (constValue1.m_value.aByte != constValue2.m_value.aByte)
485 if ( options.forceOutput() && !options.unoTypeCheck() )
487 dumpTypeClass(bDump, typeClass, keyName);
488 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
489 constValue1.m_value.aByte, constValue2.m_value.aByte);
491 return 1;
493 break;
494 case RT_TYPE_INT16:
495 if (constValue1.m_value.aShort != constValue2.m_value.aShort)
497 if ( options.forceOutput() && !options.unoTypeCheck() )
499 dumpTypeClass(bDump, typeClass, keyName);
500 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
501 constValue1.m_value.aShort, constValue2.m_value.aShort);
503 return 1;
505 break;
506 case RT_TYPE_UINT16:
507 if (constValue1.m_value.aUShort != constValue2.m_value.aUShort)
509 if ( options.forceOutput() && !options.unoTypeCheck() )
511 dumpTypeClass(bDump, typeClass, keyName);
512 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
513 constValue1.m_value.aUShort, constValue2.m_value.aUShort);
515 return 1;
517 break;
518 case RT_TYPE_INT32:
519 if (constValue1.m_value.aLong != constValue2.m_value.aLong)
521 if ( options.forceOutput() && !options.unoTypeCheck() )
523 dumpTypeClass(bDump, typeClass, keyName);
524 fprintf(stdout, " Field %d: Value1 = %ld != Value2 = %ld\n", index1,
525 sal::static_int_cast< long >(constValue1.m_value.aLong),
526 sal::static_int_cast< long >(constValue2.m_value.aLong));
528 return 1;
530 break;
531 case RT_TYPE_UINT32:
532 if (constValue1.m_value.aULong != constValue2.m_value.aULong)
534 if ( options.forceOutput() && !options.unoTypeCheck() )
536 dumpTypeClass(bDump, typeClass, keyName);
537 fprintf(stdout, " Field %d: Value1 = %lu != Value2 = %lu\n", index1,
538 sal::static_int_cast< unsigned long >(constValue1.m_value.aULong),
539 sal::static_int_cast< unsigned long >(constValue2.m_value.aULong));
541 return 1;
543 break;
544 case RT_TYPE_INT64:
545 if (constValue1.m_value.aHyper != constValue2.m_value.aHyper)
547 if ( options.forceOutput() && !options.unoTypeCheck() )
549 dumpTypeClass(bDump, typeClass, keyName);
550 fprintf(
551 stdout, " Field %d: Value1 = %s != Value2 = %s\n",
552 index1,
553 OUStringToOString(
554 OUString::number(constValue1.m_value.aHyper),
555 RTL_TEXTENCODING_ASCII_US).getStr(),
556 OUStringToOString(
557 OUString::number(constValue2.m_value.aHyper),
558 RTL_TEXTENCODING_ASCII_US).getStr());
560 return 1;
562 break;
563 case RT_TYPE_UINT64:
564 if (constValue1.m_value.aUHyper != constValue2.m_value.aUHyper)
566 if ( options.forceOutput() && !options.unoTypeCheck() )
568 dumpTypeClass(bDump, typeClass, keyName);
569 fprintf(
570 stdout, " Field %d: Value1 = %s != Value2 = %s\n",
571 index1,
572 OUStringToOString(
573 OUString::number(
574 constValue1.m_value.aUHyper),
575 RTL_TEXTENCODING_ASCII_US).getStr(),
576 OUStringToOString(
577 OUString::number(
578 constValue2.m_value.aUHyper),
579 RTL_TEXTENCODING_ASCII_US).getStr());
580 // printing the unsigned values as signed should be
581 // acceptable...
583 return 1;
585 break;
586 case RT_TYPE_FLOAT:
587 if (constValue1.m_value.aFloat != constValue2.m_value.aFloat)
589 if ( options.forceOutput() && !options.unoTypeCheck() )
591 dumpTypeClass(bDump, typeClass, keyName);
592 fprintf(stdout, " Field %d: Value1 = %f != Value2 = %f\n", index1,
593 constValue1.m_value.aFloat, constValue2.m_value.aFloat);
595 return 1;
597 break;
598 case RT_TYPE_DOUBLE:
599 if (constValue1.m_value.aDouble != constValue2.m_value.aDouble)
601 if ( options.forceOutput() && !options.unoTypeCheck() )
603 dumpTypeClass(bDump, typeClass, keyName);
604 fprintf(stdout, " Field %d: Value1 = %f != Value2 = %f\n", index1,
605 constValue1.m_value.aDouble, constValue2.m_value.aDouble);
607 return 1;
609 break;
610 default:
611 OSL_ASSERT(false);
612 break;
614 return 0;
617 enum verbosity_t {SILENT, REPORT};
618 static sal_uInt32 checkField(Options_Impl const & options,
619 const OUString& keyName,
620 RTTypeClass typeClass,
621 bool & bDump,
622 typereg::Reader& reader1,
623 typereg::Reader& reader2,
624 sal_uInt16 index1,
625 sal_uInt16 index2,
626 verbosity_t const eVerbosity)
628 sal_uInt32 nError = 0;
629 if ( reader1.getFieldName(index1) != reader2.getFieldName(index2) )
631 if (options.forceOutput() && (REPORT == eVerbosity))
633 dumpTypeClass (bDump, typeClass, keyName);
634 fprintf(stdout, " Field %d: Name1 = %s != Name2 = %s\n", index1,
635 U2S(reader1.getFieldName(index1)), U2S(reader2.getFieldName(index2)));
637 nError++;
639 if ( reader1.getFieldTypeName(index1) != reader2.getFieldTypeName(index2) )
641 if (options.forceOutput() && (REPORT == eVerbosity))
643 dumpTypeClass (bDump, typeClass, keyName);
644 fprintf(stdout, " Field %d: Type1 = %s != Type2 = %s\n", index1,
645 U2S(reader1.getFieldTypeName(index1)), U2S(reader2.getFieldTypeName(index2)));
647 nError++;
649 else
651 RTConstValue constValue1 = reader1.getFieldValue(index1);
652 RTConstValue constValue2 = reader2.getFieldValue(index2);
653 if ( constValue1.m_type != constValue2.m_type )
655 if (options.forceOutput() && (REPORT == eVerbosity))
657 dumpTypeClass (bDump, typeClass, keyName);
658 fprintf(stdout, " Field %d: Access1 = %s != Access2 = %s\n", index1,
659 getConstValueType(constValue1), getConstValueType(constValue2));
660 fprintf(stdout, " Field %d: Value1 = ", index1);
661 printConstValue(constValue1);
662 fprintf(stdout, " != Value2 = ");
663 printConstValue(constValue1);
664 fprintf(stdout, "\n;");
666 nError++;
668 else
670 nError += checkConstValue(options, keyName, typeClass, bDump, constValue1, constValue2, index1);
674 if ( reader1.getFieldFlags(index1) != reader2.getFieldFlags(index2) )
676 if (options.forceOutput() && (REPORT == eVerbosity))
678 dumpTypeClass (bDump, typeClass, keyName);
679 fprintf(stdout, " Field %d: FieldAccess1 = %s != FieldAccess2 = %s\n", index1,
680 getFieldAccess(reader1.getFieldFlags(index1)).getStr(),
681 getFieldAccess(reader1.getFieldFlags(index2)).getStr());
683 nError++;
686 if ( options.fullCheck() && (reader1.getFieldDocumentation(index1) != reader2.getFieldDocumentation(index2)) )
688 if (options.forceOutput() && (REPORT == eVerbosity))
690 dumpTypeClass (bDump, typeClass, keyName);
691 fprintf(stdout, " Field %d: Doku1 = %s\n Doku2 = %s\n", index1,
692 U2S(reader1.getFieldDocumentation(index1)), U2S(reader2.getFieldDocumentation(index2)));
694 nError++;
696 return nError;
699 static char const * getMethodMode(RTMethodMode methodMode)
701 switch ( methodMode )
703 case RTMethodMode::ONEWAY:
704 return "ONEWAY";
705 case RTMethodMode::ONEWAY_CONST:
706 return "ONEWAY,CONST";
707 case RTMethodMode::TWOWAY:
708 return "NONE";
709 case RTMethodMode::TWOWAY_CONST:
710 return "CONST";
711 default:
712 return "INVALID";
716 static char const * getParamMode(RTParamMode paramMode)
718 switch ( paramMode )
720 case RT_PARAM_IN:
721 return "IN";
722 case RT_PARAM_OUT:
723 return "OUT";
724 case RT_PARAM_INOUT:
725 return "INOUT";
726 default:
727 return "INVALID";
731 static sal_uInt32 checkMethod(Options_Impl const & options,
732 const OUString& keyName,
733 RTTypeClass typeClass,
734 bool & bDump,
735 typereg::Reader& reader1,
736 typereg::Reader& reader2,
737 sal_uInt16 index)
739 sal_uInt32 nError = 0;
740 if ( reader1.getMethodName(index) != reader2.getMethodName(index) )
742 if ( options.forceOutput() )
744 dumpTypeClass (bDump, typeClass, keyName);
745 fprintf(stdout, " Method1 %d: Name1 = %s != Name2 = %s\n", index,
746 U2S(reader1.getMethodName(index)),
747 U2S(reader2.getMethodName(index)));
749 nError++;
752 if ( reader1.getMethodReturnTypeName(index) != reader2.getMethodReturnTypeName(index) )
754 if ( options.forceOutput() )
756 dumpTypeClass (bDump, typeClass, keyName);
757 fprintf(stdout, " Method1 %d: ReturnType1 = %s != ReturnType2 = %s\n", index,
758 U2S(reader1.getMethodReturnTypeName(index)),
759 U2S(reader2.getMethodReturnTypeName(index)));
761 nError++;
764 sal_uInt16 nParams1 = (sal_uInt16)reader1.getMethodParameterCount(index);
765 sal_uInt16 nParams2 = (sal_uInt16)reader2.getMethodParameterCount(index);
766 if ( nParams1 != nParams2 )
768 if ( options.forceOutput() )
770 dumpTypeClass (bDump, typeClass, keyName);
771 fprintf(stdout, " Method %d : nParameters1 = %d != nParameters2 = %d\n", index, nParams1, nParams2);
773 nError++;
775 sal_uInt16 i=0;
776 for (i=0; i < nParams1 && i < nParams2; i++)
778 if ( reader1.getMethodParameterTypeName(index, i) != reader2.getMethodParameterTypeName(index, i) )
780 if ( options.forceOutput() )
782 dumpTypeClass (bDump, typeClass, keyName);
783 fprintf(stdout, " Method %d, Parameter %d: Type1 = %s != Type2 = %s\n", index, i,
784 U2S(reader1.getMethodParameterTypeName(index, i)),
785 U2S(reader2.getMethodParameterTypeName(index, i)));
787 nError++;
789 if ( options.fullCheck() && (reader1.getMethodParameterName(index, i) != reader2.getMethodParameterName(index, i)) )
791 if ( options.forceOutput() )
793 dumpTypeClass (bDump, typeClass, keyName);
794 fprintf(stdout, " Method %d, Parameter %d: Name1 = %s != Name2 = %s\n", index, i,
795 U2S(reader1.getMethodParameterName(index, i)),
796 U2S(reader2.getMethodParameterName(index, i)));
798 nError++;
800 if ( reader1.getMethodParameterFlags(index, i) != reader2.getMethodParameterFlags(index, i) )
802 if ( options.forceOutput() )
804 dumpTypeClass (bDump, typeClass, keyName);
805 fprintf(stdout, " Method %d, Parameter %d: Mode1 = %s != Mode2 = %s\n", index, i,
806 getParamMode(reader1.getMethodParameterFlags(index, i)),
807 getParamMode(reader2.getMethodParameterFlags(index, i)));
809 nError++;
812 if ( i < nParams1 && options.forceOutput() )
814 dumpTypeClass (bDump, typeClass, keyName);
815 fprintf(stdout, " Registry1: Method %d contains %d more parameters\n", index, nParams1 - i);
817 if ( i < nParams2 && options.forceOutput() )
819 dumpTypeClass (bDump, typeClass, keyName);
820 fprintf(stdout, " Registry2: Method %d contains %d more parameters\n", index, nParams2 - i);
823 sal_uInt16 nExcep1 = (sal_uInt16)reader1.getMethodExceptionCount(index);
824 sal_uInt16 nExcep2 = (sal_uInt16)reader2.getMethodExceptionCount(index);
825 if ( nExcep1 != nExcep2 )
827 if ( options.forceOutput() )
829 dumpTypeClass (bDump, typeClass, keyName);
830 fprintf(stdout, " nExceptions1 = %d != nExceptions2 = %d\n", nExcep1, nExcep2);
832 nError++;
834 for (i=0; i < nExcep1 && i < nExcep2; i++)
836 if ( reader1.getMethodExceptionTypeName(index, i) != reader2.getMethodExceptionTypeName(index, i) )
838 if ( options.forceOutput() )
840 dumpTypeClass (bDump, typeClass, keyName);
841 fprintf(stdout, " Method %d, Exception %d: Name1 = %s != Name2 = %s\n", index, i,
842 U2S(reader1.getMethodExceptionTypeName(index, i)),
843 U2S(reader2.getMethodExceptionTypeName(index, i)));
845 nError++;
848 if ( i < nExcep1 && options.forceOutput() )
850 dumpTypeClass (bDump, typeClass, keyName);
851 fprintf(stdout, " Registry1: Method %d contains %d more exceptions\n", index, nExcep1 - i);
853 if ( i < nExcep2 && options.forceOutput() )
855 dumpTypeClass (bDump, typeClass, keyName);
856 fprintf(stdout, " Registry2: Method %d contains %d more exceptions\n", index, nExcep2 - i);
859 if ( reader1.getMethodFlags(index) != reader2.getMethodFlags(index) )
861 if ( options.forceOutput() )
863 dumpTypeClass (bDump, typeClass, keyName);
864 fprintf(stdout, " Method %d: Mode1 = %s != Mode2 = %s\n", index,
865 getMethodMode(reader1.getMethodFlags(index)),
866 getMethodMode(reader2.getMethodFlags(index)));
868 nError++;
871 if ( options.fullCheck() && (reader1.getMethodDocumentation(index) != reader2.getMethodDocumentation(index)) )
873 if ( options.forceOutput() )
875 dumpTypeClass (bDump, typeClass, keyName);
876 fprintf(stdout, " Method %d: Doku1 = %s\n Doku2 = %s\n", index,
877 U2S(reader1.getMethodDocumentation(index)),
878 U2S(reader2.getMethodDocumentation(index)));
880 nError++;
882 return nError;
885 static char const * getReferenceType(RTReferenceType refType)
887 switch (refType)
889 case RTReferenceType::SUPPORTS:
890 return "RTReferenceType::SUPPORTS";
891 case RTReferenceType::OBSERVES:
892 return "RTReferenceType::OBSERVES";
893 case RTReferenceType::EXPORTS:
894 return "RTReferenceType::EXPORTS";
895 case RTReferenceType::NEEDS:
896 return "RTReferenceType::NEEDS";
897 default:
898 return "RTReferenceType::INVALID";
902 static sal_uInt32 checkReference(Options_Impl const & options,
903 const OUString& keyName,
904 RTTypeClass typeClass,
905 bool & bDump,
906 typereg::Reader& reader1,
907 typereg::Reader& reader2,
908 sal_uInt16 index1,
909 sal_uInt16 index2)
911 sal_uInt32 nError = 0;
912 if ( reader1.getReferenceTypeName(index1) != reader2.getReferenceTypeName(index2) )
914 if ( options.forceOutput() && !options.unoTypeCheck() )
916 dumpTypeClass (bDump, typeClass, keyName);
917 fprintf(stdout, " Reference %d: Name1 = %s != Name2 = %s\n", index1,
918 U2S(reader1.getReferenceTypeName(index1)),
919 U2S(reader2.getReferenceTypeName(index2)));
921 nError++;
923 if ( reader1.getReferenceTypeName(index1) != reader2.getReferenceTypeName(index2) )
925 if ( options.forceOutput() && !options.unoTypeCheck() )
927 dumpTypeClass (bDump, typeClass, keyName);
928 fprintf(stdout, " Reference %d: Type1 = %s != Type2 = %s\n", index1,
929 getReferenceType(reader1.getReferenceSort(index1)),
930 getReferenceType(reader2.getReferenceSort(index2)));
932 nError++;
934 if ( options.fullCheck() && (reader1.getReferenceDocumentation(index1) != reader2.getReferenceDocumentation(index2)) )
936 if ( options.forceOutput() && !options.unoTypeCheck() )
938 dumpTypeClass (bDump, typeClass, keyName);
939 fprintf(stdout, " Reference %d: Doku1 = %s\n Doku2 = %s\n", index1,
940 U2S(reader1.getReferenceDocumentation(index1)),
941 U2S(reader2.getReferenceDocumentation(index2)));
943 nError++;
945 if ( reader1.getReferenceFlags(index1) != reader2.getReferenceFlags(index2) )
947 if ( options.forceOutput() && !options.unoTypeCheck() )
949 dumpTypeClass (bDump, typeClass, keyName);
950 fprintf(stdout, " Reference %d: Access1 = %s != Access2 = %s\n", index1,
951 getFieldAccess(reader1.getReferenceFlags(index1)).getStr(),
952 getFieldAccess(reader1.getReferenceFlags(index2)).getStr());
954 nError++;
956 return nError;
959 static sal_uInt32 checkFieldsWithoutOrder(Options_Impl const & options,
960 const OUString& keyName,
961 RTTypeClass typeClass,
962 bool & bDump,
963 typereg::Reader& reader1,
964 typereg::Reader& reader2)
966 sal_uInt32 nError = 0;
968 sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount();
969 sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount();
970 sal_uInt16 i=0, j=0;
972 if ( nFields1 > nFields2 )
974 if ( options.forceOutput() )
976 dumpTypeClass (bDump, typeClass, keyName);
977 fprintf(stdout, " %s1 contains %d more properties as %s2\n",
978 getTypeClass(typeClass), nFields1-nFields2, getTypeClass(typeClass));
982 bool bFound = false;
983 ::std::set< sal_uInt16 > moreProps;
985 for (i=0; i < nFields1; i++)
987 for (j=0; j < nFields2; j++)
989 if (!checkField(options, keyName, typeClass, bDump, reader1, reader2, i, j, SILENT))
991 bFound = true;
992 moreProps.insert(j);
993 break;
996 if (!bFound)
998 if (options.forceOutput())
1000 dumpTypeClass (bDump, typeClass, keyName);
1001 fprintf(stdout, " incompatible change: Field %d ('%s') of r1 is not longer a property of this %s in r2\n",
1002 i, U2S(shortName(reader1.getFieldName(i))), getTypeClass(typeClass));
1004 nError++;
1006 else
1008 bFound = false;
1012 if ( typeClass == RT_TYPE_SERVICE && !moreProps.empty() )
1014 for (j=0; j < nFields2; j++)
1016 if ( moreProps.find(j) == moreProps.end() )
1018 if ( (reader2.getFieldFlags(j) & RTFieldAccess::OPTIONAL) != RTFieldAccess::OPTIONAL )
1020 if ( options.forceOutput() )
1022 dumpTypeClass (bDump, typeClass, keyName);
1023 fprintf(stdout,
1024 " incompatible change: Field %d ('%s') of r2 is a new property"
1025 " compared to this %s in r1 and is not 'optional'\n",
1026 j, U2S(shortName(reader2.getFieldName(j))), getTypeClass(typeClass));
1028 nError++;
1034 return nError;
1037 static sal_uInt32 checkBlob(
1038 Options_Impl const & options,
1039 const OUString& keyName,
1040 typereg::Reader& reader1, sal_uInt32 size1,
1041 typereg::Reader& reader2, sal_uInt32 size2)
1043 sal_uInt32 nError = 0;
1044 bool bDump = true;
1046 if ( options.fullCheck() && (size1 != size2) )
1048 if ( options.forceOutput() )
1050 fprintf(
1051 stdout, " Size1 = %lu Size2 = %lu\n",
1052 sal::static_int_cast< unsigned long >(size1),
1053 sal::static_int_cast< unsigned long >(size2));
1056 if (reader1.isPublished())
1058 if (!reader2.isPublished())
1060 if (options.forceOutput())
1062 dumpTypeClass(bDump, /*"?"*/ reader1.getTypeClass(), keyName);
1063 fprintf(stdout, " published in 1 but unpublished in 2\n");
1065 ++nError;
1068 else if (!options.checkUnpublished())
1070 return nError;
1072 if ( reader1.getTypeClass() != reader2.getTypeClass() )
1074 if ( options.forceOutput() )
1076 dumpTypeClass(bDump, /*"?"*/ reader1.getTypeClass(), keyName);
1077 fprintf(stdout, " TypeClass1 = %s != TypeClass2 = %s\n",
1078 getTypeClass(reader1.getTypeClass()),
1079 getTypeClass(reader2.getTypeClass()));
1081 return ++nError;
1084 RTTypeClass typeClass = reader1.getTypeClass();
1085 if ( reader1.getTypeName() != reader2.getTypeName() )
1087 if ( options.forceOutput() )
1089 dumpTypeClass(bDump, typeClass, keyName);
1090 fprintf(stdout, " TypeName1 = %s != TypeName2 = %s\n",
1091 U2S(reader1.getTypeName()), U2S(reader2.getTypeName()));
1093 nError++;
1095 if ( (typeClass == RT_TYPE_INTERFACE ||
1096 typeClass == RT_TYPE_STRUCT ||
1097 typeClass == RT_TYPE_EXCEPTION) )
1099 if (reader1.getSuperTypeCount() != reader2.getSuperTypeCount())
1101 dumpTypeClass(bDump, typeClass, keyName);
1102 fprintf(
1103 stdout, " SuperTypeCount1 = %d != SuperTypeCount2 = %d\n",
1104 static_cast< int >(reader1.getSuperTypeCount()),
1105 static_cast< int >(reader2.getSuperTypeCount()));
1106 ++nError;
1107 } else
1109 for (sal_Int16 i = 0; i < reader1.getSuperTypeCount(); ++i)
1111 if (reader1.getSuperTypeName(i) != reader2.getSuperTypeName(i))
1113 if ( options.forceOutput() )
1115 dumpTypeClass(bDump, typeClass, keyName);
1116 fprintf(stdout, " SuperTypeName1 = %s != SuperTypeName2 = %s\n",
1117 U2S(reader1.getSuperTypeName(i)), U2S(reader2.getSuperTypeName(i)));
1119 nError++;
1125 sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount();
1126 sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount();
1127 bool bCheckNormal = true;
1129 if ( (typeClass == RT_TYPE_SERVICE ||
1130 typeClass == RT_TYPE_MODULE ||
1131 typeClass == RT_TYPE_CONSTANTS) && options.unoTypeCheck() )
1133 bCheckNormal = false;
1136 if ( bCheckNormal )
1138 if ( nFields1 != nFields2 )
1140 if ( options.forceOutput() )
1142 dumpTypeClass(bDump, typeClass, keyName);
1143 fprintf(stdout, " nFields1 = %d != nFields2 = %d\n", nFields1, nFields2);
1145 nError++;
1148 sal_uInt16 i;
1149 for (i=0; i < nFields1 && i < nFields2; i++)
1151 nError += checkField(options, keyName, typeClass, bDump, reader1, reader2, i, i, REPORT);
1153 if ( i < nFields1 && options.forceOutput() )
1155 dumpTypeClass(bDump, typeClass, keyName);
1156 fprintf(stdout, " Registry1 contains %d more fields\n", nFields1 - i);
1158 if ( i < nFields2 && options.forceOutput() )
1160 dumpTypeClass(bDump, typeClass, keyName);
1161 fprintf(stdout, " Registry2 contains %d more fields\n", nFields2 - i);
1164 else
1166 nError += checkFieldsWithoutOrder(options, keyName, typeClass, bDump, reader1, reader2);
1169 if ( typeClass == RT_TYPE_INTERFACE )
1171 sal_uInt16 nMethods1 = (sal_uInt16)reader1.getMethodCount();
1172 sal_uInt16 nMethods2 = (sal_uInt16)reader2.getMethodCount();
1173 if ( nMethods1 != nMethods2 )
1175 if ( options.forceOutput() )
1177 dumpTypeClass(bDump, typeClass, keyName);
1178 fprintf(stdout, " nMethods1 = %d != nMethods2 = %d\n", nMethods1, nMethods2);
1180 nError++;
1183 sal_uInt16 i;
1184 for (i=0; i < nMethods1 && i < nMethods2; i++)
1186 nError += checkMethod(options, keyName, typeClass, bDump, reader1, reader2, i);
1188 if ( i < nMethods1 && options.forceOutput() )
1190 fprintf(stdout, " Registry1 contains %d more methods\n", nMethods1 - i);
1192 if ( i < nMethods2 && options.forceOutput() )
1194 fprintf(stdout, " Registry2 contains %d more methods\n", nMethods2 - i);
1197 if ( typeClass == RT_TYPE_SERVICE )
1199 sal_uInt16 nReference1 = (sal_uInt16)reader1.getReferenceCount();
1200 sal_uInt16 nReference2 = (sal_uInt16)reader2.getReferenceCount();
1202 if ( !bCheckNormal )
1204 sal_uInt16 i=0, j=0;
1206 if ( nReference1 > nReference2 )
1208 if ( options.forceOutput() )
1210 dumpTypeClass(bDump, typeClass, keyName);
1211 fprintf(stdout, " service1 contains %d more references as service2\n",
1212 nReference1-nReference2);
1216 bool bFound = false;
1217 ::std::set< sal_uInt16 > moreReferences;
1219 for (i=0; i < nReference1; i++)
1221 for (j=0; j < nReference2; j++)
1223 if (!checkReference(options, keyName, typeClass, bDump, reader1, reader2, i, j))
1225 bFound = true;
1226 moreReferences.insert(j);
1227 break;
1230 if (!bFound)
1232 if (options.forceOutput())
1234 dumpTypeClass(bDump, typeClass, keyName);
1235 fprintf(stdout,
1236 " incompatible change: Reference %d ('%s') in 'r1' is not longer a reference"
1237 " of this service in 'r2'\n",
1238 i, U2S(shortName(reader1.getReferenceTypeName(i))));
1240 nError++;
1242 else
1244 bFound = false;
1248 if ( !moreReferences.empty() )
1250 for (j=0; j < nReference2; j++)
1252 if ( moreReferences.find(j) == moreReferences.end() )
1254 if ( (reader2.getReferenceFlags(j) & RTFieldAccess::OPTIONAL) != RTFieldAccess::OPTIONAL )
1256 if ( options.forceOutput() )
1258 dumpTypeClass(bDump, typeClass, keyName);
1259 fprintf(stdout,
1260 " incompatible change: Reference %d ('%s') of r2 is a new reference"
1261 " compared to this service in r1 and is not 'optional'\n",
1262 j, U2S(shortName(reader2.getReferenceTypeName(j))));
1264 nError++;
1270 else
1272 if ( nReference1 != nReference2 )
1274 if ( options.forceOutput() )
1276 dumpTypeClass(bDump, typeClass, keyName);
1277 fprintf(stdout, " nReferences1 = %d != nReferences2 = %d\n", nReference1, nReference2);
1279 nError++;
1282 sal_uInt16 i;
1283 for (i=0; i < nReference1 && i < nReference2; i++)
1285 nError += checkReference(options, keyName, typeClass, bDump, reader1, reader2, i, i);
1287 if ( i < nReference1 && options.forceOutput() )
1289 fprintf(stdout, " Registry1 contains %d more references\n", nReference1 - i);
1291 if ( i < nReference2 && options.forceOutput() )
1293 fprintf(stdout, " Registry2 contains %d more references\n", nReference2 - i);
1298 if ( options.fullCheck() && (reader1.getDocumentation() != reader2.getDocumentation()) )
1300 if ( options.forceOutput() )
1302 dumpTypeClass(bDump, typeClass, keyName);
1303 fprintf(stdout, " Doku1 = %s\n Doku2 = %s\n",
1304 U2S(reader1.getDocumentation()), U2S(reader2.getDocumentation()));
1306 nError++;
1308 return nError;
1311 static sal_uInt32 checkValueDifference(
1312 Options_Impl const & options,
1313 RegistryKey& key1, RegValueType valueType1, sal_uInt32 size1,
1314 RegistryKey& key2, RegValueType valueType2, sal_uInt32 size2)
1316 OUString tmpName;
1317 sal_uInt32 nError = 0;
1319 if ( valueType1 == valueType2 )
1321 bool bEqual = true;
1322 switch (valueType1)
1324 case RegValueType::LONGLIST:
1326 RegistryValueList<sal_Int32> valueList1;
1327 RegistryValueList<sal_Int32> valueList2;
1328 key1.getLongListValue(tmpName, valueList1);
1329 key2.getLongListValue(tmpName, valueList2);
1330 sal_uInt32 length1 = valueList1.getLength();
1331 sal_uInt32 length2 = valueList1.getLength();
1332 if ( length1 != length2 )
1334 bEqual = false;
1335 break;
1337 for (sal_uInt32 i=0; i<length1; i++)
1339 if ( valueList1.getElement(i) != valueList2.getElement(i) )
1341 bEqual = false;
1342 break;
1346 break;
1347 case RegValueType::STRINGLIST:
1349 RegistryValueList<sal_Char*> valueList1;
1350 RegistryValueList<sal_Char*> valueList2;
1351 key1.getStringListValue(tmpName, valueList1);
1352 key2.getStringListValue(tmpName, valueList2);
1353 sal_uInt32 length1 = valueList1.getLength();
1354 sal_uInt32 length2 = valueList1.getLength();
1355 if ( length1 != length2 )
1357 bEqual = false;
1358 break;
1360 for (sal_uInt32 i=0; i<length1; i++)
1362 if ( strcmp(valueList1.getElement(i), valueList2.getElement(i)) != 0 )
1364 bEqual = false;
1365 break;
1369 break;
1370 case RegValueType::UNICODELIST:
1372 RegistryValueList<sal_Unicode*> valueList1;
1373 RegistryValueList<sal_Unicode*> valueList2;
1374 key1.getUnicodeListValue(tmpName, valueList1);
1375 key2.getUnicodeListValue(tmpName, valueList2);
1376 sal_uInt32 length1 = valueList1.getLength();
1377 sal_uInt32 length2 = valueList1.getLength();
1378 if ( length1 != length2 )
1380 bEqual = false;
1381 break;
1383 for (sal_uInt32 i=0; i<length1; i++)
1385 if ( rtl_ustr_compare(valueList1.getElement(i), valueList2.getElement(i)) != 0 )
1387 bEqual = false;
1388 break;
1392 break;
1393 default:
1394 break;
1397 if ( bEqual)
1399 std::vector< sal_uInt8 > value1(size1);
1400 key1.getValue(tmpName, &value1[0]);
1402 std::vector< sal_uInt8 > value2(size2);
1403 key2.getValue(tmpName, &value2[0]);
1405 bEqual = (memcmp(&value1[0], &value2[0], value1.size()) == 0 );
1406 if ( !bEqual && valueType1 == RegValueType::BINARY && valueType2 == RegValueType::BINARY )
1408 typereg::Reader reader1(&value1[0], value1.size(), false, TYPEREG_VERSION_1);
1409 typereg::Reader reader2(&value2[0], value2.size(), false, TYPEREG_VERSION_1);
1410 if ( reader1.isValid() && reader2.isValid() )
1412 return checkBlob(options, key1.getName(), reader1, size1, reader2, size2);
1415 if ( bEqual )
1417 return 0;
1419 else
1421 if ( options.forceOutput() )
1423 fprintf(stdout, "Difference: key values of key \"%s\" are different\n", U2S(key1.getName()));
1425 nError++;
1430 if ( options.forceOutput() )
1432 switch (valueType1)
1434 case RegValueType::NOT_DEFINED:
1435 fprintf(stdout, " Registry 1: key has no value\n");
1436 break;
1437 case RegValueType::LONG:
1439 std::vector< sal_uInt8 > value1(size1);
1440 key1.getValue(tmpName, &value1[0]);
1442 fprintf(stdout, " Registry 1: Value: Type = RegValueType::LONG\n");
1443 fprintf(
1444 stdout, " Size = %lu\n",
1445 sal::static_int_cast< unsigned long >(size1));
1446 fprintf(stdout, " Data = %p\n", &value1[0]);
1448 break;
1449 case RegValueType::STRING:
1451 std::vector< sal_uInt8 > value1(size1);
1452 key1.getValue(tmpName, &value1[0]);
1454 fprintf(stdout, " Registry 1: Value: Type = RegValueType::STRING\n");
1455 fprintf(
1456 stdout, " Size = %lu\n",
1457 sal::static_int_cast< unsigned long >(size1));
1458 fprintf(stdout, " Data = \"%s\"\n", reinterpret_cast<char const*>(&value1[0]));
1460 break;
1461 case RegValueType::UNICODE:
1463 std::vector< sal_uInt8 > value1(size1);
1464 key1.getValue(tmpName, &value1[0]);
1466 OUString uStrValue(reinterpret_cast<sal_Unicode const*>(&value1[0]));
1467 fprintf(stdout, " Registry 1: Value: Type = RegValueType::UNICODE\n");
1468 fprintf(
1469 stdout, " Size = %lu\n",
1470 sal::static_int_cast< unsigned long >(size1));
1471 fprintf(stdout, " Data = \"%s\"\n", U2S(uStrValue));
1473 break;
1474 case RegValueType::BINARY:
1475 fprintf(stdout, " Registry 1: Value: Type = RegValueType::BINARY\n");
1476 break;
1477 case RegValueType::LONGLIST:
1479 RegistryValueList<sal_Int32> valueList;
1480 key1.getLongListValue(tmpName, valueList);
1481 fprintf(stdout, " Registry 1: Value: Type = RegValueType::LONGLIST\n");
1482 fprintf(
1483 stdout, " Size = %lu\n",
1484 sal::static_int_cast< unsigned long >(size1));
1485 sal_uInt32 length = valueList.getLength();
1486 for (sal_uInt32 i=0; i<length; i++)
1488 fprintf(
1489 stdout, " Data[%lu] = %ld\n",
1490 sal::static_int_cast< unsigned long >(i),
1491 sal::static_int_cast< long >(valueList.getElement(i)));
1494 break;
1495 case RegValueType::STRINGLIST:
1497 RegistryValueList<sal_Char*> valueList;
1498 key1.getStringListValue(tmpName, valueList);
1499 fprintf(stdout, " Registry 1: Value: Type = RegValueType::STRINGLIST\n");
1500 fprintf(
1501 stdout, " Size = %lu\n",
1502 sal::static_int_cast< unsigned long >(size1));
1503 sal_uInt32 length = valueList.getLength();
1504 for (sal_uInt32 i=0; i<length; i++)
1506 fprintf(
1507 stdout, " Data[%lu] = \"%s\"\n",
1508 sal::static_int_cast< unsigned long >(i),
1509 valueList.getElement(i));
1512 break;
1513 case RegValueType::UNICODELIST:
1515 RegistryValueList<sal_Unicode*> valueList;
1516 key1.getUnicodeListValue(tmpName, valueList);
1517 fprintf(stdout, " Registry 1: Value: Type = RegValueType::UNICODELIST\n");
1518 fprintf(
1519 stdout, " Size = %lu\n",
1520 sal::static_int_cast< unsigned long >(size1));
1521 sal_uInt32 length = valueList.getLength();
1522 OUString uStrValue;
1523 for (sal_uInt32 i=0; i<length; i++)
1525 uStrValue = OUString(valueList.getElement(i));
1526 fprintf(
1527 stdout, " Data[%lu] = \"%s\"\n",
1528 sal::static_int_cast< unsigned long >(i), U2S(uStrValue));
1531 break;
1534 switch (valueType2)
1536 case RegValueType::NOT_DEFINED:
1537 fprintf(stdout, " Registry 2: key has no value\n");
1538 break;
1539 case RegValueType::LONG:
1541 std::vector< sal_uInt8 > value2(size2);
1542 key2.getValue(tmpName, &value2[0]);
1544 fprintf(stdout, " Registry 2: Value: Type = RegValueType::LONG\n");
1545 fprintf(
1546 stdout, " Size = %lu\n",
1547 sal::static_int_cast< unsigned long >(size2));
1548 fprintf(stdout, " Data = %p\n", &value2[0]);
1550 break;
1551 case RegValueType::STRING:
1553 std::vector< sal_uInt8 > value2(size2);
1554 key2.getValue(tmpName, &value2[0]);
1556 fprintf(stdout, " Registry 2: Value: Type = RegValueType::STRING\n");
1557 fprintf(
1558 stdout, " Size = %lu\n",
1559 sal::static_int_cast< unsigned long >(size2));
1560 fprintf(stdout, " Data = \"%s\"\n", reinterpret_cast<char const*>(&value2[0]));
1562 break;
1563 case RegValueType::UNICODE:
1565 std::vector< sal_uInt8 > value2(size2);
1566 key2.getValue(tmpName, &value2[0]);
1568 OUString uStrValue(reinterpret_cast<sal_Unicode const*>(&value2[0]));
1569 fprintf(stdout, " Registry 2: Value: Type = RegValueType::UNICODE\n");
1570 fprintf(
1571 stdout, " Size = %lu\n",
1572 sal::static_int_cast< unsigned long >(size2));
1573 fprintf(stdout, " Data = \"%s\"\n", U2S(uStrValue));
1575 break;
1576 case RegValueType::BINARY:
1577 fprintf(stdout, " Registry 2: Value: Type = RegValueType::BINARY\n");
1578 break;
1579 case RegValueType::LONGLIST:
1581 RegistryValueList<sal_Int32> valueList;
1582 key2.getLongListValue(tmpName, valueList);
1583 fprintf(stdout, " Registry 2: Value: Type = RegValueType::LONGLIST\n");
1584 fprintf(
1585 stdout, " Size = %lu\n",
1586 sal::static_int_cast< unsigned long >(size2));
1587 sal_uInt32 length = valueList.getLength();
1588 for (sal_uInt32 i=0; i<length; i++)
1590 fprintf(
1591 stdout, " Data[%lu] = %ld\n",
1592 sal::static_int_cast< unsigned long >(i),
1593 sal::static_int_cast< long >(valueList.getElement(i)));
1596 break;
1597 case RegValueType::STRINGLIST:
1599 RegistryValueList<sal_Char*> valueList;
1600 key2.getStringListValue(tmpName, valueList);
1601 fprintf(stdout, " Registry 2: Value: Type = RegValueType::STRINGLIST\n");
1602 fprintf(
1603 stdout, " Size = %lu\n",
1604 sal::static_int_cast< unsigned long >(size2));
1605 sal_uInt32 length = valueList.getLength();
1606 for (sal_uInt32 i=0; i<length; i++)
1608 fprintf(
1609 stdout, " Data[%lu] = \"%s\"\n",
1610 sal::static_int_cast< unsigned long >(i),
1611 valueList.getElement(i));
1614 break;
1615 case RegValueType::UNICODELIST:
1617 RegistryValueList<sal_Unicode*> valueList;
1618 key2.getUnicodeListValue(tmpName, valueList);
1619 fprintf(stdout, " Registry 2: Value: Type = RegValueType::UNICODELIST\n");
1620 fprintf(
1621 stdout, " Size = %lu\n",
1622 sal::static_int_cast< unsigned long >(size2));
1623 sal_uInt32 length = valueList.getLength();
1624 OUString uStrValue;
1625 for (sal_uInt32 i=0; i<length; i++)
1627 uStrValue = OUString(valueList.getElement(i));
1628 fprintf(
1629 stdout, " Data[%lu] = \"%s\"\n",
1630 sal::static_int_cast< unsigned long >(i), U2S(uStrValue));
1633 break;
1636 return nError;
1639 static bool hasPublishedChildren(Options_Impl const & options, RegistryKey & key)
1641 RegistryKeyNames subKeyNames;
1642 key.getKeyNames(OUString(), subKeyNames);
1643 for (sal_uInt32 i = 0; i < subKeyNames.getLength(); ++i)
1645 OUString keyName(subKeyNames.getElement(i));
1646 if (!options.matchedWithExcludeKey(keyName))
1648 keyName = keyName.copy(keyName.lastIndexOf('/') + 1);
1649 RegistryKey subKey;
1650 if (key.openKey(keyName, subKey) == RegError::NO_ERROR)
1652 if (options.forceOutput())
1654 fprintf(
1655 stdout,
1656 ("WARNING: could not open key \"%s\" in registry"
1657 " \"%s\"\n"),
1658 U2S(subKeyNames.getElement(i)),
1659 options.getRegName1().c_str());
1662 if (subKey.isValid())
1664 RegValueType type;
1665 sal_uInt32 size;
1666 if (subKey.getValueInfo(OUString(), &type, &size) != RegError::NO_ERROR)
1668 if (options.forceOutput())
1670 fprintf(
1671 stdout,
1672 ("WARNING: could not read key \"%s\" in registry"
1673 " \"%s\"\n"),
1674 U2S(subKeyNames.getElement(i)),
1675 options.getRegName1().c_str());
1678 else if (type == RegValueType::BINARY)
1680 bool published = false;
1681 std::vector< sal_uInt8 > value(size);
1682 if (subKey.getValue(OUString(), &value[0]) != RegError::NO_ERROR)
1684 if (options.forceOutput())
1686 fprintf(
1687 stdout,
1688 ("WARNING: could not read key \"%s\" in"
1689 " registry \"%s\"\n"),
1690 U2S(subKeyNames.getElement(i)),
1691 options.getRegName1().c_str());
1694 else
1696 published = typereg::Reader(&value[0], value.size(), false, TYPEREG_VERSION_1).isPublished();
1698 if (published)
1700 return true;
1706 return false;
1709 static sal_uInt32 checkDifferences(
1710 Options_Impl const & options,
1711 RegistryKey& key, StringSet& keys,
1712 RegistryKeyNames& subKeyNames1,
1713 RegistryKeyNames& subKeyNames2)
1715 sal_uInt32 nError = 0;
1716 sal_uInt32 length1 = subKeyNames1.getLength();
1717 sal_uInt32 length2 = subKeyNames2.getLength();
1718 sal_uInt32 i,j;
1720 for (i=0; i<length1; i++)
1722 bool bFound = false;
1723 for (j=0; j<length2; j++)
1725 if ( subKeyNames1.getElement(i) == subKeyNames2.getElement(j) )
1727 bFound = true;
1728 keys.insert(subKeyNames1.getElement(i));
1729 break;
1732 if ( !bFound )
1734 if ( options.fullCheck() )
1736 if ( options.forceOutput() )
1738 fprintf(stdout, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n",
1739 U2S(subKeyNames1.getElement(i)), options.getRegName1().c_str());
1741 nError++;
1743 else
1745 OUString keyName(subKeyNames1.getElement(i));
1746 if (!options.matchedWithExcludeKey(keyName))
1748 keyName = keyName.copy(keyName.lastIndexOf('/') + 1);
1749 RegistryKey subKey;
1750 if (key.openKey(keyName, subKey) != RegError::NO_ERROR)
1752 if (options.forceOutput())
1754 fprintf(
1755 stdout,
1756 ("ERROR: could not open key \"%s\" in registry"
1757 " \"%s\"\n"),
1758 U2S(subKeyNames1.getElement(i)),
1759 options.getRegName1().c_str());
1761 ++nError;
1763 if (subKey.isValid())
1765 RegValueType type;
1766 sal_uInt32 size;
1767 if (subKey.getValueInfo(OUString(), &type, &size) != RegError::NO_ERROR)
1769 if (options.forceOutput())
1771 fprintf(
1772 stdout,
1773 ("ERROR: could not read key \"%s\" in"
1774 " registry \"%s\"\n"),
1775 U2S(subKeyNames1.getElement(i)),
1776 options.getRegName1().c_str());
1778 ++nError;
1780 else if (type == RegValueType::BINARY)
1782 std::vector< sal_uInt8 > value(size);
1783 if (subKey.getValue(OUString(), &value[0]) != RegError::NO_ERROR)
1785 if (options.forceOutput())
1787 fprintf(
1788 stdout,
1789 ("ERROR: could not read key \"%s\" in"
1790 " registry \"%s\"\n"),
1791 U2S(subKeyNames1.getElement(i)),
1792 options.getRegName1().c_str());
1794 ++nError;
1796 else
1798 typereg::Reader reader(&value[0], value.size(), false, TYPEREG_VERSION_1);
1799 if (reader.getTypeClass() == RT_TYPE_MODULE)
1801 if (options.checkUnpublished() || hasPublishedChildren(options, subKey))
1803 if (options.forceOutput())
1805 fprintf(
1806 stdout,
1807 ("EXISTENCE: module \"%s\""
1808 " %sexists only in registry"
1809 " 1\n"),
1810 U2S(subKeyNames1.getElement(i)),
1811 (options.checkUnpublished()
1812 ? ""
1813 : "with published children "));
1815 ++nError;
1818 else if (options.checkUnpublished() || reader.isPublished())
1820 if (options.forceOutput())
1822 fprintf(
1823 stdout,
1824 ("EXISTENCE: %spublished key \"%s\""
1825 " exists only in registry 1\n"),
1826 reader.isPublished() ? "" : "un",
1827 U2S(subKeyNames1.getElement(i)));
1829 ++nError;
1839 for (i=0; i<length2; i++)
1841 bool bFound = false;
1842 for (j=0; j<length1; j++)
1844 if ( subKeyNames2.getElement(i) == subKeyNames1.getElement(j) )
1846 bFound = true;
1847 keys.insert(subKeyNames2.getElement(i));
1848 break;
1851 if ( !bFound && options.fullCheck() )
1853 if ( options.forceOutput() )
1855 fprintf(stdout, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n",
1856 U2S(subKeyNames2.getElement(i)), options.getRegName2().c_str());
1858 nError++;
1861 return nError;
1864 static sal_uInt32 compareKeys(
1865 Options_Impl const & options,
1866 RegistryKey& key1,
1867 RegistryKey& key2)
1869 sal_uInt32 nError = 0;
1871 RegValueType valueType1 = RegValueType::NOT_DEFINED;
1872 RegValueType valueType2 = RegValueType::NOT_DEFINED;
1873 sal_uInt32 size1 = 0;
1874 sal_uInt32 size2 = 0;
1876 OUString tmpName;
1877 RegError e1 = key1.getValueInfo(tmpName, &valueType1, &size1);
1878 RegError e2 = key2.getValueInfo(tmpName, &valueType2, &size2);
1879 if ( (e1 == e2) && (e1 != RegError::VALUE_NOT_EXISTS) && (e1 != RegError::INVALID_VALUE) )
1881 nError += checkValueDifference(options, key1, valueType1, size1, key2, valueType2, size2);
1883 else
1885 if ( (e1 != RegError::INVALID_VALUE) || (e2 != RegError::INVALID_VALUE) )
1887 if ( options.forceOutput() )
1889 fprintf(stdout, "VALUES: key values of key \"%s\" are different\n", U2S(key1.getName()));
1891 nError++;
1895 RegistryKeyNames subKeyNames1;
1896 RegistryKeyNames subKeyNames2;
1898 key1.getKeyNames(tmpName, subKeyNames1);
1899 key2.getKeyNames(tmpName, subKeyNames2);
1901 StringSet keys;
1902 nError += checkDifferences(options, key1, keys, subKeyNames1, subKeyNames2);
1904 StringSet::iterator iter = keys.begin();
1905 StringSet::iterator end = keys.end();
1907 while ( iter != end )
1909 OUString keyName(*iter);
1910 if ( options.matchedWithExcludeKey(keyName) )
1912 ++iter;
1913 continue;
1916 sal_Int32 nPos = keyName.lastIndexOf( '/' );
1917 keyName = keyName.copy( nPos != -1 ? nPos+1 : 0 );
1919 RegistryKey subKey1;
1920 if ( key1.openKey(keyName, subKey1) != RegError::NO_ERROR )
1922 if ( options.forceOutput() )
1924 fprintf(stdout, "ERROR: could not open key \"%s\" in registry \"%s\"\n",
1925 U2S(*iter), options.getRegName1().c_str());
1927 nError++;
1930 RegistryKey subKey2;
1931 if ( key2.openKey(keyName, subKey2) != RegError::NO_ERROR )
1933 if ( options.forceOutput() )
1935 fprintf(stdout, "ERROR: could not open key \"%s\" in registry \"%s\"\n",
1936 U2S(*iter), options.getRegName2().c_str());
1938 nError++;
1941 if ( subKey1.isValid() && subKey2.isValid() )
1943 nError += compareKeys(options, subKey1, subKey2);
1945 ++iter;
1948 return nError;
1951 #if (defined UNX) || defined __MINGW32__
1952 int main( int argc, char * argv[] )
1953 #else
1954 int _cdecl main( int argc, char * argv[] )
1955 #endif
1957 std::vector< std::string > args;
1959 Options_Impl options(argv[0]);
1960 for (int i = 1; i < argc; i++)
1962 if (!Options::checkArgument(args, argv[i], strlen(argv[i])))
1964 // failure.
1965 options.printUsage();
1966 return 1;
1969 if (!options.initOptions(args))
1971 return 1;
1974 OUString regName1( convertToFileUrl(options.getRegName1().c_str(), options.getRegName1().size()) );
1975 OUString regName2( convertToFileUrl(options.getRegName2().c_str(), options.getRegName2().size()) );
1977 Registry reg1, reg2;
1978 if ( reg1.open(regName1, RegAccessMode::READONLY) != RegError::NO_ERROR )
1980 fprintf(stdout, "%s: open registry \"%s\" failed\n",
1981 options.getProgramName().c_str(), options.getRegName1().c_str());
1982 return 2;
1984 if ( reg2.open(regName2, RegAccessMode::READONLY) != RegError::NO_ERROR )
1986 fprintf(stdout, "%s: open registry \"%s\" failed\n",
1987 options.getProgramName().c_str(), options.getRegName2().c_str());
1988 return 3;
1991 RegistryKey key1, key2;
1992 if ( reg1.openRootKey(key1) != RegError::NO_ERROR )
1994 fprintf(stdout, "%s: open root key of registry \"%s\" failed\n",
1995 options.getProgramName().c_str(), options.getRegName1().c_str());
1996 return 4;
1998 if ( reg2.openRootKey(key2) != RegError::NO_ERROR )
2000 fprintf(stdout, "%s: open root key of registry \"%s\" failed\n",
2001 options.getProgramName().c_str(), options.getRegName2().c_str());
2002 return 5;
2005 if ( options.isStartKeyValid() )
2007 if ( options.matchedWithExcludeKey( options.getStartKey() ) )
2009 fprintf(stdout, "%s: start key is equal to one of the exclude keys\n",
2010 options.getProgramName().c_str());
2011 return 6;
2013 RegistryKey sk1, sk2;
2014 if ( key1.openKey(options.getStartKey(), sk1) != RegError::NO_ERROR )
2016 fprintf(stdout, "%s: open start key of registry \"%s\" failed\n",
2017 options.getProgramName().c_str(), options.getRegName1().c_str());
2018 return 7;
2020 if ( key2.openKey(options.getStartKey(), sk2) != RegError::NO_ERROR )
2022 fprintf(stdout, "%s: open start key of registry \"%s\" failed\n",
2023 options.getProgramName().c_str(), options.getRegName2().c_str());
2024 return 8;
2027 key1 = sk1;
2028 key2 = sk2;
2031 sal_uInt32 nError = compareKeys(options, key1, key2);
2032 if ( nError )
2034 if ( options.unoTypeCheck() )
2036 fprintf(stdout, "%s: registries are incompatible: %lu differences!\n",
2037 options.getProgramName().c_str(),
2038 sal::static_int_cast< unsigned long >(nError));
2040 else
2042 fprintf(stdout, "%s: registries contain %lu differences!\n",
2043 options.getProgramName().c_str(),
2044 sal::static_int_cast< unsigned long >(nError));
2048 key1.releaseKey();
2049 key2.releaseKey();
2050 if ( reg1.close() != RegError::NO_ERROR )
2052 fprintf(stdout, "%s: closing registry \"%s\" failed\n",
2053 options.getProgramName().c_str(), options.getRegName1().c_str());
2054 return 9;
2056 if ( reg2.close() != RegError::NO_ERROR )
2058 fprintf(stdout, "%s: closing registry \"%s\" failed\n",
2059 options.getProgramName().c_str(), options.getRegName2().c_str());
2060 return 10;
2063 return ((nError > 0) ? 11 : 0);
2066 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */