1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
37 using namespace registry::tools
;
39 typedef std::set
< OUString
> StringSet
;
41 class Options_Impl
: public Options
44 explicit Options_Impl(char const * program
)
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
; }
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
;
73 StringSet m_excludeKeys
;
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');
103 void Options_Impl::printUsage_Impl() const
105 std::string
const & rProgName
= getProgramName();
107 "Usage: %s -r1<filename> -r2<filename> [-options] | @<filename>\n", rProgName
.c_str()
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"
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"
132 "\n%s Version 1.0\n\n", rProgName
.c_str()
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());
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());
169 param
= std::string(&(option
[1]), option
.size() - 1);
171 if (!setRegName_Impl(option
[0], param
))
173 return badOption("invalid", option
.c_str());
180 if (!((++first
!= last
) && ((*first
)[0] != '-')))
182 return badOption("invalid", (*first
).c_str());
184 m_startKey
= makeOUString(*first
);
190 if (!((++first
!= last
) && ((*first
)[0] != '-')))
192 return badOption("invalid", (*first
).c_str());
194 m_excludeKeys
.insert(makeOUString(*first
));
200 if ((*first
).size() > 2)
202 return badOption("invalid", (*first
).c_str());
204 m_bForceOutput
= true;
210 if ((*first
).size() > 2)
212 return badOption("invalid", (*first
).c_str());
220 if ((*first
).size() > 2)
222 return badOption("invalid", (*first
).c_str());
224 m_bUnoTypeCheck
= true;
230 if ((*first
).size() > 2)
232 return badOption("invalid", (*first
).c_str());
234 m_checkUnpublished
= true;
240 if ((*first
).size() > 2)
242 return badOption("invalid", (*first
).c_str());
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");
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
))
278 static char const * getTypeClass(RTTypeClass typeClass
)
282 case RT_TYPE_INTERFACE
:
290 case RT_TYPE_EXCEPTION
:
292 case RT_TYPE_TYPEDEF
:
294 case RT_TYPE_SERVICE
:
298 case RT_TYPE_CONSTANTS
:
305 static OString
getFieldAccess(RTFieldAccess fieldAccess
)
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");
367 static char const * getConstValueType(RTConstValue
& constValue
)
369 switch (constValue
.m_type
)
383 // case RT_TYPE_INT64:
384 // return "sal_Int64";
385 // case RT_TYPE_UINT64:
386 // return "sal_uInt64";
392 return "sal_Unicode*";
398 static void printConstValue(RTConstValue
& constValue
)
400 switch (constValue
.m_type
)
403 fprintf(stdout
, "none");
406 fprintf(stdout
, "%s", constValue
.m_value
.aBool
? "TRUE" : "FALSE");
409 fprintf(stdout
, "%d", constValue
.m_value
.aByte
);
412 fprintf(stdout
, "%d", constValue
.m_value
.aShort
);
415 fprintf(stdout
, "%d", constValue
.m_value
.aUShort
);
420 sal::static_int_cast
< long >(constValue
.m_value
.aLong
));
425 sal::static_int_cast
< unsigned long >(
426 constValue
.m_value
.aULong
));
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);
433 fprintf(stdout
, "%f", constValue
.m_value
.aFloat
);
436 fprintf(stdout
, "%f", constValue
.m_value
.aDouble
);
442 constValue
.m_value
.aString
, RTL_TEXTENCODING_UTF8
).
450 static void dumpTypeClass(bool & rbDump
, RTTypeClass typeClass
, OUString
const & keyName
)
453 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
457 static sal_uInt32
checkConstValue(Options_Impl
const & options
,
458 const OUString
& keyName
,
459 RTTypeClass typeClass
,
461 RTConstValue
& constValue1
,
462 RTConstValue
& constValue2
,
465 switch (constValue1
.m_type
)
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");
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
);
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
);
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
);
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
));
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
));
545 if (constValue1
.m_value
.aHyper
!= constValue2
.m_value
.aHyper
)
547 if ( options
.forceOutput() && !options
.unoTypeCheck() )
549 dumpTypeClass(bDump
, typeClass
, keyName
);
551 stdout
, " Field %d: Value1 = %s != Value2 = %s\n",
554 OUString::number(constValue1
.m_value
.aHyper
),
555 RTL_TEXTENCODING_ASCII_US
).getStr(),
557 OUString::number(constValue2
.m_value
.aHyper
),
558 RTL_TEXTENCODING_ASCII_US
).getStr());
564 if (constValue1
.m_value
.aUHyper
!= constValue2
.m_value
.aUHyper
)
566 if ( options
.forceOutput() && !options
.unoTypeCheck() )
568 dumpTypeClass(bDump
, typeClass
, keyName
);
570 stdout
, " Field %d: Value1 = %s != Value2 = %s\n",
574 constValue1
.m_value
.aUHyper
),
575 RTL_TEXTENCODING_ASCII_US
).getStr(),
578 constValue2
.m_value
.aUHyper
),
579 RTL_TEXTENCODING_ASCII_US
).getStr());
580 // printing the unsigned values as signed should be
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
);
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
);
617 enum verbosity_t
{SILENT
, REPORT
};
618 static sal_uInt32
checkField(Options_Impl
const & options
,
619 const OUString
& keyName
,
620 RTTypeClass typeClass
,
622 typereg::Reader
& reader1
,
623 typereg::Reader
& reader2
,
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
)));
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
)));
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;");
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());
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
)));
699 static char const * getMethodMode(RTMethodMode methodMode
)
701 switch ( methodMode
)
703 case RTMethodMode::ONEWAY
:
705 case RTMethodMode::ONEWAY_CONST
:
706 return "ONEWAY,CONST";
707 case RTMethodMode::TWOWAY
:
709 case RTMethodMode::TWOWAY_CONST
:
716 static char const * getParamMode(RTParamMode paramMode
)
731 static sal_uInt32
checkMethod(Options_Impl
const & options
,
732 const OUString
& keyName
,
733 RTTypeClass typeClass
,
735 typereg::Reader
& reader1
,
736 typereg::Reader
& reader2
,
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
)));
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
)));
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
);
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
)));
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
)));
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
)));
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
);
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
)));
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
)));
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
)));
885 static char const * getReferenceType(RTReferenceType 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";
898 return "RTReferenceType::INVALID";
902 static sal_uInt32
checkReference(Options_Impl
const & options
,
903 const OUString
& keyName
,
904 RTTypeClass typeClass
,
906 typereg::Reader
& reader1
,
907 typereg::Reader
& reader2
,
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
)));
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
)));
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
)));
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());
959 static sal_uInt32
checkFieldsWithoutOrder(Options_Impl
const & options
,
960 const OUString
& keyName
,
961 RTTypeClass typeClass
,
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();
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
));
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
))
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
));
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
);
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
));
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;
1046 if ( options
.fullCheck() && (size1
!= size2
) )
1048 if ( options
.forceOutput() )
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");
1068 else if (!options
.checkUnpublished())
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()));
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()));
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
);
1103 stdout
, " SuperTypeCount1 = %d != SuperTypeCount2 = %d\n",
1104 static_cast< int >(reader1
.getSuperTypeCount()),
1105 static_cast< int >(reader2
.getSuperTypeCount()));
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
)));
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;
1138 if ( nFields1
!= nFields2
)
1140 if ( options
.forceOutput() )
1142 dumpTypeClass(bDump
, typeClass
, keyName
);
1143 fprintf(stdout
, " nFields1 = %d != nFields2 = %d\n", nFields1
, nFields2
);
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
);
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
);
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
))
1226 moreReferences
.insert(j
);
1232 if (options
.forceOutput())
1234 dumpTypeClass(bDump
, typeClass
, keyName
);
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
))));
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
);
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
))));
1272 if ( nReference1
!= nReference2
)
1274 if ( options
.forceOutput() )
1276 dumpTypeClass(bDump
, typeClass
, keyName
);
1277 fprintf(stdout
, " nReferences1 = %d != nReferences2 = %d\n", nReference1
, nReference2
);
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()));
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
)
1317 sal_uInt32 nError
= 0;
1319 if ( valueType1
== valueType2
)
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
)
1337 for (sal_uInt32 i
=0; i
<length1
; i
++)
1339 if ( valueList1
.getElement(i
) != valueList2
.getElement(i
) )
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
)
1360 for (sal_uInt32 i
=0; i
<length1
; i
++)
1362 if ( strcmp(valueList1
.getElement(i
), valueList2
.getElement(i
)) != 0 )
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
)
1383 for (sal_uInt32 i
=0; i
<length1
; i
++)
1385 if ( rtl_ustr_compare(valueList1
.getElement(i
), valueList2
.getElement(i
)) != 0 )
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
);
1421 if ( options
.forceOutput() )
1423 fprintf(stdout
, "Difference: key values of key \"%s\" are different\n", U2S(key1
.getName()));
1430 if ( options
.forceOutput() )
1434 case RegValueType::NOT_DEFINED
:
1435 fprintf(stdout
, " Registry 1: key has no value\n");
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");
1444 stdout
, " Size = %lu\n",
1445 sal::static_int_cast
< unsigned long >(size1
));
1446 fprintf(stdout
, " Data = %p\n", &value1
[0]);
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");
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]));
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");
1469 stdout
, " Size = %lu\n",
1470 sal::static_int_cast
< unsigned long >(size1
));
1471 fprintf(stdout
, " Data = \"%s\"\n", U2S(uStrValue
));
1474 case RegValueType::BINARY
:
1475 fprintf(stdout
, " Registry 1: Value: Type = RegValueType::BINARY\n");
1477 case RegValueType::LONGLIST
:
1479 RegistryValueList
<sal_Int32
> valueList
;
1480 key1
.getLongListValue(tmpName
, valueList
);
1481 fprintf(stdout
, " Registry 1: Value: Type = RegValueType::LONGLIST\n");
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
++)
1489 stdout
, " Data[%lu] = %ld\n",
1490 sal::static_int_cast
< unsigned long >(i
),
1491 sal::static_int_cast
< long >(valueList
.getElement(i
)));
1495 case RegValueType::STRINGLIST
:
1497 RegistryValueList
<sal_Char
*> valueList
;
1498 key1
.getStringListValue(tmpName
, valueList
);
1499 fprintf(stdout
, " Registry 1: Value: Type = RegValueType::STRINGLIST\n");
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
++)
1507 stdout
, " Data[%lu] = \"%s\"\n",
1508 sal::static_int_cast
< unsigned long >(i
),
1509 valueList
.getElement(i
));
1513 case RegValueType::UNICODELIST
:
1515 RegistryValueList
<sal_Unicode
*> valueList
;
1516 key1
.getUnicodeListValue(tmpName
, valueList
);
1517 fprintf(stdout
, " Registry 1: Value: Type = RegValueType::UNICODELIST\n");
1519 stdout
, " Size = %lu\n",
1520 sal::static_int_cast
< unsigned long >(size1
));
1521 sal_uInt32 length
= valueList
.getLength();
1523 for (sal_uInt32 i
=0; i
<length
; i
++)
1525 uStrValue
= OUString(valueList
.getElement(i
));
1527 stdout
, " Data[%lu] = \"%s\"\n",
1528 sal::static_int_cast
< unsigned long >(i
), U2S(uStrValue
));
1536 case RegValueType::NOT_DEFINED
:
1537 fprintf(stdout
, " Registry 2: key has no value\n");
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");
1546 stdout
, " Size = %lu\n",
1547 sal::static_int_cast
< unsigned long >(size2
));
1548 fprintf(stdout
, " Data = %p\n", &value2
[0]);
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");
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]));
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");
1571 stdout
, " Size = %lu\n",
1572 sal::static_int_cast
< unsigned long >(size2
));
1573 fprintf(stdout
, " Data = \"%s\"\n", U2S(uStrValue
));
1576 case RegValueType::BINARY
:
1577 fprintf(stdout
, " Registry 2: Value: Type = RegValueType::BINARY\n");
1579 case RegValueType::LONGLIST
:
1581 RegistryValueList
<sal_Int32
> valueList
;
1582 key2
.getLongListValue(tmpName
, valueList
);
1583 fprintf(stdout
, " Registry 2: Value: Type = RegValueType::LONGLIST\n");
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
++)
1591 stdout
, " Data[%lu] = %ld\n",
1592 sal::static_int_cast
< unsigned long >(i
),
1593 sal::static_int_cast
< long >(valueList
.getElement(i
)));
1597 case RegValueType::STRINGLIST
:
1599 RegistryValueList
<sal_Char
*> valueList
;
1600 key2
.getStringListValue(tmpName
, valueList
);
1601 fprintf(stdout
, " Registry 2: Value: Type = RegValueType::STRINGLIST\n");
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
++)
1609 stdout
, " Data[%lu] = \"%s\"\n",
1610 sal::static_int_cast
< unsigned long >(i
),
1611 valueList
.getElement(i
));
1615 case RegValueType::UNICODELIST
:
1617 RegistryValueList
<sal_Unicode
*> valueList
;
1618 key2
.getUnicodeListValue(tmpName
, valueList
);
1619 fprintf(stdout
, " Registry 2: Value: Type = RegValueType::UNICODELIST\n");
1621 stdout
, " Size = %lu\n",
1622 sal::static_int_cast
< unsigned long >(size2
));
1623 sal_uInt32 length
= valueList
.getLength();
1625 for (sal_uInt32 i
=0; i
<length
; i
++)
1627 uStrValue
= OUString(valueList
.getElement(i
));
1629 stdout
, " Data[%lu] = \"%s\"\n",
1630 sal::static_int_cast
< unsigned long >(i
), U2S(uStrValue
));
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);
1650 if (key
.openKey(keyName
, subKey
) == RegError::NO_ERROR
)
1652 if (options
.forceOutput())
1656 ("WARNING: could not open key \"%s\" in registry"
1658 U2S(subKeyNames
.getElement(i
)),
1659 options
.getRegName1().c_str());
1662 if (subKey
.isValid())
1666 if (subKey
.getValueInfo(OUString(), &type
, &size
) != RegError::NO_ERROR
)
1668 if (options
.forceOutput())
1672 ("WARNING: could not read key \"%s\" in registry"
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())
1688 ("WARNING: could not read key \"%s\" in"
1689 " registry \"%s\"\n"),
1690 U2S(subKeyNames
.getElement(i
)),
1691 options
.getRegName1().c_str());
1696 published
= typereg::Reader(&value
[0], value
.size(), false, TYPEREG_VERSION_1
).isPublished();
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();
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
) )
1728 keys
.insert(subKeyNames1
.getElement(i
));
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());
1745 OUString
keyName(subKeyNames1
.getElement(i
));
1746 if (!options
.matchedWithExcludeKey(keyName
))
1748 keyName
= keyName
.copy(keyName
.lastIndexOf('/') + 1);
1750 if (key
.openKey(keyName
, subKey
) != RegError::NO_ERROR
)
1752 if (options
.forceOutput())
1756 ("ERROR: could not open key \"%s\" in registry"
1758 U2S(subKeyNames1
.getElement(i
)),
1759 options
.getRegName1().c_str());
1763 if (subKey
.isValid())
1767 if (subKey
.getValueInfo(OUString(), &type
, &size
) != RegError::NO_ERROR
)
1769 if (options
.forceOutput())
1773 ("ERROR: could not read key \"%s\" in"
1774 " registry \"%s\"\n"),
1775 U2S(subKeyNames1
.getElement(i
)),
1776 options
.getRegName1().c_str());
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())
1789 ("ERROR: could not read key \"%s\" in"
1790 " registry \"%s\"\n"),
1791 U2S(subKeyNames1
.getElement(i
)),
1792 options
.getRegName1().c_str());
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())
1807 ("EXISTENCE: module \"%s\""
1808 " %sexists only in registry"
1810 U2S(subKeyNames1
.getElement(i
)),
1811 (options
.checkUnpublished()
1813 : "with published children "));
1818 else if (options
.checkUnpublished() || reader
.isPublished())
1820 if (options
.forceOutput())
1824 ("EXISTENCE: %spublished key \"%s\""
1825 " exists only in registry 1\n"),
1826 reader
.isPublished() ? "" : "un",
1827 U2S(subKeyNames1
.getElement(i
)));
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
) )
1847 keys
.insert(subKeyNames2
.getElement(i
));
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());
1864 static sal_uInt32
compareKeys(
1865 Options_Impl
const & options
,
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;
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
);
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()));
1895 RegistryKeyNames subKeyNames1
;
1896 RegistryKeyNames subKeyNames2
;
1898 key1
.getKeyNames(tmpName
, subKeyNames1
);
1899 key2
.getKeyNames(tmpName
, subKeyNames2
);
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
) )
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());
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());
1941 if ( subKey1
.isValid() && subKey2
.isValid() )
1943 nError
+= compareKeys(options
, subKey1
, subKey2
);
1951 #if (defined UNX) || defined __MINGW32__
1952 int main( int argc
, char * argv
[] )
1954 int _cdecl
main( int argc
, char * argv
[] )
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
])))
1965 options
.printUsage();
1969 if (!options
.initOptions(args
))
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());
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());
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());
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());
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());
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());
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());
2031 sal_uInt32 nError
= compareKeys(options
, key1
, key2
);
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
));
2042 fprintf(stdout
, "%s: registries contain %lu differences!\n",
2043 options
.getProgramName().c_str(),
2044 sal::static_int_cast
< unsigned long >(nError
));
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());
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());
2063 return ((nError
> 0) ? 11 : 0);
2066 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */