diff --git a/.uncrustify.cfg b/.uncrustify.cfg new file mode 100644 index 000000000..074811b05 --- /dev/null +++ b/.uncrustify.cfg @@ -0,0 +1,3128 @@ +# Uncrustify-0.72.0_f + +# +# General options +# + +# The type of line endings. +# +# Default: auto +newlines = auto # lf/crlf/cr/auto + +# The original size of tabs in the input. +# +# Default: 8 +input_tab_size = 4 # unsigned number + +# The size of tabs in the output (only used if align_with_tabs=true). +# +# Default: 8 +output_tab_size = 4 # unsigned number + +# The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). +# +# Default: 92 +string_escape_char = 92 # unsigned number + +# Alternate string escape char (usually only used for Pawn). +# Only works right before the quote char. +string_escape_char2 = 0 # unsigned number + +# Replace tab characters found in string literals with the escape sequence \t +# instead. +string_replace_tab_chars = false # true/false + +# Allow interpreting '>=' and '>>=' as part of a template in code like +# 'void f(list>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. +# Improvements to template detection may make this option obsolete. +tok_split_gte = false # true/false + +# Disable formatting of NL_CONT ('\\n') ended lines (e.g. multiline macros) +disable_processing_nl_cont = false # true/false + +# Specify the marker used in comments to disable processing of part of the +# file. +# The comment should be used alone in one line. +# +# Default: *INDENT-OFF* +disable_processing_cmt = " *INDENT-OFF*" # string + +# Specify the marker used in comments to (re)enable processing in a file. +# The comment should be used alone in one line. +# +# Default: *INDENT-ON* +enable_processing_cmt = " *INDENT-ON*" # string + +# Enable parsing of digraphs. +enable_digraphs = false # true/false + +# Add or remove the UTF-8 BOM (recommend 'remove'). +utf8_bom = ignore # ignore/add/remove/force + +# If the file contains bytes with values between 128 and 255, but is not +# UTF-8, then output as UTF-8. +utf8_byte = false # true/false + +# Force the output encoding to UTF-8. +utf8_force = false # true/false + +# Add or remove space between 'do' and '{'. +sp_do_brace_open = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'while'. +sp_brace_close_while = ignore # ignore/add/remove/force + +# Add or remove space between 'while' and '('. +sp_while_paren_open = add # ignore/add/remove/force + +# +# Spacing options +# + +# Add or remove space around non-assignment symbolic operators ('+', '/', '%', +# '<<', and so forth). +sp_arith = ignore # ignore/add/remove/force + +# Add or remove space around arithmetic operators '+' and '-'. +# +# Overrides sp_arith. +sp_arith_additive = ignore # ignore/add/remove/force + +# Add or remove space around assignment operator '=', '+=', etc. +sp_assign = ignore # ignore/add/remove/force + +# Add or remove space around '=' in C++11 lambda capture specifications. +# +# Overrides sp_assign. +sp_cpp_lambda_assign = ignore # ignore/add/remove/force + +# Add or remove space after the capture specification of a C++11 lambda when +# an argument list is present, as in '[] (int x){ ... }'. +sp_cpp_lambda_square_paren = ignore # ignore/add/remove/force + +# Add or remove space after the capture specification of a C++11 lambda with +# no argument list is present, as in '[] { ... }'. +sp_cpp_lambda_square_brace = ignore # ignore/add/remove/force + +# Add or remove space after the argument list of a C++11 lambda, as in +# '[](int x) { ... }'. +sp_cpp_lambda_paren_brace = ignore # ignore/add/remove/force + +# Add or remove space between a lambda body and its call operator of an +# immediately invoked lambda, as in '[]( ... ){ ... } ( ... )'. +sp_cpp_lambda_fparen = ignore # ignore/add/remove/force + +# Add or remove space around assignment operator '=' in a prototype. +# +# If set to ignore, use sp_assign. +sp_assign_default = ignore # ignore/add/remove/force + +# Add or remove space before assignment operator '=', '+=', etc. +# +# Overrides sp_assign. +sp_before_assign = ignore # ignore/add/remove/force + +# Add or remove space after assignment operator '=', '+=', etc. +# +# Overrides sp_assign. +sp_after_assign = ignore # ignore/add/remove/force + +# Add or remove space in 'NS_ENUM ('. +sp_enum_paren = ignore # ignore/add/remove/force + +# Add or remove space around assignment '=' in enum. +sp_enum_assign = ignore # ignore/add/remove/force + +# Add or remove space before assignment '=' in enum. +# +# Overrides sp_enum_assign. +sp_enum_before_assign = ignore # ignore/add/remove/force + +# Add or remove space after assignment '=' in enum. +# +# Overrides sp_enum_assign. +sp_enum_after_assign = ignore # ignore/add/remove/force + +# Add or remove space around assignment ':' in enum. +sp_enum_colon = ignore # ignore/add/remove/force + +# Add or remove space around preprocessor '##' concatenation operator. +# +# Default: add +sp_pp_concat = add # ignore/add/remove/force + +# Add or remove space after preprocessor '#' stringify operator. +# Also affects the '#@' charizing operator. +sp_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space before preprocessor '#' stringify operator +# as in '#define x(y) L#y'. +sp_before_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space around boolean operators '&&' and '||'. +sp_bool = force # ignore/add/remove/force + +# Add or remove space around compare operator '<', '>', '==', etc. +sp_compare = ignore # ignore/add/remove/force + +# Add or remove space inside '(' and ')'. +sp_inside_paren = remove # ignore/add/remove/force + +# Add or remove space between nested parentheses, i.e. '((' vs. ') )'. +sp_paren_paren = remove # ignore/add/remove/force + +# Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. +sp_cparen_oparen = ignore # ignore/add/remove/force + +# Whether to balance spaces inside nested parentheses. +sp_balance_nested_parens = false # true/false + +# Add or remove space between ')' and '{'. +sp_paren_brace = force # ignore/add/remove/force + +# Add or remove space between nested braces, i.e. '{{' vs '{ {'. +sp_brace_brace = ignore # ignore/add/remove/force + +# Add or remove space before pointer star '*'. +sp_before_ptr_star = ignore # ignore/add/remove/force + +# Add or remove space before pointer star '*' that isn't followed by a +# variable name. If set to ignore, sp_before_ptr_star is used instead. +sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force + +# Add or remove space between pointer stars '*'. +sp_between_ptr_star = remove # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a word. +# +# Overrides sp_type_func. +sp_after_ptr_star = ignore # ignore/add/remove/force + +# Add or remove space after pointer caret '^', if followed by a word. +sp_after_ptr_block_caret = ignore # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a qualifier. +sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by a function +# prototype or function definition. +# +# Overrides sp_after_ptr_star and sp_type_func. +sp_after_ptr_star_func = ignore # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by an open +# parenthesis, as in 'void* (*)(). +sp_ptr_star_paren = ignore # ignore/add/remove/force + +# Add or remove space before a pointer star '*', if followed by a function +# prototype or function definition. +sp_before_ptr_star_func = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&'. +sp_before_byref = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&' that isn't followed by a +# variable name. If set to ignore, sp_before_byref is used instead. +sp_before_unnamed_byref = ignore # ignore/add/remove/force + +# Add or remove space after reference sign '&', if followed by a word. +# +# Overrides sp_type_func. +sp_after_byref = ignore # ignore/add/remove/force + +# Add or remove space after a reference sign '&', if followed by a function +# prototype or function definition. +# +# Overrides sp_after_byref and sp_type_func. +sp_after_byref_func = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&', if followed by a function +# prototype or function definition. +sp_before_byref_func = ignore # ignore/add/remove/force + +# Add or remove space between type and word. In cases where total removal of +# whitespace would be a syntax error, a value of 'remove' is treated the same +# as 'force'. +# +# This also affects some other instances of space following a type that are +# not covered by other options; for example, between the return type and +# parenthesis of a function type template argument, between the type and +# parenthesis of an array parameter, or between 'decltype(...)' and the +# following word. +# +# Default: force +sp_after_type = force # ignore/add/remove/force + +# Add or remove space between 'decltype(...)' and word. +# +# Overrides sp_after_type. +sp_after_decltype = ignore # ignore/add/remove/force + +# (D) Add or remove space before the parenthesis in the D constructs +# 'template Foo(' and 'class Foo('. +sp_before_template_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'template' and '<'. +# If set to ignore, sp_before_angle is used. +sp_template_angle = ignore # ignore/add/remove/force + +# Add or remove space before '<'. +sp_before_angle = remove # ignore/add/remove/force + +# Add or remove space inside '<' and '>'. +sp_inside_angle = remove # ignore/add/remove/force + +# Add or remove space inside '<>'. +sp_inside_angle_empty = ignore # ignore/add/remove/force + +# Add or remove space between '>' and ':'. +sp_angle_colon = ignore # ignore/add/remove/force + +# Add or remove space after '>'. +sp_after_angle = add # ignore/add/remove/force + +# Add or remove space between '>' and '(' as found in 'new List(foo);'. +sp_angle_paren = remove # ignore/add/remove/force + +# Add or remove space between '>' and '()' as found in 'new List();'. +sp_angle_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between '>' and a word as in 'List m;' or +# 'template static ...'. +sp_angle_word = add # ignore/add/remove/force + +# Add or remove space between '>' and '>' in '>>' (template stuff). +# +# Default: add +sp_angle_shift = ignore # ignore/add/remove/force + +# (C++11) Permit removal of the space between '>>' in 'foo >'. Note +# that sp_angle_shift cannot remove the space without this option. +sp_permit_cpp11_shift = true # true/false + +# Add or remove space before '(' of control statements ('if', 'for', 'switch', +# 'while', etc.). +sp_before_sparen = force # ignore/add/remove/force + +# Add or remove space inside '(' and ')' of control statements. +sp_inside_sparen = remove # ignore/add/remove/force + +# Add or remove space after '(' of control statements. +# +# Overrides sp_inside_sparen. +sp_inside_sparen_open = ignore # ignore/add/remove/force + +# Add or remove space before ')' of control statements. +# +# Overrides sp_inside_sparen. +sp_inside_sparen_close = ignore # ignore/add/remove/force + +# Add or remove space after ')' of control statements. +sp_after_sparen = force # ignore/add/remove/force + +# Add or remove space between ')' and '{' of of control statements. +sp_sparen_brace = force # ignore/add/remove/force + +# (D) Add or remove space between 'invariant' and '('. +sp_invariant_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space after the ')' in 'invariant (C) c'. +sp_after_invariant_paren = ignore # ignore/add/remove/force + +# Add or remove space before empty statement ';' on 'if', 'for' and 'while'. +sp_special_semi = ignore # ignore/add/remove/force + +# Add or remove space before ';'. +# +# Default: remove +sp_before_semi = remove # ignore/add/remove/force + +# Add or remove space before ';' in non-empty 'for' statements. +sp_before_semi_for = remove # ignore/add/remove/force + +# Add or remove space before a semicolon of an empty part of a for statement. +sp_before_semi_for_empty = ignore # ignore/add/remove/force + +# Add or remove space after ';', except when followed by a comment. +# +# Default: add +sp_after_semi = add # ignore/add/remove/force + +# Add or remove space after ';' in non-empty 'for' statements. +# +# Default: force +sp_after_semi_for = force # ignore/add/remove/force + +# Add or remove space after the final semicolon of an empty part of a for +# statement, as in 'for ( ; ; )'. +sp_after_semi_for_empty = remove # ignore/add/remove/force + +# Add or remove space before '[' (except '[]'). +sp_before_square = ignore # ignore/add/remove/force + +# Add or remove space before '[' for a variable definition. +# +# Default: remove +sp_before_vardef_square = remove # ignore/add/remove/force + +# Add or remove space before '[' for asm block. +sp_before_square_asm_block = ignore # ignore/add/remove/force + +# Add or remove space before '[]'. +sp_before_squares = remove # ignore/add/remove/force + +# Add or remove space before C++17 structured bindings. +sp_cpp_before_struct_binding = ignore # ignore/add/remove/force + +# Add or remove space inside a non-empty '[' and ']'. +sp_inside_square = remove # ignore/add/remove/force + +# Add or remove space inside '[]'. +sp_inside_square_empty = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and +# ']'. If set to ignore, sp_inside_square is used. +sp_inside_square_oc_array = ignore # ignore/add/remove/force + +# Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. +sp_after_comma = ignore # ignore/add/remove/force + +# Add or remove space before ','. +# +# Default: remove +sp_before_comma = remove # ignore/add/remove/force + +# (C#) Add or remove space between ',' and ']' in multidimensional array type +# like 'int[,,]'. +sp_after_mdatype_commas = ignore # ignore/add/remove/force + +# (C#) Add or remove space between '[' and ',' in multidimensional array type +# like 'int[,,]'. +sp_before_mdatype_commas = ignore # ignore/add/remove/force + +# (C#) Add or remove space between ',' in multidimensional array type +# like 'int[,,]'. +sp_between_mdatype_commas = ignore # ignore/add/remove/force + +# Add or remove space between an open parenthesis and comma, +# i.e. '(,' vs. '( ,'. +# +# Default: force +sp_paren_comma = force # ignore/add/remove/force + +# Add or remove space before the variadic '...' when preceded by a +# non-punctuator. +sp_before_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space between a type and '...'. +sp_type_ellipsis = ignore # ignore/add/remove/force + +# (D) Add or remove space between a type and '?'. +sp_type_question = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '...'. +sp_paren_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space between ')' and a qualifier such as 'const'. +sp_paren_qualifier = ignore # ignore/add/remove/force + +# Add or remove space between ')' and 'noexcept'. +sp_paren_noexcept = ignore # ignore/add/remove/force + +# Add or remove space after class ':'. +sp_after_class_colon = force # ignore/add/remove/force + +# Add or remove space before class ':'. +sp_before_class_colon = force # ignore/add/remove/force + +# Add or remove space after class constructor ':'. +sp_after_constr_colon = ignore # ignore/add/remove/force + +# Add or remove space before class constructor ':'. +sp_before_constr_colon = ignore # ignore/add/remove/force + +# Add or remove space before case ':'. +# +# Default: remove +sp_before_case_colon = remove # ignore/add/remove/force + +# Add or remove space between 'operator' and operator sign. +sp_after_operator = ignore # ignore/add/remove/force + +# Add or remove space between the operator symbol and the open parenthesis, as +# in 'operator ++('. +sp_after_operator_sym = ignore # ignore/add/remove/force + +# Overrides sp_after_operator_sym when the operator has no arguments, as in +# 'operator *()'. +sp_after_operator_sym_empty = ignore # ignore/add/remove/force + +# Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or +# '(int)a' vs. '(int) a'. +sp_after_cast = ignore # ignore/add/remove/force + +# Add or remove spaces inside cast parentheses. +sp_inside_paren_cast = ignore # ignore/add/remove/force + +# Add or remove space between the type and open parenthesis in a C++ cast, +# i.e. 'int(exp)' vs. 'int (exp)'. +sp_cpp_cast_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '('. +sp_sizeof_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '...'. +sp_sizeof_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space between 'sizeof...' and '('. +sp_sizeof_ellipsis_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'decltype' and '('. +sp_decltype_paren = ignore # ignore/add/remove/force + +# (Pawn) Add or remove space after the tag keyword. +sp_after_tag = ignore # ignore/add/remove/force + +# Add or remove space inside enum '{' and '}'. +sp_inside_braces_enum = ignore # ignore/add/remove/force + +# Add or remove space inside struct/union '{' and '}'. +sp_inside_braces_struct = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}' +sp_inside_braces_oc_dict = ignore # ignore/add/remove/force + +# Add or remove space after open brace in an unnamed temporary +# direct-list-initialization. +sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force + +# Add or remove space before close brace in an unnamed temporary +# direct-list-initialization. +sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force + +# Add or remove space inside an unnamed temporary direct-list-initialization. +sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force + +# Add or remove space inside '{' and '}'. +sp_inside_braces = ignore # ignore/add/remove/force + +# Add or remove space inside '{}'. +sp_inside_braces_empty = remove # ignore/add/remove/force + +# Add or remove space around trailing return operator '->'. +sp_trailing_return = ignore # ignore/add/remove/force + +# Add or remove space between return type and function name. A minimum of 1 +# is forced except for pointer return types. +sp_type_func = ignore # ignore/add/remove/force + +# Add or remove space between type and open brace of an unnamed temporary +# direct-list-initialization. +sp_type_brace_init_lst = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' on function declaration. +sp_func_proto_paren = ignore # ignore/add/remove/force + +# Add or remove space between function name and '()' on function declaration +# without parameters. +sp_func_proto_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' with a typedef specifier. +sp_func_type_paren = ignore # ignore/add/remove/force + +# Add or remove space between alias name and '(' of a non-pointer function type typedef. +sp_func_def_paren = ignore # ignore/add/remove/force + +# Add or remove space between function name and '()' on function definition +# without parameters. +sp_func_def_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space inside empty function '()'. +# Overrides sp_after_angle unless use_sp_after_angle_always is set to true. +sp_inside_fparens = ignore # ignore/add/remove/force + +# Add or remove space inside function '(' and ')'. +sp_inside_fparen = ignore # ignore/add/remove/force + +# Add or remove space inside the first parentheses in a function type, as in +# 'void (*x)(...)'. +sp_inside_tparen = ignore # ignore/add/remove/force + +# Add or remove space between the ')' and '(' in a function type, as in +# 'void (*x)(...)'. +sp_after_tparen_close = ignore # ignore/add/remove/force + +# Add or remove space between ']' and '(' when part of a function call. +sp_square_fparen = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '{' of function. +sp_fparen_brace = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '{' of a function call in object +# initialization. +# +# Overrides sp_fparen_brace. +sp_fparen_brace_initializer = ignore # ignore/add/remove/force + +# (Java) Add or remove space between ')' and '{{' of double brace initializer. +sp_fparen_dbrace = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' on function calls. +sp_func_call_paren = ignore # ignore/add/remove/force + +# Add or remove space between function name and '()' on function calls without +# parameters. If set to ignore (the default), sp_func_call_paren is used. +sp_func_call_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between the user function name and '(' on function +# calls. You need to set a keyword to be a user function in the config file, +# like: +# set func_call_user tr _ i18n +sp_func_call_user_paren = ignore # ignore/add/remove/force + +# Add or remove space inside user function '(' and ')'. +sp_func_call_user_inside_fparen = ignore # ignore/add/remove/force + +# Add or remove space between nested parentheses with user functions, +# i.e. '((' vs. '( ('. +sp_func_call_user_paren_paren = ignore # ignore/add/remove/force + +# Add or remove space between a constructor/destructor and the open +# parenthesis. +sp_func_class_paren = ignore # ignore/add/remove/force + +# Add or remove space between a constructor without parameters or destructor +# and '()'. +sp_func_class_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between 'return' and '('. +sp_return_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'return' and '{'. +sp_return_brace = ignore # ignore/add/remove/force + +# Add or remove space between '__attribute__' and '('. +sp_attribute_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'defined' and '(' in '#if defined (FOO)'. +sp_defined_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'throw' and '(' in 'throw (something)'. +sp_throw_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'throw' and anything other than '(' as in +# '@throw [...];'. +sp_after_throw = ignore # ignore/add/remove/force + +# Add or remove space between 'catch' and '(' in 'catch (something) { }'. +# If set to ignore, sp_before_sparen is used. +sp_catch_paren = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@catch' and '(' +# in '@catch (something) { }'. If set to ignore, sp_catch_paren is used. +sp_oc_catch_paren = ignore # ignore/add/remove/force + +# (OC) Add or remove space before Objective-C protocol list +# as in '@protocol Protocol' or '@interface MyClass : NSObject'. +sp_before_oc_proto_list = ignore # ignore/add/remove/force + +# (OC) Add or remove space between class name and '(' +# in '@interface className(categoryName):BaseClass' +sp_oc_classname_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'version' and '(' +# in 'version (something) { }'. If set to ignore, sp_before_sparen is used. +sp_version_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'scope' and '(' +# in 'scope (something) { }'. If set to ignore, sp_before_sparen is used. +sp_scope_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'super' and '(' in 'super (something)'. +# +# Default: remove +sp_super_paren = remove # ignore/add/remove/force + +# Add or remove space between 'this' and '(' in 'this (something)'. +# +# Default: remove +sp_this_paren = remove # ignore/add/remove/force + +# Add or remove space between a macro name and its definition. +sp_macro = ignore # ignore/add/remove/force + +# Add or remove space between a macro function ')' and its definition. +sp_macro_func = ignore # ignore/add/remove/force + +# Add or remove space between 'else' and '{' if on the same line. +sp_else_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'else' if on the same line. +sp_brace_else = force # ignore/add/remove/force + +# Add or remove space between '}' and the name of a typedef on the same line. +sp_brace_typedef = ignore # ignore/add/remove/force + +# Add or remove space before the '{' of a 'catch' statement, if the '{' and +# 'catch' are on the same line, as in 'catch (decl) {'. +sp_catch_brace = force # ignore/add/remove/force + +# (OC) Add or remove space before the '{' of a '@catch' statement, if the '{' +# and '@catch' are on the same line, as in '@catch (decl) {'. +# If set to ignore, sp_catch_brace is used. +sp_oc_catch_brace = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'catch' if on the same line. +sp_brace_catch = force # ignore/add/remove/force + +# (OC) Add or remove space between '}' and '@catch' if on the same line. +# If set to ignore, sp_brace_catch is used. +sp_oc_brace_catch = ignore # ignore/add/remove/force + +# Add or remove space between 'finally' and '{' if on the same line. +sp_finally_brace = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'finally' if on the same line. +sp_brace_finally = ignore # ignore/add/remove/force + +# Add or remove space between 'try' and '{' if on the same line. +sp_try_brace = ignore # ignore/add/remove/force + +# Add or remove space between get/set and '{' if on the same line. +sp_getset_brace = ignore # ignore/add/remove/force + +# Add or remove space between a variable and '{' for C++ uniform +# initialization. +sp_word_brace_init_lst = ignore # ignore/add/remove/force + +# Add or remove space between a variable and '{' for a namespace. +# +# Default: add +sp_word_brace_ns = add # ignore/add/remove/force + +# Add or remove space before the '::' operator. +sp_before_dc = ignore # ignore/add/remove/force + +# Add or remove space after the '::' operator. +sp_after_dc = ignore # ignore/add/remove/force + +# (D) Add or remove around the D named array initializer ':' operator. +sp_d_array_colon = ignore # ignore/add/remove/force + +# Add or remove space after the '!' (not) unary operator. +# +# Default: remove +sp_not = remove # ignore/add/remove/force + +# Add or remove space after the '~' (invert) unary operator. +# +# Default: remove +sp_inv = remove # ignore/add/remove/force + +# Add or remove space after the '&' (address-of) unary operator. This does not +# affect the spacing after a '&' that is part of a type. +# +# Default: remove +sp_addr = remove # ignore/add/remove/force + +# Add or remove space around the '.' or '->' operators. +# +# Default: remove +sp_member = remove # ignore/add/remove/force + +# Add or remove space after the '*' (dereference) unary operator. This does +# not affect the spacing after a '*' that is part of a type. +# +# Default: remove +sp_deref = remove # ignore/add/remove/force + +# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. +# +# Default: remove +sp_sign = remove # ignore/add/remove/force + +# Add or remove space between '++' and '--' the word to which it is being +# applied, as in '(--x)' or 'y++;'. +# +# Default: remove +sp_incdec = remove # ignore/add/remove/force + +# Add or remove space before a backslash-newline at the end of a line. +# +# Default: add +sp_before_nl_cont = add # ignore/add/remove/force + +# (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;' +# or '+(int) bar;'. +sp_after_oc_scope = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in message specs, +# i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'. +sp_after_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in message specs, +# i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'. +sp_before_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};'. +sp_after_oc_dict_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};'. +sp_before_oc_dict_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in message specs, +# i.e. '[object setValue:1];' vs. '[object setValue: 1];'. +sp_after_send_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in message specs, +# i.e. '[object setValue:1];' vs. '[object setValue :1];'. +sp_before_send_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the (type) in message specs, +# i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'. +sp_after_oc_type = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the first (type) in message specs, +# i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'. +sp_after_oc_return_type = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@selector' and '(', +# i.e. '@selector(msgName)' vs. '@selector (msgName)'. +# Also applies to '@protocol()' constructs. +sp_after_oc_at_sel = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@selector(x)' and the following word, +# i.e. '@selector(foo) a:' vs. '@selector(foo)a:'. +sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside '@selector' parentheses, +# i.e. '@selector(foo)' vs. '@selector( foo )'. +# Also applies to '@protocol()' constructs. +sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force + +# (OC) Add or remove space before a block pointer caret, +# i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'. +sp_before_oc_block_caret = ignore # ignore/add/remove/force + +# (OC) Add or remove space after a block pointer caret, +# i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'. +sp_after_oc_block_caret = ignore # ignore/add/remove/force + +# (OC) Add or remove space between the receiver and selector in a message, +# as in '[receiver selector ...]'. +sp_after_oc_msg_receiver = ignore # ignore/add/remove/force + +# (OC) Add or remove space after '@property'. +sp_after_oc_property = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@synchronized' and the open parenthesis, +# i.e. '@synchronized(foo)' vs. '@synchronized (foo)'. +sp_after_oc_synchronized = ignore # ignore/add/remove/force + +# Add or remove space around the ':' in 'b ? t : f'. +sp_cond_colon = ignore # ignore/add/remove/force + +# Add or remove space before the ':' in 'b ? t : f'. +# +# Overrides sp_cond_colon. +sp_cond_colon_before = ignore # ignore/add/remove/force + +# Add or remove space after the ':' in 'b ? t : f'. +# +# Overrides sp_cond_colon. +sp_cond_colon_after = ignore # ignore/add/remove/force + +# Add or remove space around the '?' in 'b ? t : f'. +sp_cond_question = ignore # ignore/add/remove/force + +# Add or remove space before the '?' in 'b ? t : f'. +# +# Overrides sp_cond_question. +sp_cond_question_before = ignore # ignore/add/remove/force + +# Add or remove space after the '?' in 'b ? t : f'. +# +# Overrides sp_cond_question. +sp_cond_question_after = ignore # ignore/add/remove/force + +# In the abbreviated ternary form '(a ?: b)', add or remove space between '?' +# and ':'. +# +# Overrides all other sp_cond_* options. +sp_cond_ternary_short = ignore # ignore/add/remove/force + +# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make +# sense here. +sp_case_label = ignore # ignore/add/remove/force + +# (D) Add or remove space around the D '..' operator. +sp_range = ignore # ignore/add/remove/force + +# Add or remove space after ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_after_for_colon = ignore # ignore/add/remove/force + +# Add or remove space before ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_before_for_colon = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'extern' and '(' as in 'extern (C)'. +sp_extern_paren = ignore # ignore/add/remove/force + +# Add or remove space after the opening of a C++ comment, +# i.e. '// A' vs. '//A'. +sp_cmt_cpp_start = ignore # ignore/add/remove/force + +# If true, space is added with sp_cmt_cpp_start will be added after doxygen +# sequences like '///', '///<', '//!' and '//!<'. +sp_cmt_cpp_doxygen = false # true/false + +# If true, space is added with sp_cmt_cpp_start will be added after Qt +# translator or meta-data comments like '//:', '//=', and '//~'. +sp_cmt_cpp_qttr = false # true/false + +# Add or remove space between #else or #endif and a trailing comment. +sp_endif_cmt = ignore # ignore/add/remove/force + +# Add or remove space after 'new', 'delete' and 'delete[]'. +sp_after_new = ignore # ignore/add/remove/force + +# Add or remove space between 'new' and '(' in 'new()'. +sp_between_new_paren = ignore # ignore/add/remove/force + +# Add or remove space between ')' and type in 'new(foo) BAR'. +sp_after_newop_paren = ignore # ignore/add/remove/force + +# Add or remove space inside parenthesis of the new operator +# as in 'new(foo) BAR'. +sp_inside_newop_paren = ignore # ignore/add/remove/force + +# Add or remove space after the open parenthesis of the new operator, +# as in 'new(foo) BAR'. +# +# Overrides sp_inside_newop_paren. +sp_inside_newop_paren_open = ignore # ignore/add/remove/force + +# Add or remove space before the close parenthesis of the new operator, +# as in 'new(foo) BAR'. +# +# Overrides sp_inside_newop_paren. +sp_inside_newop_paren_close = ignore # ignore/add/remove/force + +# Add or remove space before a trailing or embedded comment. +sp_before_tr_emb_cmt = ignore # ignore/add/remove/force + +# Number of spaces before a trailing or embedded comment. +sp_num_before_tr_emb_cmt = 0 # unsigned number + +# (Java) Add or remove space between an annotation and the open parenthesis. +sp_annotation_paren = ignore # ignore/add/remove/force + +# If true, vbrace tokens are dropped to the previous token and skipped. +sp_skip_vbrace_tokens = false # true/false + +# Add or remove space after 'noexcept'. +sp_after_noexcept = ignore # ignore/add/remove/force + +# Add or remove space after '_'. +sp_vala_after_translation = ignore # ignore/add/remove/force + +# If true, a is inserted after #define. +force_tab_after_define = false # true/false + +# +# Indenting options +# + +# The number of columns to indent per level. Usually 2, 3, 4, or 8. +# +# Default: 8 +indent_columns = 4 # unsigned number + +# The continuation indent. If non-zero, this overrides the indent of '(', '[' +# and '=' continuation indents. Negative values are OK; negative value is +# absolute and not increased for each '(' or '[' level. +# +# For FreeBSD, this is set to 4. +indent_continue = 0 # number + +# The continuation indent, only for class header line(s). If non-zero, this +# overrides the indent of 'class' continuation indents. +indent_continue_class_head = 0 # unsigned number + +# Whether to indent empty lines (i.e. lines which contain only spaces before +# the newline character). +indent_single_newlines = false # true/false + +# The continuation indent for func_*_param if they are true. If non-zero, this +# overrides the indent. +indent_param = 0 # unsigned number + +# How to use tabs when indenting code. +# +# 0: Spaces only +# 1: Indent with tabs to brace level, align with spaces (default) +# 2: Indent and align with tabs, using spaces when not on a tabstop +# +# Default: 1 +indent_with_tabs = 0 # unsigned number + +# Whether to indent comments that are not at a brace level with tabs on a +# tabstop. Requires indent_with_tabs=2. If false, will use spaces. +indent_cmt_with_tabs = false # true/false + +# Whether to indent strings broken by '\' so that they line up. +indent_align_string = false # true/false + +# The number of spaces to indent multi-line XML strings. +# Requires indent_align_string=true. +indent_xml_string = 0 # unsigned number + +# Spaces to indent '{' from level. +indent_brace = 0 # unsigned number + +# Whether braces are indented to the body level. +indent_braces = false # true/false + +# Whether to disable indenting function braces if indent_braces=true. +indent_braces_no_func = false # true/false + +# Whether to disable indenting class braces if indent_braces=true. +indent_braces_no_class = false # true/false + +# Whether to disable indenting struct braces if indent_braces=true. +indent_braces_no_struct = false # true/false + +# Whether to indent based on the size of the brace parent, +# i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. +indent_brace_parent = false # true/false + +# Whether to indent based on the open parenthesis instead of the open brace +# in '({\n'. +indent_paren_open_brace = false # true/false + +# (C#) Whether to indent the brace of a C# delegate by another level. +indent_cs_delegate_brace = false # true/false + +# (C#) Whether to indent a C# delegate (to handle delegates with no brace) by +# another level. +indent_cs_delegate_body = false # true/false + +# Whether to indent the body of a 'namespace'. +indent_namespace = true # true/false + +# Whether to indent only the first namespace, and not any nested namespaces. +# Requires indent_namespace=true. +indent_namespace_single_indent = false # true/false + +# The number of spaces to indent a namespace block. +# If set to zero, use the value indent_columns +indent_namespace_level = 0 # unsigned number + +# If the body of the namespace is longer than this number, it won't be +# indented. Requires indent_namespace=true. 0 means no limit. +indent_namespace_limit = 0 # unsigned number + +# Whether the 'extern "C"' body is indented. +indent_extern = false # true/false + +# Whether the 'class' body is indented. +indent_class = true # true/false + +# Whether to indent the stuff after a leading base class colon. +indent_class_colon = false # true/false + +# Whether to indent based on a class colon instead of the stuff after the +# colon. Requires indent_class_colon=true. +indent_class_on_colon = false # true/false + +# Whether to indent the stuff after a leading class initializer colon. +indent_constr_colon = false # true/false + +# Virtual indent from the ':' for member initializers. +# +# Default: 2 +indent_ctor_init_leading = 2 # unsigned number + +# Additional indent for constructor initializer list. +# Negative values decrease indent down to the first column. +indent_ctor_init = 0 # number + +# Whether to indent 'if' following 'else' as a new block under the 'else'. +# If false, 'else\nif' is treated as 'else if' for indenting purposes. +indent_else_if = false # true/false + +# Amount to indent variable declarations after a open brace. +# +# <0: Relative +# >=0: Absolute +indent_var_def_blk = 0 # number + +# Whether to indent continued variable declarations instead of aligning. +indent_var_def_cont = false # true/false + +# Whether to indent continued shift expressions ('<<' and '>>') instead of +# aligning. Set align_left_shift=false when enabling this. +indent_shift = false # true/false + +# Whether to force indentation of function definitions to start in column 1. +indent_func_def_force_col1 = false # true/false + +# Whether to indent continued function call parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_call_param = false # true/false + +# Whether to indent continued function definition parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_def_param = false # true/false + +# for function definitions, only if indent_func_def_param is false +# Allows to align params when appropriate and indent them when not +# behave as if it was true if paren position is more than this value +# if paren position is more than the option value +indent_func_def_param_paren_pos_threshold = 0 # unsigned number + +# Whether to indent continued function call prototype one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_proto_param = false # true/false + +# Whether to indent continued function call declaration one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_class_param = false # true/false + +# Whether to indent continued class variable constructors one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_ctor_var_param = false # true/false + +# Whether to indent continued template parameter list one indent level, +# rather than aligning parameters under the open parenthesis. +indent_template_param = false # true/false + +# Double the indent for indent_func_xxx_param options. +# Use both values of the options indent_columns and indent_param. +indent_func_param_double = false # true/false + +# Indentation column for standalone 'const' qualifier on a function +# prototype. +indent_func_const = 0 # unsigned number + +# Indentation column for standalone 'throw' qualifier on a function +# prototype. +indent_func_throw = 0 # unsigned number + +# How to indent within a macro followed by a brace on the same line +# This allows reducing the indent in macros that have (for example) +# `do { ... } while (0)` blocks bracketing them. +# +# true: add an indent for the brace on the same line as the macro +# false: do not add an indent for the brace on the same line as the macro +# +# Default: true +indent_macro_brace = true # true/false + +# The number of spaces to indent a continued '->' or '.'. +# Usually set to 0, 1, or indent_columns. +indent_member = 0 # unsigned number + +# Whether lines broken at '.' or '->' should be indented by a single indent. +# The indent_member option will not be effective if this is set to true. +indent_member_single = false # true/false + +# Spaces to indent single line ('//') comments on lines before code. +indent_sing_line_comments = 0 # unsigned number + +# When opening a paren for a control statement (if, for, while, etc), increase +# the indent level by this value. Negative values decrease the indent level. +indent_sparen_extra = 0 # number + +# Whether to indent trailing single line ('//') comments relative to the code +# instead of trying to keep the same absolute column. +indent_relative_single_line_comments = false # true/false + +# Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. +indent_switch_case = 0 # unsigned number + +# indent 'break' with 'case' from 'switch'. +indent_switch_break_with_case = false # true/false + +# Whether to indent preprocessor statements inside of switch statements. +# +# Default: true +indent_switch_pp = true # true/false + +# Spaces to shift the 'case' line, without affecting any other lines. +# Usually 0. +indent_case_shift = 0 # unsigned number + +# Spaces to indent '{' from 'case'. By default, the brace will appear under +# the 'c' in case. Usually set to 0 or indent_columns. Negative values are OK. +indent_case_brace = 0 # number + +# Whether to indent comments found in first column. +indent_col1_comment = false # true/false + +# Whether to indent multi string literal in first column. +indent_col1_multi_string_literal = false # true/false + +# How to indent goto labels. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_label = 1 # number + +# How to indent access specifiers that are followed by a +# colon. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_access_spec = -4 # number + +# Whether to indent the code after an access specifier by one level. +# If true, this option forces 'indent_access_spec=0'. +indent_access_spec_body = false # true/false + +# If an open parenthesis is followed by a newline, whether to indent the next +# line so that it lines up after the open parenthesis (not recommended). +indent_paren_nl = false # true/false + +# How to indent a close parenthesis after a newline. +# +# 0: Indent to body level (default) +# 1: Align under the open parenthesis +# 2: Indent to the brace level +indent_paren_close = 0 # unsigned number + +# Whether to indent the open parenthesis of a function definition, +# if the parenthesis is on its own line. +indent_paren_after_func_def = false # true/false + +# Whether to indent the open parenthesis of a function declaration, +# if the parenthesis is on its own line. +indent_paren_after_func_decl = false # true/false + +# Whether to indent the open parenthesis of a function call, +# if the parenthesis is on its own line. +indent_paren_after_func_call = false # true/false + +# Whether to indent a comma when inside a parenthesis. +# If true, aligns under the open parenthesis. +indent_comma_paren = false # true/false + +# Whether to indent a Boolean operator when inside a parenthesis. +# If true, aligns under the open parenthesis. +indent_bool_paren = false # true/false + +# Whether to indent a semicolon when inside a for parenthesis. +# If true, aligns under the open for parenthesis. +indent_semicolon_for_paren = false # true/false + +# Whether to align the first expression to following ones +# if indent_bool_paren=true. +indent_first_bool_expr = false # true/false + +# Whether to align the first expression to following ones +# if indent_semicolon_for_paren=true. +indent_first_for_expr = false # true/false + +# If an open square is followed by a newline, whether to indent the next line +# so that it lines up after the open square (not recommended). +indent_square_nl = false # true/false + +# (ESQL/C) Whether to preserve the relative indent of 'EXEC SQL' bodies. +indent_preserve_sql = false # true/false + +# Whether to align continued statements at the '='. If false or if the '=' is +# followed by a newline, the next line is indent one tab. +# +# Default: true +indent_align_assign = true # true/false + +# If true, the indentation of the chunks after a '=' sequence will be set at +# LHS token indentation column before '='. +indent_off_after_assign = false # true/false + +# Whether to align continued statements at the '('. If false or the '(' is +# followed by a newline, the next line indent is one tab. +# +# Default: true +indent_align_paren = true # true/false + +# (OC) Whether to indent Objective-C code inside message selectors. +indent_oc_inside_msg_sel = false # true/false + +# (OC) Whether to indent Objective-C blocks at brace level instead of usual +# rules. +indent_oc_block = false # true/false + +# (OC) Indent for Objective-C blocks in a message relative to the parameter +# name. +# +# =0: Use indent_oc_block rules +# >0: Use specified number of spaces to indent +indent_oc_block_msg = 0 # unsigned number + +# (OC) Minimum indent for subsequent parameters +indent_oc_msg_colon = 0 # unsigned number + +# (OC) Whether to prioritize aligning with initial colon (and stripping spaces +# from lines, if necessary). +# +# Default: true +indent_oc_msg_prioritize_first_colon = true # true/false + +# (OC) Whether to indent blocks the way that Xcode does by default +# (from the keyword if the parameter is on its own line; otherwise, from the +# previous indentation level). Requires indent_oc_block_msg=true. +indent_oc_block_msg_xcode_style = false # true/false + +# (OC) Whether to indent blocks from where the brace is, relative to a +# message keyword. Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_keyword = false # true/false + +# (OC) Whether to indent blocks from where the brace is, relative to a message +# colon. Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_colon = false # true/false + +# (OC) Whether to indent blocks from where the block caret is. +# Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_caret = false # true/false + +# (OC) Whether to indent blocks from where the brace caret is. +# Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_brace = false # true/false + +# When indenting after virtual brace open and newline add further spaces to +# reach this minimum indent. +indent_min_vbrace_open = 0 # unsigned number + +# Whether to add further spaces after regular indent to reach next tabstop +# when indenting after virtual brace open and newline. +indent_vbrace_open_on_tabstop = false # true/false + +# How to indent after a brace followed by another token (not a newline). +# true: indent all contained lines to match the token +# false: indent all contained lines to match the brace +# +# Default: true +indent_token_after_brace = true # true/false + +# Whether to indent the body of a C++11 lambda. +indent_cpp_lambda_body = false # true/false + +# How to indent compound literals that are being returned. +# true: add both the indent from return & the compound literal open brace (ie: +# 2 indent levels) +# false: only indent 1 level, don't add the indent for the open brace, only add +# the indent for the return. +# +# Default: true +indent_compound_literal_return = true # true/false + +# (C#) Whether to indent a 'using' block if no braces are used. +# +# Default: true +indent_using_block = true # true/false + +# How to indent the continuation of ternary operator. +# +# 0: Off (default) +# 1: When the `if_false` is a continuation, indent it under `if_false` +# 2: When the `:` is a continuation, indent it under `?` +indent_ternary_operator = 0 # unsigned number + +# Whether to indent the statments inside ternary operator. +indent_inside_ternary_operator = false # true/false + +# If true, the indentation of the chunks after a `return` sequence will be set at return indentation column. +indent_off_after_return = false # true/false + +# If true, the indentation of the chunks after a `return new` sequence will be set at return indentation column. +indent_off_after_return_new = false # true/false + +# If true, the tokens after return are indented with regular single indentation. By default (false) the indentation is after the return token. +indent_single_after_return = false # true/false + +# Whether to ignore indent and alignment for 'asm' blocks (i.e. assume they +# have their own indentation). +indent_ignore_asm_block = false # true/false + +# Don't indent the close parenthesis of a function definition, +# if the parenthesis is on its own line. +donot_indent_func_def_close_paren = false # true/false + +# +# Newline adding and removing options +# + +# Whether to collapse empty blocks between '{' and '}'. +# If true, overrides nl_inside_empty_func +nl_collapse_empty_body = true # true/false + +# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. +nl_assign_leave_one_liners = false # true/false + +# Don't split one-line braced statements inside a 'class xx { }' body. +nl_class_leave_one_liners = false # true/false + +# Don't split one-line enums, as in 'enum foo { BAR = 15 };' +nl_enum_leave_one_liners = false # true/false + +# Don't split one-line get or set functions. +nl_getset_leave_one_liners = false # true/false + +# (C#) Don't split one-line property get or set functions. +nl_cs_property_leave_one_liners = false # true/false + +# Don't split one-line function definitions, as in 'int foo() { return 0; }'. +# might modify nl_func_type_name +nl_func_leave_one_liners = false # true/false + +# Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. +nl_cpp_lambda_leave_one_liners = false # true/false + +# Don't split one-line if/else statements, as in 'if(...) b++;'. +nl_if_leave_one_liners = false # true/false + +# Don't split one-line while statements, as in 'while(...) b++;'. +nl_while_leave_one_liners = false # true/false + +# Don't split one-line for statements, as in 'for(...) b++;'. +nl_for_leave_one_liners = false # true/false + +# (OC) Don't split one-line Objective-C messages. +nl_oc_msg_leave_one_liner = false # true/false + +# (OC) Add or remove newline between method declaration and '{'. +nl_oc_mdef_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between Objective-C block signature and '{'. +nl_oc_block_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove blank line before '@interface' statement. +nl_oc_before_interface = ignore # ignore/add/remove/force + +# (OC) Add or remove blank line before '@implementation' statement. +nl_oc_before_implementation = ignore # ignore/add/remove/force + +# (OC) Add or remove blank line before '@end' statement. +nl_oc_before_end = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between '@interface' and '{'. +nl_oc_interface_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between '@implementation' and '{'. +nl_oc_implementation_brace = ignore # ignore/add/remove/force + +# Add or remove newlines at the start of the file. +nl_start_of_file = ignore # ignore/add/remove/force + +# The minimum number of newlines at the start of the file (only used if +# nl_start_of_file is 'add' or 'force'). +nl_start_of_file_min = 0 # unsigned number + +# Add or remove newline at the end of the file. +nl_end_of_file = ignore # ignore/add/remove/force + +# The minimum number of newlines at the end of the file (only used if +# nl_end_of_file is 'add' or 'force'). +nl_end_of_file_min = 0 # unsigned number + +# Add or remove newline between '=' and '{'. +nl_assign_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between '=' and '['. +nl_assign_square = ignore # ignore/add/remove/force + +# Add or remove newline between '[]' and '{'. +nl_tsquare_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline after '= ['. Will also affect the newline before +# the ']'. +nl_after_square_assign = ignore # ignore/add/remove/force + +# Add or remove newline between a function call's ')' and '{', as in +# 'list_for_each(item, &list) { }'. +nl_fcall_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum' and '{'. +nl_enum_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum' and 'class'. +nl_enum_class = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class' and the identifier. +nl_enum_class_identifier = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class' type and ':'. +nl_enum_identifier_colon = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class identifier :' and type. +nl_enum_colon_type = ignore # ignore/add/remove/force + +# Add or remove newline between 'struct and '{'. +nl_struct_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'union' and '{'. +nl_union_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'if' and '{'. +nl_if_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'else'. +nl_brace_else = ignore # ignore/add/remove/force + +# Add or remove newline between 'else if' and '{'. If set to ignore, +# nl_if_brace is used instead. +nl_elseif_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'else' and '{'. +nl_else_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'else' and 'if'. +nl_else_if = ignore # ignore/add/remove/force + +# Add or remove newline before '{' opening brace +nl_before_opening_brace_func_class_def = ignore # ignore/add/remove/force + +# Add or remove newline before 'if'/'else if' closing parenthesis. +nl_before_if_closing_paren = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'finally'. +nl_brace_finally = ignore # ignore/add/remove/force + +# Add or remove newline between 'finally' and '{'. +nl_finally_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'try' and '{'. +nl_try_brace = ignore # ignore/add/remove/force + +# Add or remove newline between get/set and '{'. +nl_getset_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'for' and '{'. +nl_for_brace = ignore # ignore/add/remove/force + +# Add or remove newline before the '{' of a 'catch' statement, as in +# 'catch (decl) {'. +nl_catch_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove newline before the '{' of a '@catch' statement, as in +# '@catch (decl) {'. If set to ignore, nl_catch_brace is used. +nl_oc_catch_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'catch'. +nl_brace_catch = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between '}' and '@catch'. If set to ignore, +# nl_brace_catch is used. +nl_oc_brace_catch = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and ']'. +nl_brace_square = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and ')' in a function invocation. +nl_brace_fparen = ignore # ignore/add/remove/force + +# Add or remove newline between 'while' and '{'. +nl_while_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between 'scope (x)' and '{'. +nl_scope_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between 'unittest' and '{'. +nl_unittest_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between 'version (x)' and '{'. +nl_version_brace = ignore # ignore/add/remove/force + +# (C#) Add or remove newline between 'using' and '{'. +nl_using_brace = ignore # ignore/add/remove/force + +# Add or remove newline between two open or close braces. Due to general +# newline/brace handling, REMOVE may not work. +nl_brace_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'do' and '{'. +nl_do_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'while' of 'do' statement. +nl_brace_while = ignore # ignore/add/remove/force + +# Add or remove newline between 'switch' and '{'. +nl_switch_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'synchronized' and '{'. +nl_synchronized_brace = ignore # ignore/add/remove/force + +# Add a newline between ')' and '{' if the ')' is on a different line than the +# if/for/etc. +# +# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and +# nl_catch_brace. +nl_multi_line_cond = false # true/false + +# Add a newline after '(' if an if/for/while/switch condition spans multiple +# lines +nl_multi_line_sparen_open = ignore # ignore/add/remove/force + +# Add a newline before ')' if an if/for/while/switch condition spans multiple +# lines. Overrides nl_before_if_closing_paren if both are specified. +nl_multi_line_sparen_close = ignore # ignore/add/remove/force + +# Force a newline in a define after the macro name for multi-line defines. +nl_multi_line_define = false # true/false + +# Whether to add a newline before 'case', and a blank line before a 'case' +# statement that follows a ';' or '}'. +nl_before_case = false # true/false + +# Whether to add a newline after a 'case' statement. +nl_after_case = false # true/false + +# Add or remove newline between a case ':' and '{'. +# +# Overrides nl_after_case. +nl_case_colon_brace = ignore # ignore/add/remove/force + +# Add or remove newline between ')' and 'throw'. +nl_before_throw = ignore # ignore/add/remove/force + +# Add or remove newline between 'namespace' and '{'. +nl_namespace_brace = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class. +nl_template_class = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class declaration. +# +# Overrides nl_template_class. +nl_template_class_decl = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<>' of a specialized class declaration. +# +# Overrides nl_template_class_decl. +nl_template_class_decl_special = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class definition. +# +# Overrides nl_template_class. +nl_template_class_def = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<>' of a specialized class definition. +# +# Overrides nl_template_class_def. +nl_template_class_def_special = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template function. +nl_template_func = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template function +# declaration. +# +# Overrides nl_template_func. +nl_template_func_decl = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<>' of a specialized function +# declaration. +# +# Overrides nl_template_func_decl. +nl_template_func_decl_special = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template function +# definition. +# +# Overrides nl_template_func. +nl_template_func_def = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<>' of a specialized function +# definition. +# +# Overrides nl_template_func_def. +nl_template_func_def_special = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template variable. +nl_template_var = ignore # ignore/add/remove/force + +# Add or remove newline between 'template<...>' and 'using' of a templated +# type alias. +nl_template_using = ignore # ignore/add/remove/force + +# Add or remove newline between 'class' and '{'. +nl_class_brace = ignore # ignore/add/remove/force + +# Add or remove newline before or after (depending on pos_class_comma, +# may not be IGNORE) each',' in the base class list. +nl_class_init_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in the constructor member +# initialization. Related to nl_constr_colon, pos_constr_colon and +# pos_constr_comma. +nl_constr_init_args = ignore # ignore/add/remove/force + +# Add or remove newline before first element, after comma, and after last +# element, in 'enum'. +nl_enum_own_lines = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a function +# definition. +# might be modified by nl_func_leave_one_liners +nl_func_type_name = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name inside a class +# definition. If set to ignore, nl_func_type_name or nl_func_proto_type_name +# is used instead. +nl_func_type_name_class = ignore # ignore/add/remove/force + +# Add or remove newline between class specification and '::' +# in 'void A::f() { }'. Only appears in separate member implementation (does +# not appear with in-line implementation). +nl_func_class_scope = ignore # ignore/add/remove/force + +# Add or remove newline between function scope and name, as in +# 'void A :: f() { }'. +nl_func_scope_name = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a prototype. +nl_func_proto_type_name = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# declaration. +nl_func_paren = ignore # ignore/add/remove/force + +# Overrides nl_func_paren for functions with no parameters. +nl_func_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# definition. +nl_func_def_paren = ignore # ignore/add/remove/force + +# Overrides nl_func_def_paren for functions with no parameters. +nl_func_def_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# call. +nl_func_call_paren = ignore # ignore/add/remove/force + +# Overrides nl_func_call_paren for functions with no parameters. +nl_func_call_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline after '(' in a function declaration. +nl_func_decl_start = ignore # ignore/add/remove/force + +# Add or remove newline after '(' in a function definition. +nl_func_def_start = ignore # ignore/add/remove/force + +# Overrides nl_func_decl_start when there is only one parameter. +nl_func_decl_start_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_start when there is only one parameter. +nl_func_def_start_single = ignore # ignore/add/remove/force + +# Whether to add a newline after '(' in a function declaration if '(' and ')' +# are in different lines. If false, nl_func_decl_start is used instead. +nl_func_decl_start_multi_line = false # true/false + +# Whether to add a newline after '(' in a function definition if '(' and ')' +# are in different lines. If false, nl_func_def_start is used instead. +nl_func_def_start_multi_line = false # true/false + +# Add or remove newline after each ',' in a function declaration. +nl_func_decl_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function definition. +nl_func_def_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function call. +nl_func_call_args = ignore # ignore/add/remove/force + +# Whether to add a newline after each ',' in a function declaration if '(' +# and ')' are in different lines. If false, nl_func_decl_args is used instead. +nl_func_decl_args_multi_line = false # true/false + +# Whether to add a newline after each ',' in a function definition if '(' +# and ')' are in different lines. If false, nl_func_def_args is used instead. +nl_func_def_args_multi_line = false # true/false + +# Add or remove newline before the ')' in a function declaration. +nl_func_decl_end = ignore # ignore/add/remove/force + +# Add or remove newline before the ')' in a function definition. +nl_func_def_end = ignore # ignore/add/remove/force + +# Overrides nl_func_decl_end when there is only one parameter. +nl_func_decl_end_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_end when there is only one parameter. +nl_func_def_end_single = ignore # ignore/add/remove/force + +# Whether to add a newline before ')' in a function declaration if '(' and ')' +# are in different lines. If false, nl_func_decl_end is used instead. +nl_func_decl_end_multi_line = false # true/false + +# Whether to add a newline before ')' in a function definition if '(' and ')' +# are in different lines. If false, nl_func_def_end is used instead. +nl_func_def_end_multi_line = false # true/false + +# Add or remove newline between '()' in a function declaration. +nl_func_decl_empty = ignore # ignore/add/remove/force + +# Add or remove newline between '()' in a function definition. +nl_func_def_empty = ignore # ignore/add/remove/force + +# Add or remove newline between '()' in a function call. +nl_func_call_empty = ignore # ignore/add/remove/force + +# Whether to add a newline after '(' in a function call, +# has preference over nl_func_call_start_multi_line. +nl_func_call_start = ignore # ignore/add/remove/force + +# Whether to add a newline before ')' in a function call. +nl_func_call_end = ignore # ignore/add/remove/force + +# Whether to add a newline after '(' in a function call if '(' and ')' are in +# different lines. +nl_func_call_start_multi_line = false # true/false + +# Whether to add a newline after each ',' in a function call if '(' and ')' +# are in different lines. +nl_func_call_args_multi_line = false # true/false + +# Whether to add a newline before ')' in a function call if '(' and ')' are in +# different lines. +nl_func_call_end_multi_line = false # true/false + +# Whether to respect nl_func_call_XXX option incase of closure args. +nl_func_call_args_multi_line_ignore_closures = false # true/false + +# Whether to add a newline after '<' of a template parameter list. +nl_template_start = false # true/false + +# Whether to add a newline after each ',' in a template parameter list. +nl_template_args = false # true/false + +# Whether to add a newline before '>' of a template parameter list. +nl_template_end = false # true/false + +# (OC) Whether to put each Objective-C message parameter on a separate line. +# See nl_oc_msg_leave_one_liner. +nl_oc_msg_args = false # true/false + +# Add or remove newline between function signature and '{'. +nl_fdef_brace = ignore # ignore/add/remove/force + +# Add or remove newline between function signature and '{', +# if signature ends with ')'. Overrides nl_fdef_brace. +nl_fdef_brace_cond = ignore # ignore/add/remove/force + +# Add or remove newline between C++11 lambda signature and '{'. +nl_cpp_ldef_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'return' and the return expression. +nl_return_expr = ignore # ignore/add/remove/force + +# Whether to add a newline after semicolons, except in 'for' statements. +nl_after_semicolon = false # true/false + +# (Java) Add or remove newline between the ')' and '{{' of the double brace +# initializer. +nl_paren_dbrace_open = ignore # ignore/add/remove/force + +# Whether to add a newline after the type in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst = ignore # ignore/add/remove/force + +# Whether to add a newline after the open brace in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst_open = ignore # ignore/add/remove/force + +# Whether to add a newline before the close brace in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst_close = ignore # ignore/add/remove/force + +# Whether to add a newline after '{'. This also adds a newline before the +# matching '}'. +nl_after_brace_open = false # true/false + +# Whether to add a newline between the open brace and a trailing single-line +# comment. Requires nl_after_brace_open=true. +nl_after_brace_open_cmt = false # true/false + +# Whether to add a newline after a virtual brace open with a non-empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open = false # true/false + +# Whether to add a newline after a virtual brace open with an empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open_empty = false # true/false + +# Whether to add a newline after '}'. Does not apply if followed by a +# necessary ';'. +nl_after_brace_close = false # true/false + +# Whether to add a newline after a virtual brace close, +# as in 'if (foo) a++; return;'. +nl_after_vbrace_close = false # true/false + +# Add or remove newline between the close brace and identifier, +# as in 'struct { int a; } b;'. Affects enumerations, unions and +# structures. If set to ignore, uses nl_after_brace_close. +nl_brace_struct_var = ignore # ignore/add/remove/force + +# Whether to alter newlines in '#define' macros. +nl_define_macro = false # true/false + +# Whether to alter newlines between consecutive parenthesis closes. The number +# of closing parentheses in a line will depend on respective open parenthesis +# lines. +nl_squeeze_paren_close = false # true/false + +# Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and +# '#endif'. Does not affect top-level #ifdefs. +nl_squeeze_ifdef = false # true/false + +# Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well. +nl_squeeze_ifdef_top_level = false # true/false + +# Add or remove blank line before 'if'. +nl_before_if = ignore # ignore/add/remove/force + +# Add or remove blank line after 'if' statement. Add/Force work only if the +# next token is not a closing brace. +nl_after_if = ignore # ignore/add/remove/force + +# Add or remove blank line before 'for'. +nl_before_for = ignore # ignore/add/remove/force + +# Add or remove blank line after 'for' statement. +nl_after_for = ignore # ignore/add/remove/force + +# Add or remove blank line before 'while'. +nl_before_while = ignore # ignore/add/remove/force + +# Add or remove blank line after 'while' statement. +nl_after_while = ignore # ignore/add/remove/force + +# Add or remove blank line before 'switch'. +nl_before_switch = ignore # ignore/add/remove/force + +# Add or remove blank line after 'switch' statement. +nl_after_switch = ignore # ignore/add/remove/force + +# Add or remove blank line before 'synchronized'. +nl_before_synchronized = ignore # ignore/add/remove/force + +# Add or remove blank line after 'synchronized' statement. +nl_after_synchronized = ignore # ignore/add/remove/force + +# Add or remove blank line before 'do'. +nl_before_do = ignore # ignore/add/remove/force + +# Add or remove blank line after 'do/while' statement. +nl_after_do = ignore # ignore/add/remove/force + +# Whether to put a blank line before 'return' statements, unless after an open +# brace. +nl_before_return = false # true/false + +# Whether to put a blank line after 'return' statements, unless followed by a +# close brace. +nl_after_return = false # true/false + +# Whether to put a blank line before a member '.' or '->' operators. +nl_before_member = ignore # ignore/add/remove/force + +# (Java) Whether to put a blank line after a member '.' or '->' operators. +nl_after_member = ignore # ignore/add/remove/force + +# Whether to double-space commented-entries in 'struct'/'union'/'enum'. +nl_ds_struct_enum_cmt = false # true/false + +# Whether to force a newline before '}' of a 'struct'/'union'/'enum'. +# (Lower priority than eat_blanks_before_close_brace.) +nl_ds_struct_enum_close_brace = false # true/false + +# Add or remove newline before or after (depending on pos_class_colon) a class +# colon, as in 'class Foo : public Bar'. +nl_class_colon = ignore # ignore/add/remove/force + +# Add or remove newline around a class constructor colon. The exact position +# depends on nl_constr_init_args, pos_constr_colon and pos_constr_comma. +nl_constr_colon = ignore # ignore/add/remove/force + +# Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }' +# into a single line. If true, prevents other brace newline rules from turning +# such code into four lines. +nl_namespace_two_to_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced if statements, turning them +# into one-liners, as in 'if(b)\n i++;' => 'if(b) i++;'. +nl_create_if_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced for statements, turning them +# into one-liners, as in 'for (...)\n stmt;' => 'for (...) stmt;'. +nl_create_for_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced while statements, turning +# them into one-liners, as in 'while (expr)\n stmt;' => 'while (expr) stmt;'. +nl_create_while_one_liner = false # true/false + +# Whether to collapse a function definition whose body (not counting braces) +# is only one line so that the entire definition (prototype, braces, body) is +# a single line. +nl_create_func_def_one_liner = false # true/false + +# Whether to collapse a function definition whose body (not counting braces) +# is only one line so that the entire definition (prototype, braces, body) is +# a single line. +nl_create_list_one_liner = false # true/false + +# Whether to split one-line simple unbraced if statements into two lines by +# adding a newline, as in 'if(b) i++;'. +nl_split_if_one_liner = false # true/false + +# Whether to split one-line simple unbraced for statements into two lines by +# adding a newline, as in 'for (...) stmt;'. +nl_split_for_one_liner = false # true/false + +# Whether to split one-line simple unbraced while statements into two lines by +# adding a newline, as in 'while (expr) stmt;'. +nl_split_while_one_liner = false # true/false + +# Don't add a newline before a cpp-comment in a parameter list of a function +# call. +donot_add_nl_before_cpp_comment = false # true/false + +# +# Blank line options +# + +# The maximum number of consecutive newlines (3 = 2 blank lines). +nl_max = 0 # unsigned number + +# The maximum number of consecutive newlines in a function. +nl_max_blank_in_func = 0 # unsigned number + +# The number of newlines inside an empty function body. +# This option is overridden by nl_collapse_empty_body=true +nl_inside_empty_func = 0 # unsigned number + +# The number of newlines before a function prototype. +nl_before_func_body_proto = 0 # unsigned number + +# The number of newlines before a multi-line function definition. +nl_before_func_body_def = 0 # unsigned number + +# The number of newlines before a class constructor/destructor prototype. +nl_before_func_class_proto = 0 # unsigned number + +# The number of newlines before a class constructor/destructor definition. +nl_before_func_class_def = 0 # unsigned number + +# The number of newlines after a function prototype. +nl_after_func_proto = 0 # unsigned number + +# The number of newlines after a function prototype, if not followed by +# another function prototype. +nl_after_func_proto_group = 0 # unsigned number + +# The number of newlines after a class constructor/destructor prototype. +nl_after_func_class_proto = 0 # unsigned number + +# The number of newlines after a class constructor/destructor prototype, +# if not followed by another constructor/destructor prototype. +nl_after_func_class_proto_group = 0 # unsigned number + +# Whether one-line method definitions inside a class body should be treated +# as if they were prototypes for the purposes of adding newlines. +# +# Requires nl_class_leave_one_liners=true. Overrides nl_before_func_body_def +# and nl_before_func_class_def for one-liners. +nl_class_leave_one_liner_groups = false # true/false + +# The number of newlines after '}' of a multi-line function body. +nl_after_func_body = 0 # unsigned number + +# The number of newlines after '}' of a multi-line function body in a class +# declaration. Also affects class constructors/destructors. +# +# Overrides nl_after_func_body. +nl_after_func_body_class = 0 # unsigned number + +# The number of newlines after '}' of a single line function body. Also +# affects class constructors/destructors. +# +# Overrides nl_after_func_body and nl_after_func_body_class. +nl_after_func_body_one_liner = 0 # unsigned number + +# The number of blank lines after a block of variable definitions at the top +# of a function body. +# +# 0: No change (default). +nl_func_var_def_blk = 0 # unsigned number + +# The number of newlines before a block of typedefs. If nl_after_access_spec +# is non-zero, that option takes precedence. +# +# 0: No change (default). +nl_typedef_blk_start = 0 # unsigned number + +# The number of newlines after a block of typedefs. +# +# 0: No change (default). +nl_typedef_blk_end = 0 # unsigned number + +# The maximum number of consecutive newlines within a block of typedefs. +# +# 0: No change (default). +nl_typedef_blk_in = 0 # unsigned number + +# The number of newlines before a block of variable definitions not at the top +# of a function body. If nl_after_access_spec is non-zero, that option takes +# precedence. +# +# 0: No change (default). +nl_var_def_blk_start = 0 # unsigned number + +# The number of newlines after a block of variable definitions not at the top +# of a function body. +# +# 0: No change (default). +nl_var_def_blk_end = 0 # unsigned number + +# The maximum number of consecutive newlines within a block of variable +# definitions. +# +# 0: No change (default). +nl_var_def_blk_in = 0 # unsigned number + +# The minimum number of newlines before a multi-line comment. +# Doesn't apply if after a brace open or another multi-line comment. +nl_before_block_comment = 0 # unsigned number + +# The minimum number of newlines before a single-line C comment. +# Doesn't apply if after a brace open or other single-line C comments. +nl_before_c_comment = 0 # unsigned number + +# The minimum number of newlines before a CPP comment. +# Doesn't apply if after a brace open or other CPP comments. +nl_before_cpp_comment = 0 # unsigned number + +# Whether to force a newline after a multi-line comment. +nl_after_multiline_comment = false # true/false + +# Whether to force a newline after a label's colon. +nl_after_label_colon = false # true/false + +# The number of newlines after '}' or ';' of a struct/enum/union definition. +nl_after_struct = 0 # unsigned number + +# The number of newlines before a class definition. +nl_before_class = 0 # unsigned number + +# The number of newlines after '}' or ';' of a class definition. +nl_after_class = 0 # unsigned number + +# The number of newlines before a namespace. +nl_before_namespace = 0 # unsigned number + +# The number of newlines after '{' of a namespace. This also adds newlines +# before the matching '}'. +# +# 0: Apply eat_blanks_after_open_brace or eat_blanks_before_close_brace if +# applicable, otherwise no change. +# +# Overrides eat_blanks_after_open_brace and eat_blanks_before_close_brace. +nl_inside_namespace = 0 # unsigned number + +# The number of newlines after '}' of a namespace. +nl_after_namespace = 0 # unsigned number + +# The number of newlines before an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +nl_before_access_spec = 0 # unsigned number + +# The number of newlines after an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +# +# Overrides nl_typedef_blk_start and nl_var_def_blk_start. +nl_after_access_spec = 0 # unsigned number + +# The number of newlines between a function definition and the function +# comment, as in '// comment\n void foo() {...}'. +# +# 0: No change (default). +nl_comment_func_def = 0 # unsigned number + +# The number of newlines after a try-catch-finally block that isn't followed +# by a brace close. +# +# 0: No change (default). +nl_after_try_catch_finally = 0 # unsigned number + +# (C#) The number of newlines before and after a property, indexer or event +# declaration. +# +# 0: No change (default). +nl_around_cs_property = 0 # unsigned number + +# (C#) The number of newlines between the get/set/add/remove handlers. +# +# 0: No change (default). +nl_between_get_set = 0 # unsigned number + +# (C#) Add or remove newline between property and the '{'. +nl_property_brace = ignore # ignore/add/remove/force + +# Whether to remove blank lines after '{'. +eat_blanks_after_open_brace = false # true/false + +# Whether to remove blank lines before '}'. +eat_blanks_before_close_brace = false # true/false + +# How aggressively to remove extra newlines not in preprocessor. +# +# 0: No change (default) +# 1: Remove most newlines not handled by other config +# 2: Remove all newlines and reformat completely by config +nl_remove_extra_newlines = 0 # unsigned number + +# (Java) Add or remove newline after an annotation statement. Only affects +# annotations that are after a newline. +nl_after_annotation = ignore # ignore/add/remove/force + +# (Java) Add or remove newline between two annotations. +nl_between_annotation = ignore # ignore/add/remove/force + +# The number of newlines before a whole-file #ifdef. +# +# 0: No change (default). +nl_before_whole_file_ifdef = 0 # unsigned number + +# The number of newlines after a whole-file #ifdef. +# +# 0: No change (default). +nl_after_whole_file_ifdef = 0 # unsigned number + +# The number of newlines before a whole-file #endif. +# +# 0: No change (default). +nl_before_whole_file_endif = 0 # unsigned number + +# The number of newlines after a whole-file #endif. +# +# 0: No change (default). +nl_after_whole_file_endif = 0 # unsigned number + +# +# Positioning options +# + +# The position of arithmetic operators in wrapped expressions. +pos_arith = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of assignment in wrapped expressions. Do not affect '=' +# followed by '{'. +pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of Boolean operators in wrapped expressions. +pos_bool = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of comparison operators in wrapped expressions. +pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of conditional operators, as in the '?' and ':' of +# 'expr ? stmt : stmt', in wrapped expressions. +pos_conditional = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in wrapped expressions. +pos_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in enum entries. +pos_enum_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the base class list if there is more than one +# line. Affects nl_class_init_args. +pos_class_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the constructor initialization list. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. +pos_constr_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of trailing/leading class colon, between class and base class +# list. Affects nl_class_colon. +pos_class_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of colons between constructor and member initialization. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. +pos_constr_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of shift operators in wrapped expressions. +pos_shift = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# +# Line splitting options +# + +# Try to limit code width to N columns. +code_width = 0 # unsigned number + +# Whether to fully split long 'for' statements at semi-colons. +ls_for_split_full = false # true/false + +# Whether to fully split long function prototypes/calls at commas. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_func_split_full = false # true/false + +# Whether to split lines as close to code_width as possible and ignore some +# groupings. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_code_width = false # true/false + +# +# Code alignment options (not left column spaces/tabs) +# + +# Whether to keep non-indenting tabs. +align_keep_tabs = false # true/false + +# Whether to use tabs for aligning. +align_with_tabs = false # true/false + +# Whether to bump out to the next tab when aligning. +align_on_tabstop = false # true/false + +# Whether to right-align numbers. +align_number_right = false # true/false + +# Whether to keep whitespace not required for alignment. +align_keep_extra_space = false # true/false + +# Whether to align variable definitions in prototypes and functions. +align_func_params = false # true/false + +# The span for aligning parameter definitions in function on parameter name. +# +# 0: Don't align (default). +align_func_params_span = 0 # unsigned number + +# The threshold for aligning function parameter definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_func_params_thresh = 0 # number + +# The gap for aligning function parameter definitions. +align_func_params_gap = 0 # unsigned number + +# The span for aligning constructor value. +# +# 0: Don't align (default). +align_constr_value_span = 0 # unsigned number + +# The threshold for aligning constructor value. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_constr_value_thresh = 0 # number + +# The gap for aligning constructor value. +align_constr_value_gap = 0 # unsigned number + +# Whether to align parameters in single-line functions that have the same +# name. The function names must already be aligned with each other. +align_same_func_call_params = false # true/false + +# The span for aligning function-call parameters for single line functions. +# +# 0: Don't align (default). +align_same_func_call_params_span = 0 # unsigned number + +# The threshold for aligning function-call parameters for single line +# functions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_same_func_call_params_thresh = 0 # number + +# The span for aligning variable definitions. +# +# 0: Don't align (default). +align_var_def_span = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of variable definitions. +# +# 0: Part of the type 'void * foo;' (default) +# 1: Part of the variable 'void *foo;' +# 2: Dangling 'void *foo;' +# Dangling: the '*' will not be taken into account when aligning. +align_var_def_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of variable definitions. +# +# 0: Part of the type 'long & foo;' (default) +# 1: Part of the variable 'long &foo;' +# 2: Dangling 'long &foo;' +# Dangling: the '&' will not be taken into account when aligning. +align_var_def_amp_style = 0 # unsigned number + +# The threshold for aligning variable definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_def_thresh = 0 # number + +# The gap for aligning variable definitions. +align_var_def_gap = 0 # unsigned number + +# Whether to align the colon in struct bit fields. +align_var_def_colon = false # true/false + +# The gap for aligning the colon in struct bit fields. +align_var_def_colon_gap = 0 # unsigned number + +# Whether to align any attribute after the variable name. +align_var_def_attribute = false # true/false + +# Whether to align inline struct/enum/union variable definitions. +align_var_def_inline = false # true/false + +# The span for aligning on '=' in assignments. +# +# 0: Don't align (default). +align_assign_span = 0 # unsigned number + +# The span for aligning on '=' in function prototype modifier. +# +# 0: Don't align (default). +align_assign_func_proto_span = 0 # unsigned number + +# The threshold for aligning on '=' in assignments. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_assign_thresh = 0 # number + +# How to apply align_assign_span to function declaration "assignments", i.e. +# 'virtual void foo() = 0' or '~foo() = {default|delete}'. +# +# 0: Align with other assignments (default) +# 1: Align with each other, ignoring regular assignments +# 2: Don't align +align_assign_decl_func = 0 # unsigned number + +# The span for aligning on '=' in enums. +# +# 0: Don't align (default). +align_enum_equ_span = 0 # unsigned number + +# The threshold for aligning on '=' in enums. +# Use a negative number for absolute thresholds. +# +# 0: no limit (default). +align_enum_equ_thresh = 0 # number + +# The span for aligning class member definitions. +# +# 0: Don't align (default). +align_var_class_span = 0 # unsigned number + +# The threshold for aligning class member definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_class_thresh = 0 # number + +# The gap for aligning class member definitions. +align_var_class_gap = 0 # unsigned number + +# The span for aligning struct/union member definitions. +# +# 0: Don't align (default). +align_var_struct_span = 0 # unsigned number + +# The threshold for aligning struct/union member definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_struct_thresh = 0 # number + +# The gap for aligning struct/union member definitions. +align_var_struct_gap = 0 # unsigned number + +# The span for aligning struct initializer values. +# +# 0: Don't align (default). +align_struct_init_span = 0 # unsigned number + +# The span for aligning single-line typedefs. +# +# 0: Don't align (default). +align_typedef_span = 0 # unsigned number + +# The minimum space between the type and the synonym of a typedef. +align_typedef_gap = 0 # unsigned number + +# How to align typedef'd functions with other typedefs. +# +# 0: Don't mix them at all (default) +# 1: Align the open parenthesis with the types +# 2: Align the function type name with the other type names +align_typedef_func = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of typedefs. +# +# 0: Part of the typedef type, 'typedef int * pint;' (default) +# 1: Part of type name: 'typedef int *pint;' +# 2: Dangling: 'typedef int *pint;' +# Dangling: the '*' will not be taken into account when aligning. +align_typedef_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of typedefs. +# +# 0: Part of the typedef type, 'typedef int & intref;' (default) +# 1: Part of type name: 'typedef int &intref;' +# 2: Dangling: 'typedef int &intref;' +# Dangling: the '&' will not be taken into account when aligning. +align_typedef_amp_style = 0 # unsigned number + +# The span for aligning comments that end lines. +# +# 0: Don't align (default). +align_right_cmt_span = 0 # unsigned number + +# Minimum number of columns between preceding text and a trailing comment in +# order for the comment to qualify for being aligned. Must be non-zero to have +# an effect. +align_right_cmt_gap = 0 # unsigned number + +# If aligning comments, whether to mix with comments after '}' and #endif with +# less than three spaces before the comment. +align_right_cmt_mix = false # true/false + +# Whether to only align trailing comments that are at the same brace level. +align_right_cmt_same_level = false # true/false + +# Minimum column at which to align trailing comments. Comments which are +# aligned beyond this column, but which can be aligned in a lesser column, +# may be "pulled in". +# +# 0: Ignore (default). +align_right_cmt_at_col = 0 # unsigned number + +# The span for aligning function prototypes. +# +# 0: Don't align (default). +align_func_proto_span = 0 # unsigned number + +# The threshold for aligning function prototypes. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_func_proto_thresh = 0 # number + +# Minimum gap between the return type and the function name. +align_func_proto_gap = 0 # unsigned number + +# Whether to align function prototypes on the 'operator' keyword instead of +# what follows. +align_on_operator = false # true/false + +# Whether to mix aligning prototype and variable declarations. If true, +# align_var_def_XXX options are used instead of align_func_proto_XXX options. +align_mix_var_proto = false # true/false + +# Whether to align single-line functions with function prototypes. +# Uses align_func_proto_span. +align_single_line_func = false # true/false + +# Whether to align the open brace of single-line functions. +# Requires align_single_line_func=true. Uses align_func_proto_span. +align_single_line_brace = false # true/false + +# Gap for align_single_line_brace. +align_single_line_brace_gap = 0 # unsigned number + +# (OC) The span for aligning Objective-C message specifications. +# +# 0: Don't align (default). +align_oc_msg_spec_span = 0 # unsigned number + +# Whether to align macros wrapped with a backslash and a newline. This will +# not work right if the macro contains a multi-line comment. +align_nl_cont = false # true/false + +# Whether to align macro functions and variables together. +align_pp_define_together = false # true/false + +# The span for aligning on '#define' bodies. +# +# =0: Don't align (default) +# >0: Number of lines (including comments) between blocks +align_pp_define_span = 0 # unsigned number + +# The minimum space between label and value of a preprocessor define. +align_pp_define_gap = 0 # unsigned number + +# Whether to align lines that start with '<<' with previous '<<'. +# +# Default: true +align_left_shift = true # true/false + +# Whether to align comma-separated statements following '<<' (as used to +# initialize Eigen matrices). +align_eigen_comma_init = false # true/false + +# Whether to align text after 'asm volatile ()' colons. +align_asm_colon = false # true/false + +# (OC) Span for aligning parameters in an Objective-C message call +# on the ':'. +# +# 0: Don't align. +align_oc_msg_colon_span = 0 # unsigned number + +# (OC) Whether to always align with the first parameter, even if it is too +# short. +align_oc_msg_colon_first = false # true/false + +# (OC) Whether to align parameters in an Objective-C '+' or '-' declaration +# on the ':'. +align_oc_decl_colon = false # true/false + +# (OC) Whether to not align parameters in an Objectve-C message call if first +# colon is not on next line of the message call (the same way Xcode does +# aligment) +align_oc_msg_colon_xcode_like = false # true/false + +# +# Comment modification options +# + +# Try to wrap comments at N columns. +cmt_width = 0 # unsigned number + +# How to reflow comments. +# +# 0: No reflowing (apart from the line wrapping due to cmt_width) (default) +# 1: No touching at all +# 2: Full reflow +cmt_reflow_mode = 0 # unsigned number + +# Whether to convert all tabs to spaces in comments. If false, tabs in +# comments are left alone, unless used for indenting. +cmt_convert_tab_to_spaces = true # true/false + +# Whether to apply changes to multi-line comments, including cmt_width, +# keyword substitution and leading chars. +# +# Default: true +cmt_indent_multi = true # true/false + +# Whether to group c-comments that look like they are in a block. +cmt_c_group = false # true/false + +# Whether to put an empty '/*' on the first line of the combined c-comment. +cmt_c_nl_start = false # true/false + +# Whether to add a newline before the closing '*/' of the combined c-comment. +cmt_c_nl_end = false # true/false + +# Whether to change cpp-comments into c-comments. +cmt_cpp_to_c = false # true/false + +# Whether to group cpp-comments that look like they are in a block. Only +# meaningful if cmt_cpp_to_c=true. +cmt_cpp_group = false # true/false + +# Whether to put an empty '/*' on the first line of the combined cpp-comment +# when converting to a c-comment. +# +# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. +cmt_cpp_nl_start = false # true/false + +# Whether to add a newline before the closing '*/' of the combined cpp-comment +# when converting to a c-comment. +# +# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. +cmt_cpp_nl_end = false # true/false + +# Whether to put a star on subsequent comment lines. +cmt_star_cont = false # true/false + +# The number of spaces to insert at the start of subsequent comment lines. +cmt_sp_before_star_cont = 0 # unsigned number + +# The number of spaces to insert after the star on subsequent comment lines. +cmt_sp_after_star_cont = 0 # unsigned number + +# For multi-line comments with a '*' lead, remove leading spaces if the first +# and last lines of the comment are the same length. +# +# Default: true +cmt_multi_check_last = true # true/false + +# For multi-line comments with a '*' lead, remove leading spaces if the first +# and last lines of the comment are the same length AND if the length is +# bigger as the first_len minimum. +# +# Default: 4 +cmt_multi_first_len_minimum = 4 # unsigned number + +# Path to a file that contains text to insert at the beginning of a file if +# the file doesn't start with a C/C++ comment. If the inserted text contains +# '$(filename)', that will be replaced with the current file's name. +cmt_insert_file_header = "" # string + +# Path to a file that contains text to insert at the end of a file if the +# file doesn't end with a C/C++ comment. If the inserted text contains +# '$(filename)', that will be replaced with the current file's name. +cmt_insert_file_footer = "" # string + +# Path to a file that contains text to insert before a function definition if +# the function isn't preceded by a C/C++ comment. If the inserted text +# contains '$(function)', '$(javaparam)' or '$(fclass)', these will be +# replaced with, respectively, the name of the function, the javadoc '@param' +# and '@return' stuff, or the name of the class to which the member function +# belongs. +cmt_insert_func_header = "" # string + +# Path to a file that contains text to insert before a class if the class +# isn't preceded by a C/C++ comment. If the inserted text contains '$(class)', +# that will be replaced with the class name. +cmt_insert_class_header = "" # string + +# Path to a file that contains text to insert before an Objective-C message +# specification, if the method isn't preceded by a C/C++ comment. If the +# inserted text contains '$(message)' or '$(javaparam)', these will be +# replaced with, respectively, the name of the function, or the javadoc +# '@param' and '@return' stuff. +cmt_insert_oc_msg_header = "" # string + +# Whether a comment should be inserted if a preprocessor is encountered when +# stepping backwards from a function name. +# +# Applies to cmt_insert_oc_msg_header, cmt_insert_func_header and +# cmt_insert_class_header. +cmt_insert_before_preproc = false # true/false + +# Whether a comment should be inserted if a function is declared inline to a +# class definition. +# +# Applies to cmt_insert_func_header. +# +# Default: true +cmt_insert_before_inlines = true # true/false + +# Whether a comment should be inserted if the function is a class constructor +# or destructor. +# +# Applies to cmt_insert_func_header. +cmt_insert_before_ctor_dtor = false # true/false + +# +# Code modifying options (non-whitespace) +# + +# Add or remove braces on a single-line 'do' statement. +mod_full_brace_do = ignore # ignore/add/remove/force + +# Add or remove braces on a single-line 'for' statement. +mod_full_brace_for = ignore # ignore/add/remove/force + +# (Pawn) Add or remove braces on a single-line function definition. +mod_full_brace_function = ignore # ignore/add/remove/force + +# Add or remove braces on a single-line 'if' statement. Braces will not be +# removed if the braced statement contains an 'else'. +mod_full_brace_if = ignore # ignore/add/remove/force + +# Whether to enforce that all blocks of an 'if'/'else if'/'else' chain either +# have, or do not have, braces. If true, braces will be added if any block +# needs braces, and will only be removed if they can be removed from all +# blocks. +# +# Overrides mod_full_brace_if. +mod_full_brace_if_chain = false # true/false + +# Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. +# If true, mod_full_brace_if_chain will only remove braces from an 'if' that +# does not have an 'else if' or 'else'. +mod_full_brace_if_chain_only = false # true/false + +# Add or remove braces on single-line 'while' statement. +mod_full_brace_while = ignore # ignore/add/remove/force + +# Add or remove braces on single-line 'using ()' statement. +mod_full_brace_using = ignore # ignore/add/remove/force + +# Don't remove braces around statements that span N newlines +mod_full_brace_nl = 0 # unsigned number + +# Whether to prevent removal of braces from 'if'/'for'/'while'/etc. blocks +# which span multiple lines. +# +# Affects: +# mod_full_brace_for +# mod_full_brace_if +# mod_full_brace_if_chain +# mod_full_brace_if_chain_only +# mod_full_brace_while +# mod_full_brace_using +# +# Does not affect: +# mod_full_brace_do +# mod_full_brace_function +mod_full_brace_nl_block_rem_mlcond = false # true/false + +# Add or remove unnecessary parenthesis on 'return' statement. +mod_paren_on_return = ignore # ignore/add/remove/force + +# (Pawn) Whether to change optional semicolons to real semicolons. +mod_pawn_semicolon = false # true/false + +# Whether to fully parenthesize Boolean expressions in 'while' and 'if' +# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. +mod_full_paren_if_bool = false # true/false + +# Whether to remove superfluous semicolons. +mod_remove_extra_semicolon = false # true/false + +# If a function body exceeds the specified number of newlines and doesn't have +# a comment after the close brace, a comment will be added. +mod_add_long_function_closebrace_comment = 0 # unsigned number + +# If a namespace body exceeds the specified number of newlines and doesn't +# have a comment after the close brace, a comment will be added. +mod_add_long_namespace_closebrace_comment = 0 # unsigned number + +# If a class body exceeds the specified number of newlines and doesn't have a +# comment after the close brace, a comment will be added. +mod_add_long_class_closebrace_comment = 0 # unsigned number + +# If a switch body exceeds the specified number of newlines and doesn't have a +# comment after the close brace, a comment will be added. +mod_add_long_switch_closebrace_comment = 0 # unsigned number + +# If an #ifdef body exceeds the specified number of newlines and doesn't have +# a comment after the #endif, a comment will be added. +mod_add_long_ifdef_endif_comment = 0 # unsigned number + +# If an #ifdef or #else body exceeds the specified number of newlines and +# doesn't have a comment after the #else, a comment will be added. +mod_add_long_ifdef_else_comment = 0 # unsigned number + +# Whether to take care of the case by the mod_sort_xx options. +mod_sort_case_sensitive = false # true/false + +# Whether to sort consecutive single-line 'import' statements. +mod_sort_import = false # true/false + +# (C#) Whether to sort consecutive single-line 'using' statements. +mod_sort_using = false # true/false + +# Whether to sort consecutive single-line '#include' statements (C/C++) and +# '#import' statements (Objective-C). Be aware that this has the potential to +# break your code if your includes/imports have ordering dependencies. +mod_sort_include = false # true/false + +# Whether to prioritize '#include' and '#import' statements that contain +# filename without extension when sorting is enabled. +mod_sort_incl_import_prioritize_filename = false # true/false + +# Whether to prioritize '#include' and '#import' statements that does not +# contain extensions when sorting is enabled. +mod_sort_incl_import_prioritize_extensionless = false # true/false + +# Whether to prioritize '#include' and '#import' statements that contain +# angle over quotes when sorting is enabled. +mod_sort_incl_import_prioritize_angle_over_quotes = false # true/false + +# Whether to ignore file extension in '#include' and '#import' statements +# for sorting comparison. +mod_sort_incl_import_ignore_extension = false # true/false + +# Whether to group '#include' and '#import' statements when sorting is enabled. +mod_sort_incl_import_grouping_enabled = false # true/false + +# Whether to move a 'break' that appears after a fully braced 'case' before +# the close brace, as in 'case X: { ... } break;' => 'case X: { ... break; }'. +mod_move_case_break = false # true/false + +# Add or remove braces around a fully braced case statement. Will only remove +# braces if there are no variable declarations in the block. +mod_case_brace = ignore # ignore/add/remove/force + +# Whether to remove a void 'return;' that appears as the last statement in a +# function. +mod_remove_empty_return = false # true/false + +# Add or remove the comma after the last value of an enumeration. +mod_enum_last_comma = ignore # ignore/add/remove/force + +# (OC) Whether to organize the properties. If true, properties will be +# rearranged according to the mod_sort_oc_property_*_weight factors. +mod_sort_oc_properties = false # true/false + +# (OC) Weight of a class property modifier. +mod_sort_oc_property_class_weight = 0 # number + +# (OC) Weight of 'atomic' and 'nonatomic'. +mod_sort_oc_property_thread_safe_weight = 0 # number + +# (OC) Weight of 'readwrite' when organizing properties. +mod_sort_oc_property_readwrite_weight = 0 # number + +# (OC) Weight of a reference type specifier ('retain', 'copy', 'assign', +# 'weak', 'strong') when organizing properties. +mod_sort_oc_property_reference_weight = 0 # number + +# (OC) Weight of getter type ('getter=') when organizing properties. +mod_sort_oc_property_getter_weight = 0 # number + +# (OC) Weight of setter type ('setter=') when organizing properties. +mod_sort_oc_property_setter_weight = 0 # number + +# (OC) Weight of nullability type ('nullable', 'nonnull', 'null_unspecified', +# 'null_resettable') when organizing properties. +mod_sort_oc_property_nullability_weight = 0 # number + +# +# Preprocessor options +# + +# Add or remove indentation of preprocessor directives inside #if blocks +# at brace level 0 (file-level). +pp_indent = ignore # ignore/add/remove/force + +# Whether to indent #if/#else/#endif at the brace level. If false, these are +# indented from column 1. +pp_indent_at_level = false # true/false + +# Specifies the number of columns to indent preprocessors per level +# at brace level 0 (file-level). If pp_indent_at_level=false, also specifies +# the number of columns to indent preprocessors per level +# at brace level > 0 (function-level). +# +# Default: 1 +pp_indent_count = 1 # unsigned number + +# Add or remove space after # based on pp_level of #if blocks. +pp_space = ignore # ignore/add/remove/force + +# Sets the number of spaces per level added with pp_space. +pp_space_count = 0 # unsigned number + +# The indent for '#region' and '#endregion' in C# and '#pragma region' in +# C/C++. Negative values decrease indent down to the first column. +pp_indent_region = 0 # number + +# Whether to indent the code between #region and #endregion. +pp_region_indent_code = false # true/false + +# If pp_indent_at_level=true, sets the indent for #if, #else and #endif when +# not at file-level. Negative values decrease indent down to the first column. +# +# =0: Indent preprocessors using output_tab_size +# >0: Column at which all preprocessors will be indented +pp_indent_if = 0 # number + +# Whether to indent the code between #if, #else and #endif. +pp_if_indent_code = false # true/false + +# Whether to indent '#define' at the brace level. If false, these are +# indented from column 1. +pp_define_at_level = false # true/false + +# Whether to ignore the '#define' body while formatting. +pp_ignore_define_body = false # true/false + +# Whether to indent case statements between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the case statements +# directly inside of. +# +# Default: true +pp_indent_case = true # true/false + +# Whether to indent whole function definitions between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the function definition +# is directly inside of. +# +# Default: true +pp_indent_func_def = true # true/false + +# Whether to indent extern C blocks between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the extern block is +# directly inside of. +# +# Default: true +pp_indent_extern = true # true/false + +# Whether to indent braces directly inside #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the braces are directly +# inside of. +# +# Default: true +pp_indent_brace = true # true/false + +# +# Sort includes options +# + +# The regex for include category with priority 0. +include_category_0 = "" # string + +# The regex for include category with priority 1. +include_category_1 = "" # string + +# The regex for include category with priority 2. +include_category_2 = "" # string + +# +# Use or Do not Use options +# + +# true: indent_func_call_param will be used (default) +# false: indent_func_call_param will NOT be used +# +# Default: true +use_indent_func_call_param = true # true/false + +# The value of the indentation for a continuation line is calculated +# differently if the statement is: +# - a declaration: your case with QString fileName ... +# - an assignment: your case with pSettings = new QSettings( ... +# +# At the second case the indentation value might be used twice: +# - at the assignment +# - at the function call (if present) +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indent_continue will be used only once +# false: indent_continue will be used every time (default) +use_indent_continue_only_once = false # true/false + +# The value might be used twice: +# - at the assignment +# - at the opening brace +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indentation will be used only once +# false: indentation will be used every time (default) +indent_cpp_lambda_only_once = true # true/false + +# Whether sp_after_angle takes precedence over sp_inside_fparen. This was the +# historic behavior, but is probably not the desired behavior, so this is off +# by default. +use_sp_after_angle_always = false # true/false + +# Whether to apply special formatting for Qt SIGNAL/SLOT macros. Essentially, +# this tries to format these so that they match Qt's normalized form (i.e. the +# result of QMetaObject::normalizedSignature), which can slightly improve the +# performance of the QObject::connect call, rather than how they would +# otherwise be formatted. +# +# See options_for_QT.cpp for details. +# +# Default: true +use_options_overriding_for_qt_macros = true # true/false + +# If true: the form feed character is removed from the list +# of whitespace characters. +# See https://en.cppreference.com/w/cpp/string/byte/isspace +use_form_feed_no_more_as_whitespace_character = false # true/false + +# +# Warn levels - 1: error, 2: warning (default), 3: note +# + +# (C#) Warning is given if doing tab-to-\t replacement and we have found one +# in a C# verbatim string literal. +# +# Default: 2 +warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number + +# Limit the number of loops. +# Used by uncrustify.cpp to exit from infinite loop. +# 0: no limit. +debug_max_number_of_loops = 0 # number + +# Set the number of the line to protocol; +# Used in the function prot_the_line if the 2. parameter is zero. +# 0: nothing protocol. +debug_line_number_to_protocol = 0 # number + +# Set the number of second(s) before terminating formatting the current file, +# 0: no timeout. +# only for linux +debug_timeout = 0 # number + +# Meaning of the settings: +# Ignore - do not do any changes +# Add - makes sure there is 1 or more space/brace/newline/etc +# Force - makes sure there is exactly 1 space/brace/newline/etc, +# behaves like Add in some contexts +# Remove - removes space/brace/newline/etc +# +# +# - Token(s) can be treated as specific type(s) with the 'set' option: +# `set tokenType tokenString [tokenString...]` +# +# Example: +# `set BOOL __AND__ __OR__` +# +# tokenTypes are defined in src/token_enum.h, use them without the +# 'CT_' prefix: 'CT_BOOL' => 'BOOL' +# +# +# - Token(s) can be treated as type(s) with the 'type' option. +# `type tokenString [tokenString...]` +# +# Example: +# `type int c_uint_8 Rectangle` +# +# This can also be achieved with `set TYPE int c_uint_8 Rectangle` +# +# +# To embed whitespace in tokenStrings use the '\' escape character, or quote +# the tokenStrings. These quotes are supported: "'` +# +# +# - Support for the auto detection of languages through the file ending can be +# added using the 'file_ext' command. +# `file_ext langType langString [langString..]` +# +# Example: +# `file_ext CPP .ch .cxx .cpp.in` +# +# langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use +# them without the 'LANG_' prefix: 'LANG_CPP' => 'CPP' +# +# +# - Custom macro-based indentation can be set up using 'macro-open', +# 'macro-else' and 'macro-close'. +# `(macro-open | macro-else | macro-close) tokenString` +# +# Example: +# `macro-open BEGIN_TEMPLATE_MESSAGE_MAP` +# `macro-open BEGIN_MESSAGE_MAP` +# `macro-close END_MESSAGE_MAP` +# +# +# option(s) with 'not default' value: 24 +# diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 964fd55e7..5c579260a 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -102,8 +102,7 @@ CmdLineParser::CmdLineParser(Settings *settings) , mShowVersion(false) , mShowErrorMessages(false) , mExitAfterPrint(false) -{ -} +{} void CmdLineParser::printMessage(const std::string &message) { @@ -968,306 +967,306 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) void CmdLineParser::printHelp() { std::cout << "Cppcheck - A tool for static C/C++ code analysis\n" - "\n" - "Syntax:\n" - " cppcheck [OPTIONS] [files or paths]\n" - "\n" - "If a directory is given instead of a filename, *.cpp, *.cxx, *.cc, *.c++, *.c,\n" - "*.tpp, and *.txx files are checked recursively from the given directory.\n\n" - "Options:\n" - " --addon=\n" - " Execute addon. i.e. --addon=cert. If options must be\n" - " provided a json configuration is needed.\n" - " --addon-python=\n" - " You can specify the python interpreter either in the\n" - " addon json files or through this command line option.\n" - " If not present, Cppcheck will try \"python3\" first and\n" - " then \"python\".\n" - " --bug-hunting\n" - " Enable noisy and soundy analysis. The normal Cppcheck\n" - " analysis is turned off.\n" - " --cppcheck-build-dir=\n" - " Cppcheck work folder. Advantages:\n" - " * whole program analysis\n" - " * faster analysis; Cppcheck will reuse the results if\n" - " the hash for a file is unchanged.\n" - " * some useful debug information, i.e. commands used to\n" - " execute clang/clang-tidy/addons.\n" - " --check-config Check cppcheck configuration. The normal code\n" - " analysis is disabled by this flag.\n" - " --check-library Show information messages when library files have\n" - " incomplete info.\n" - " --clang= Experimental: Use Clang parser instead of the builtin Cppcheck\n" - " parser. Takes the executable as optional parameter and\n" - " defaults to `clang`. Cppcheck will run the given Clang\n" - " executable, import the Clang AST and convert it into\n" - " Cppcheck data. After that the normal Cppcheck analysis is\n" - " used. You must have the executable in PATH if no path is\n" - " given.\n" - " --config-exclude=\n" - " Path (prefix) to be excluded from configuration\n" - " checking. Preprocessor configurations defined in\n" - " headers (but not sources) matching the prefix will not\n" - " be considered for evaluation.\n" - " --config-excludes-file=\n" - " A file that contains a list of config-excludes\n" - " --dump Dump xml data for each translation unit. The dump\n" - " files have the extension .dump and contain ast,\n" - " tokenlist, symboldatabase, valueflow.\n" - " -D Define preprocessor symbol. Unless --max-configs or\n" - " --force is used, Cppcheck will only check the given\n" - " configuration when -D is used.\n" - " Example: '-DDEBUG=1 -D__cplusplus'.\n" - " -E Print preprocessor output on stdout and don't do any\n" - " further processing.\n" - " --enable= Enable additional checks. The available ids are:\n" - " * all\n" - " Enable all checks. It is recommended to only\n" - " use --enable=all when the whole program is\n" - " scanned, because this enables unusedFunction.\n" - " * warning\n" - " Enable warning messages\n" - " * style\n" - " Enable all coding style checks. All messages\n" - " with the severities 'style', 'performance' and\n" - " 'portability' are enabled.\n" - " * performance\n" - " Enable performance messages\n" - " * portability\n" - " Enable portability messages\n" - " * information\n" - " Enable information messages\n" - " * unusedFunction\n" - " Check for unused functions. It is recommend\n" - " to only enable this when the whole program is\n" - " scanned.\n" - " * missingInclude\n" - " Warn if there are missing includes. For\n" - " detailed information, use '--check-config'.\n" - " Several ids can be given if you separate them with\n" - " commas. See also --std\n" - " --error-exitcode= If errors are found, integer [n] is returned instead of\n" - " the default '0'. '" << EXIT_FAILURE << "' is returned\n" - " if arguments are not valid or if no input files are\n" - " provided. Note that your operating system can modify\n" - " this value, e.g. '256' can become '0'.\n" - " --errorlist Print a list of all the error messages in XML format.\n" - " --exitcode-suppressions=\n" - " Used when certain messages should be displayed but\n" - " should not cause a non-zero exitcode.\n" - " --file-filter= Analyze only those files matching the given filter str\n" - " Example: --file-filter=*bar.cpp analyzes only files\n" - " that end with bar.cpp.\n" - " --file-list= Specify the files to check in a text file. Add one\n" - " filename per line. When file is '-,' the file list will\n" - " be read from standard input.\n" - " -f, --force Force checking of all configurations in files. If used\n" - " together with '--max-configs=', the last option is the\n" - " one that is effective.\n" - " -h, --help Print this help.\n" - " -I Give path to search for include files. Give several -I\n" - " parameters to give several paths. First given path is\n" - " searched for contained header files first. If paths are\n" - " relative to source files, this is not needed.\n" - " --includes-file=\n" - " Specify directory paths to search for included header\n" - " files in a text file. Add one include path per line.\n" - " First given path is searched for contained header\n" - " files first. If paths are relative to source files,\n" - " this is not needed.\n" - " --include=\n" - " Force inclusion of a file before the checked file.\n" - " -i Give a source file or source file directory to exclude\n" - " from the check. This applies only to source files so\n" - " header files included by source files are not matched.\n" - " Directory name is matched to all parts of the path.\n" - " --inconclusive Allow that Cppcheck reports even though the analysis is\n" - " inconclusive.\n" - " There are false positives with this option. Each result\n" - " must be carefully investigated before you know if it is\n" - " good or bad.\n" - " --inline-suppr Enable inline suppressions. Use them by placing one or\n" - " more comments, like: '// cppcheck-suppress warningId'\n" - " on the lines before the warning to suppress.\n" - " -j Start threads to do the checking simultaneously.\n" + "\n" + "Syntax:\n" + " cppcheck [OPTIONS] [files or paths]\n" + "\n" + "If a directory is given instead of a filename, *.cpp, *.cxx, *.cc, *.c++, *.c,\n" + "*.tpp, and *.txx files are checked recursively from the given directory.\n\n" + "Options:\n" + " --addon=\n" + " Execute addon. i.e. --addon=cert. If options must be\n" + " provided a json configuration is needed.\n" + " --addon-python=\n" + " You can specify the python interpreter either in the\n" + " addon json files or through this command line option.\n" + " If not present, Cppcheck will try \"python3\" first and\n" + " then \"python\".\n" + " --bug-hunting\n" + " Enable noisy and soundy analysis. The normal Cppcheck\n" + " analysis is turned off.\n" + " --cppcheck-build-dir=\n" + " Cppcheck work folder. Advantages:\n" + " * whole program analysis\n" + " * faster analysis; Cppcheck will reuse the results if\n" + " the hash for a file is unchanged.\n" + " * some useful debug information, i.e. commands used to\n" + " execute clang/clang-tidy/addons.\n" + " --check-config Check cppcheck configuration. The normal code\n" + " analysis is disabled by this flag.\n" + " --check-library Show information messages when library files have\n" + " incomplete info.\n" + " --clang= Experimental: Use Clang parser instead of the builtin Cppcheck\n" + " parser. Takes the executable as optional parameter and\n" + " defaults to `clang`. Cppcheck will run the given Clang\n" + " executable, import the Clang AST and convert it into\n" + " Cppcheck data. After that the normal Cppcheck analysis is\n" + " used. You must have the executable in PATH if no path is\n" + " given.\n" + " --config-exclude=\n" + " Path (prefix) to be excluded from configuration\n" + " checking. Preprocessor configurations defined in\n" + " headers (but not sources) matching the prefix will not\n" + " be considered for evaluation.\n" + " --config-excludes-file=\n" + " A file that contains a list of config-excludes\n" + " --dump Dump xml data for each translation unit. The dump\n" + " files have the extension .dump and contain ast,\n" + " tokenlist, symboldatabase, valueflow.\n" + " -D Define preprocessor symbol. Unless --max-configs or\n" + " --force is used, Cppcheck will only check the given\n" + " configuration when -D is used.\n" + " Example: '-DDEBUG=1 -D__cplusplus'.\n" + " -E Print preprocessor output on stdout and don't do any\n" + " further processing.\n" + " --enable= Enable additional checks. The available ids are:\n" + " * all\n" + " Enable all checks. It is recommended to only\n" + " use --enable=all when the whole program is\n" + " scanned, because this enables unusedFunction.\n" + " * warning\n" + " Enable warning messages\n" + " * style\n" + " Enable all coding style checks. All messages\n" + " with the severities 'style', 'performance' and\n" + " 'portability' are enabled.\n" + " * performance\n" + " Enable performance messages\n" + " * portability\n" + " Enable portability messages\n" + " * information\n" + " Enable information messages\n" + " * unusedFunction\n" + " Check for unused functions. It is recommend\n" + " to only enable this when the whole program is\n" + " scanned.\n" + " * missingInclude\n" + " Warn if there are missing includes. For\n" + " detailed information, use '--check-config'.\n" + " Several ids can be given if you separate them with\n" + " commas. See also --std\n" + " --error-exitcode= If errors are found, integer [n] is returned instead of\n" + " the default '0'. '" << EXIT_FAILURE << "' is returned\n" + " if arguments are not valid or if no input files are\n" + " provided. Note that your operating system can modify\n" + " this value, e.g. '256' can become '0'.\n" + " --errorlist Print a list of all the error messages in XML format.\n" + " --exitcode-suppressions=\n" + " Used when certain messages should be displayed but\n" + " should not cause a non-zero exitcode.\n" + " --file-filter= Analyze only those files matching the given filter str\n" + " Example: --file-filter=*bar.cpp analyzes only files\n" + " that end with bar.cpp.\n" + " --file-list= Specify the files to check in a text file. Add one\n" + " filename per line. When file is '-,' the file list will\n" + " be read from standard input.\n" + " -f, --force Force checking of all configurations in files. If used\n" + " together with '--max-configs=', the last option is the\n" + " one that is effective.\n" + " -h, --help Print this help.\n" + " -I Give path to search for include files. Give several -I\n" + " parameters to give several paths. First given path is\n" + " searched for contained header files first. If paths are\n" + " relative to source files, this is not needed.\n" + " --includes-file=\n" + " Specify directory paths to search for included header\n" + " files in a text file. Add one include path per line.\n" + " First given path is searched for contained header\n" + " files first. If paths are relative to source files,\n" + " this is not needed.\n" + " --include=\n" + " Force inclusion of a file before the checked file.\n" + " -i Give a source file or source file directory to exclude\n" + " from the check. This applies only to source files so\n" + " header files included by source files are not matched.\n" + " Directory name is matched to all parts of the path.\n" + " --inconclusive Allow that Cppcheck reports even though the analysis is\n" + " inconclusive.\n" + " There are false positives with this option. Each result\n" + " must be carefully investigated before you know if it is\n" + " good or bad.\n" + " --inline-suppr Enable inline suppressions. Use them by placing one or\n" + " more comments, like: '// cppcheck-suppress warningId'\n" + " on the lines before the warning to suppress.\n" + " -j Start threads to do the checking simultaneously.\n" #ifdef THREADING_MODEL_FORK - " -l Specifies that no new threads should be started if\n" - " there are other threads running and the load average is\n" - " at least .\n" + " -l Specifies that no new threads should be started if\n" + " there are other threads running and the load average is\n" + " at least .\n" #endif - " --language=, -x \n" - " Forces cppcheck to check all files as the given\n" - " language. Valid values are: c, c++\n" - " --library= Load file that contains information about types\n" - " and functions. With such information Cppcheck\n" - " understands your code better and therefore you\n" - " get better results. The std.cfg file that is\n" - " distributed with Cppcheck is loaded automatically.\n" - " For more information about library files, read the\n" - " manual.\n" - " --max-ctu-depth=N Max depth in whole program analysis. The default value\n" - " is 2. A larger value will mean more errors can be found\n" - " but also means the analysis will be slower.\n" - " --output-file= Write results to file, rather than standard error.\n" - " --project= Run Cppcheck on project. The can be a Visual\n" - " Studio Solution (*.sln), Visual Studio Project\n" - " (*.vcxproj), compile database (compile_commands.json),\n" - " or Borland C++ Builder 6 (*.bpr). The files to analyse,\n" - " include paths, defines, platform and undefines in\n" - " the specified file will be used.\n" - " --project-configuration=\n" - " If used together with a Visual Studio Solution (*.sln)\n" - " or Visual Studio Project (*.vcxproj) you can limit\n" - " the configuration cppcheck should check.\n" - " For example: '--project-configuration=Release|Win32'\n" - " --max-configs=\n" - " Maximum number of configurations to check in a file\n" - " before skipping it. Default is '12'. If used together\n" - " with '--force', the last option is the one that is\n" - " effective.\n" - " --platform=, --platform=\n" - " Specifies platform specific types and sizes. The\n" - " available builtin platforms are:\n" - " * unix32\n" - " 32 bit unix variant\n" - " * unix64\n" - " 64 bit unix variant\n" - " * win32A\n" - " 32 bit Windows ASCII character encoding\n" - " * win32W\n" - " 32 bit Windows UNICODE character encoding\n" - " * win64\n" - " 64 bit Windows\n" - " * avr8\n" - " 8 bit AVR microcontrollers\n" - " * elbrus-e1cp\n" - " Elbrus e1c+ architecture\n" - " * pic8\n" - " 8 bit PIC microcontrollers\n" - " Baseline and mid-range architectures\n" - " * pic8-enhanced\n" - " 8 bit PIC microcontrollers\n" - " Enhanced mid-range and high end (PIC18) architectures\n" - " * pic16\n" - " 16 bit PIC microcontrollers\n" - " * mips32\n" - " 32 bit MIPS microcontrollers\n" - " * native\n" - " Type sizes of host system are assumed, but no\n" - " further assumptions.\n" - " * unspecified\n" - " Unknown type sizes\n" - " --plist-output=\n" - " Generate Clang-plist output files in folder.\n" - " -q, --quiet Do not show progress reports.\n" - " -rp=, --relative-paths=\n" - " Use relative paths in output. When given, are\n" - " used as base. You can separate multiple paths by ';'.\n" - " Otherwise path where source files are searched is used.\n" - " We use string comparison to create relative paths, so\n" - " using e.g. ~ for home folder does not work. It is\n" - " currently only possible to apply the base paths to\n" - " files that are on a lower level in the directory tree.\n" - " --report-progress Report progress messages while checking a file.\n" + " --language=, -x \n" + " Forces cppcheck to check all files as the given\n" + " language. Valid values are: c, c++\n" + " --library= Load file that contains information about types\n" + " and functions. With such information Cppcheck\n" + " understands your code better and therefore you\n" + " get better results. The std.cfg file that is\n" + " distributed with Cppcheck is loaded automatically.\n" + " For more information about library files, read the\n" + " manual.\n" + " --max-ctu-depth=N Max depth in whole program analysis. The default value\n" + " is 2. A larger value will mean more errors can be found\n" + " but also means the analysis will be slower.\n" + " --output-file= Write results to file, rather than standard error.\n" + " --project= Run Cppcheck on project. The can be a Visual\n" + " Studio Solution (*.sln), Visual Studio Project\n" + " (*.vcxproj), compile database (compile_commands.json),\n" + " or Borland C++ Builder 6 (*.bpr). The files to analyse,\n" + " include paths, defines, platform and undefines in\n" + " the specified file will be used.\n" + " --project-configuration=\n" + " If used together with a Visual Studio Solution (*.sln)\n" + " or Visual Studio Project (*.vcxproj) you can limit\n" + " the configuration cppcheck should check.\n" + " For example: '--project-configuration=Release|Win32'\n" + " --max-configs=\n" + " Maximum number of configurations to check in a file\n" + " before skipping it. Default is '12'. If used together\n" + " with '--force', the last option is the one that is\n" + " effective.\n" + " --platform=, --platform=\n" + " Specifies platform specific types and sizes. The\n" + " available builtin platforms are:\n" + " * unix32\n" + " 32 bit unix variant\n" + " * unix64\n" + " 64 bit unix variant\n" + " * win32A\n" + " 32 bit Windows ASCII character encoding\n" + " * win32W\n" + " 32 bit Windows UNICODE character encoding\n" + " * win64\n" + " 64 bit Windows\n" + " * avr8\n" + " 8 bit AVR microcontrollers\n" + " * elbrus-e1cp\n" + " Elbrus e1c+ architecture\n" + " * pic8\n" + " 8 bit PIC microcontrollers\n" + " Baseline and mid-range architectures\n" + " * pic8-enhanced\n" + " 8 bit PIC microcontrollers\n" + " Enhanced mid-range and high end (PIC18) architectures\n" + " * pic16\n" + " 16 bit PIC microcontrollers\n" + " * mips32\n" + " 32 bit MIPS microcontrollers\n" + " * native\n" + " Type sizes of host system are assumed, but no\n" + " further assumptions.\n" + " * unspecified\n" + " Unknown type sizes\n" + " --plist-output=\n" + " Generate Clang-plist output files in folder.\n" + " -q, --quiet Do not show progress reports.\n" + " -rp=, --relative-paths=\n" + " Use relative paths in output. When given, are\n" + " used as base. You can separate multiple paths by ';'.\n" + " Otherwise path where source files are searched is used.\n" + " We use string comparison to create relative paths, so\n" + " using e.g. ~ for home folder does not work. It is\n" + " currently only possible to apply the base paths to\n" + " files that are on a lower level in the directory tree.\n" + " --report-progress Report progress messages while checking a file.\n" #ifdef HAVE_RULES - " --rule= Match regular expression.\n" - " --rule-file= Use given rule file. For more information, see:\n" - " http://sourceforge.net/projects/cppcheck/files/Articles/\n" + " --rule= Match regular expression.\n" + " --rule-file= Use given rule file. For more information, see:\n" + " http://sourceforge.net/projects/cppcheck/files/Articles/\n" #endif - " --std= Set standard.\n" - " The available options are:\n" - " * c89\n" - " C code is C89 compatible\n" - " * c99\n" - " C code is C99 compatible\n" - " * c11\n" - " C code is C11 compatible (default)\n" - " * c++03\n" - " C++ code is C++03 compatible\n" - " * c++11\n" - " C++ code is C++11 compatible\n" - " * c++14\n" - " C++ code is C++14 compatible\n" - " * c++17\n" - " C++ code is C++17 compatible\n" - " * c++20\n" - " C++ code is C++20 compatible (default)\n" - " --suppress= Suppress warnings that match . The format of\n" - " is:\n" - " [error id]:[filename]:[line]\n" - " The [filename] and [line] are optional. If [error id]\n" - " is a wildcard '*', all error ids match.\n" - " --suppressions-list=\n" - " Suppress warnings listed in the file. Each suppression\n" - " is in the same format as above.\n" - " --suppress-xml=\n" - " Suppress warnings listed in a xml file. XML file should\n" - " follow the manual.pdf format specified in section.\n" - " `6.4 XML suppressions` .\n" - " --template='' Format the error messages. Available fields:\n" - " {file} file name\n" - " {line} line number\n" - " {column} column number\n" - " {callstack} show a callstack. Example:\n" - " [file.c:1] -> [file.c:100]\n" - " {inconclusive:text} if warning is inconclusive, text\n" - " is written\n" - " {severity} severity\n" - " {message} warning message\n" - " {id} warning id\n" - " {cwe} CWE id (Common Weakness Enumeration)\n" - " {code} show the real code\n" - " \\t insert tab\n" - " \\n insert newline\n" - " \\r insert carriage return\n" - " Example formats:\n" - " '{file}:{line},{severity},{id},{message}' or\n" - " '{file}({line}):({severity}) {message}' or\n" - " '{callstack} {message}'\n" - " Pre-defined templates: gcc (default), cppcheck1 (old default), vs, edit.\n" - // Note: template daca2 also exists, but is for internal use (cppcheck scripts). - " --template-location=''\n" - " Format error message location. If this is not provided\n" - " then no extra location info is shown.\n" - " Available fields:\n" - " {file} file name\n" - " {line} line number\n" - " {column} column number\n" - " {info} location info\n" - " {code} show the real code\n" - " \\t insert tab\n" - " \\n insert newline\n" - " \\r insert carriage return\n" - " Example format (gcc-like):\n" - " '{file}:{line}:{column}: note: {info}\\n{code}'\n" - " -U Undefine preprocessor symbol. Use -U to explicitly\n" - " hide certain #ifdef code paths from checking.\n" - " Example: '-UDEBUG'\n" - " -v, --verbose Output more detailed error information.\n" - " --version Print out version number.\n" - " --xml Write results in xml format to error stream (stderr).\n" - "\n" - "Example usage:\n" - " # Recursively check the current folder. Print the progress on the screen and\n" - " # write errors to a file:\n" - " cppcheck . 2> err.txt\n" - "\n" - " # Recursively check ../myproject/ and don't print progress:\n" - " cppcheck --quiet ../myproject/\n" - "\n" - " # Check test.cpp, enable all checks:\n" - " cppcheck --enable=all --inconclusive --library=posix test.cpp\n" - "\n" - " # Check f.cpp and search include files from inc1/ and inc2/:\n" - " cppcheck -I inc1/ -I inc2/ f.cpp\n" - "\n" - "For more information:\n" - " http://cppcheck.net/manual.pdf\n" - "\n" - "Many thanks to the 3rd party libraries we use:\n" - " * tinyxml2 -- loading project/library/ctu files.\n" - " * picojson -- loading compile database.\n" - " * pcre -- rules.\n" - " * qt -- used in GUI\n" - " * z3 -- theorem prover from Microsoft Research used in bug hunting.\n"; + " --std= Set standard.\n" + " The available options are:\n" + " * c89\n" + " C code is C89 compatible\n" + " * c99\n" + " C code is C99 compatible\n" + " * c11\n" + " C code is C11 compatible (default)\n" + " * c++03\n" + " C++ code is C++03 compatible\n" + " * c++11\n" + " C++ code is C++11 compatible\n" + " * c++14\n" + " C++ code is C++14 compatible\n" + " * c++17\n" + " C++ code is C++17 compatible\n" + " * c++20\n" + " C++ code is C++20 compatible (default)\n" + " --suppress= Suppress warnings that match . The format of\n" + " is:\n" + " [error id]:[filename]:[line]\n" + " The [filename] and [line] are optional. If [error id]\n" + " is a wildcard '*', all error ids match.\n" + " --suppressions-list=\n" + " Suppress warnings listed in the file. Each suppression\n" + " is in the same format as above.\n" + " --suppress-xml=\n" + " Suppress warnings listed in a xml file. XML file should\n" + " follow the manual.pdf format specified in section.\n" + " `6.4 XML suppressions` .\n" + " --template='' Format the error messages. Available fields:\n" + " {file} file name\n" + " {line} line number\n" + " {column} column number\n" + " {callstack} show a callstack. Example:\n" + " [file.c:1] -> [file.c:100]\n" + " {inconclusive:text} if warning is inconclusive, text\n" + " is written\n" + " {severity} severity\n" + " {message} warning message\n" + " {id} warning id\n" + " {cwe} CWE id (Common Weakness Enumeration)\n" + " {code} show the real code\n" + " \\t insert tab\n" + " \\n insert newline\n" + " \\r insert carriage return\n" + " Example formats:\n" + " '{file}:{line},{severity},{id},{message}' or\n" + " '{file}({line}):({severity}) {message}' or\n" + " '{callstack} {message}'\n" + " Pre-defined templates: gcc (default), cppcheck1 (old default), vs, edit.\n" + // Note: template daca2 also exists, but is for internal use (cppcheck scripts). + " --template-location=''\n" + " Format error message location. If this is not provided\n" + " then no extra location info is shown.\n" + " Available fields:\n" + " {file} file name\n" + " {line} line number\n" + " {column} column number\n" + " {info} location info\n" + " {code} show the real code\n" + " \\t insert tab\n" + " \\n insert newline\n" + " \\r insert carriage return\n" + " Example format (gcc-like):\n" + " '{file}:{line}:{column}: note: {info}\\n{code}'\n" + " -U Undefine preprocessor symbol. Use -U to explicitly\n" + " hide certain #ifdef code paths from checking.\n" + " Example: '-UDEBUG'\n" + " -v, --verbose Output more detailed error information.\n" + " --version Print out version number.\n" + " --xml Write results in xml format to error stream (stderr).\n" + "\n" + "Example usage:\n" + " # Recursively check the current folder. Print the progress on the screen and\n" + " # write errors to a file:\n" + " cppcheck . 2> err.txt\n" + "\n" + " # Recursively check ../myproject/ and don't print progress:\n" + " cppcheck --quiet ../myproject/\n" + "\n" + " # Check test.cpp, enable all checks:\n" + " cppcheck --enable=all --inconclusive --library=posix test.cpp\n" + "\n" + " # Check f.cpp and search include files from inc1/ and inc2/:\n" + " cppcheck -I inc1/ -I inc2/ f.cpp\n" + "\n" + "For more information:\n" + " http://cppcheck.net/manual.pdf\n" + "\n" + "Many thanks to the 3rd party libraries we use:\n" + " * tinyxml2 -- loading project/library/ctu files.\n" + " * picojson -- loading compile database.\n" + " * pcre -- rules.\n" + " * qt -- used in GUI\n" + " * z3 -- theorem prover from Microsoft Research used in bug hunting.\n"; } diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index f3e6b11fe..084250aea 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -81,8 +81,7 @@ CppCheckExecutor::CppCheckExecutor() : mSettings(nullptr), mLatestProgressOutputTime(0), mErrorOutput(nullptr), mBugHuntingReport(nullptr), mShowAllErrors(false) -{ -} +{} CppCheckExecutor::~CppCheckExecutor() { @@ -125,7 +124,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c { for (std::list::iterator iter = settings.includePaths.begin(); iter != settings.includePaths.end(); - ) { + ) { const std::string path(Path::toNativeSeparators(*iter)); if (FileLister::isDirectory(path)) ++iter; @@ -250,7 +249,7 @@ void CppCheckExecutor::setSettings(const Settings &settings) * \return size of array * */ template -std::size_t getArrayLength(const T(&)[size]) +std::size_t getArrayLength(const T (&)[size]) { return size; } @@ -548,7 +547,7 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context) (type==0) ? "reading " : "writing ", (unsigned long)info->si_addr, (isAddressOnStack)?" Stackoverflow?":"" - ); + ); break; case SIGUSR1: fputs("cppcheck received signal ", output); @@ -589,15 +588,15 @@ namespace { }; typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64); fpStackWalk64 pStackWalk64; - typedef DWORD64(WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); + typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); fpSymGetModuleBase64 pSymGetModuleBase64; typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); fpSymGetSymFromAddr64 pSymGetSymFromAddr64; typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64); fpSymGetLineFromAddr64 pSymGetLineFromAddr64; - typedef DWORD (WINAPI *fpUnDecorateSymbolName)(const TCHAR*, PTSTR, DWORD, DWORD) ; + typedef DWORD (WINAPI *fpUnDecorateSymbolName)(const TCHAR*, PTSTR, DWORD, DWORD); fpUnDecorateSymbolName pUnDecorateSymbolName; - typedef PVOID(WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); + typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); fpSymFunctionTableAccess64 pSymFunctionTableAccess64; typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL); fpSymInitialize pSymInitialize; @@ -630,9 +629,9 @@ namespace { hProcess, nullptr, TRUE - ); - CONTEXT context = *(ex->ContextRecord); - STACKFRAME64 stack= {0}; + ); + CONTEXT context = *(ex->ContextRecord); + STACKFRAME64 stack= {0}; #ifdef _M_IX86 stack.AddrPC.Offset = context.Eip; stack.AddrPC.Mode = AddrModeFlat; @@ -657,18 +656,18 @@ namespace { BOOL result = pStackWalk64 ( #ifdef _M_IX86 - IMAGE_FILE_MACHINE_I386, + IMAGE_FILE_MACHINE_I386, #else - IMAGE_FILE_MACHINE_AMD64, + IMAGE_FILE_MACHINE_AMD64, #endif - hProcess, - hThread, - &stack, - &context, - nullptr, - pSymFunctionTableAccess64, - pSymGetModuleBase64, - nullptr + hProcess, + hThread, + &stack, + &context, + nullptr, + pSymFunctionTableAccess64, + pSymGetModuleBase64, + nullptr ); if (!result) // official end... break; diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index f883470e7..d2348f731 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -99,14 +99,14 @@ public: */ static void setExceptionOutput(FILE* exceptionOutput); /** - * @return file name to be used for output from exception handler. Has to be either "stdout" or "stderr". - */ + * @return file name to be used for output from exception handler. Has to be either "stdout" or "stderr". + */ static FILE* getExceptionOutput(); /** - * Tries to load a library and prints warning/error messages - * @return false, if an error occurred (except unknown XML elements) - */ + * Tries to load a library and prints warning/error messages + * @return false, if an error occurred (except unknown XML elements) + */ static bool tryLoadLibrary(Library& destination, const char* basepath, const char* filename); /** @@ -152,17 +152,17 @@ private: int check_wrapper(CppCheck& cppcheck, int argc, const char* const argv[]); /** - * Starts the checking. - * - * @param cppcheck cppcheck instance - * @param argc from main() - * @param argv from main() - * @return EXIT_FAILURE if arguments are invalid or no input files - * were found. - * If errors are found and --error-exitcode is used, - * given value is returned instead of default 0. - * If no errors are found, 0 is returned. - */ + * Starts the checking. + * + * @param cppcheck cppcheck instance + * @param argc from main() + * @param argv from main() + * @return EXIT_FAILURE if arguments are invalid or no input files + * were found. + * If errors are found and --error-exitcode is used, + * given value is returned instead of default 0. + * If no errors are found, 0 is returned. + */ int check_internal(CppCheck& cppcheck, int argc, const char* const argv[]); /** diff --git a/cli/filelister.cpp b/cli/filelister.cpp index 82dc0f84a..8a2ac781d 100644 --- a/cli/filelister.cpp +++ b/cli/filelister.cpp @@ -193,7 +193,7 @@ static std::string addFiles2(std::map &files, const std::set &extra, bool recursive, const PathMatch& ignored - ) + ) { struct stat file_stat; if (stat(path.c_str(), &file_stat) != -1) { diff --git a/cli/filelister.h b/cli/filelister.h index 97136b07d..b4fbc94d8 100644 --- a/cli/filelister.h +++ b/cli/filelister.h @@ -81,9 +81,9 @@ public: static bool isDirectory(const std::string &path); /** - * @brief Check if the given path is a file and if it exists? - * @return true if path points to file and the file exists. - */ + * @brief Check if the given path is a file and if it exists? + * @return true if path points to file and the file exists. + */ static bool fileExists(const std::string &path); }; diff --git a/cli/main.cpp b/cli/main.cpp index 56a0526f0..4a2d297d6 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -88,7 +88,7 @@ int main(int argc, char* argv[]) GetModuleFileNameA(nullptr, exename, sizeof(exename)/sizeof(exename[0])-1); argv[0] = exename; #endif - +// *INDENT-OFF* #ifdef NDEBUG try { #endif @@ -103,12 +103,13 @@ int main(int argc, char* argv[]) } return EXIT_FAILURE; #endif +// *INDENT-ON* } // Warn about deprecated compilers #ifdef __clang__ -# if ( __clang_major__ < 2 || ( __clang_major__ == 2 && __clang_minor__ < 9)) +# if (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 9)) # warning "Using Clang 2.8 or earlier. Support for this version has been removed." # endif #elif defined(__GNUC__) diff --git a/cli/threadexecutor.cpp b/cli/threadexecutor.cpp index c7b2e1fad..918daaeba 100644 --- a/cli/threadexecutor.cpp +++ b/cli/threadexecutor.cpp @@ -55,7 +55,7 @@ using std::memset; ThreadExecutor::ThreadExecutor(const std::map &files, Settings &settings, ErrorLogger &errorLogger) : mFiles(files), mSettings(settings), mErrorLogger(errorLogger), mFileCount(0) - // Not initialized mFileSync, mErrorSync, mReportSync + // Not initialized mFileSync, mErrorSync, mReportSync { #if defined(THREADING_MODEL_FORK) mWpipe = 0; @@ -81,7 +81,7 @@ ThreadExecutor::~ThreadExecutor() void ThreadExecutor::addFileContent(const std::string &path, const std::string &content) { - mFileContents[ path ] = content; + mFileContents[path] = content; } int ThreadExecutor::handleRead(int rpipe, unsigned int &result) @@ -139,11 +139,11 @@ int ThreadExecutor::handleRead(int rpipe, unsigned int &result) unsigned int fileResult = 0; iss >> fileResult; result += fileResult; - delete [] buf; + delete[] buf; return -1; } - delete [] buf; + delete[] buf; return 1; } @@ -224,7 +224,7 @@ unsigned int ThreadExecutor::check() resultOfCheck = fileChecker.check(*iFileSettings); } else if (!mFileContents.empty() && mFileContents.find(iFile->first) != mFileContents.end()) { // File content was given as a string - resultOfCheck = fileChecker.check(iFile->first, mFileContents[ iFile->first ]); + resultOfCheck = fileChecker.check(iFile->first, mFileContents[iFile->first]); } else { // Read file from a file resultOfCheck = fileChecker.check(iFile->first); @@ -327,18 +327,18 @@ unsigned int ThreadExecutor::check() void ThreadExecutor::writeToPipe(PipeSignal type, const std::string &data) { unsigned int len = static_cast(data.length() + 1); - char *out = new char[ len + 1 + sizeof(len)]; + char *out = new char[len + 1 + sizeof(len)]; out[0] = static_cast(type); std::memcpy(&(out[1]), &len, sizeof(len)); std::memcpy(&(out[1+sizeof(len)]), data.c_str(), len); if (write(mWpipe, out, len + 1 + sizeof(len)) <= 0) { - delete [] out; + delete[] out; out = nullptr; std::cerr << "#### ThreadExecutor::writeToPipe, Failed to write to pipe" << std::endl; std::exit(EXIT_FAILURE); } - delete [] out; + delete[] out; } void ThreadExecutor::reportOut(const std::string &outmsg, Color c) @@ -523,7 +523,7 @@ void ThreadExecutor::reportInfo(const ErrorMessage &msg) report(msg, MessageType::REPORT_INFO); } -void ThreadExecutor::bughuntingReport(const std::string &/*str*/) +void ThreadExecutor::bughuntingReport(const std::string & /*str*/) { // TODO } @@ -562,32 +562,23 @@ void ThreadExecutor::report(const ErrorMessage &msg, MessageType msgType) #else -void ThreadExecutor::addFileContent(const std::string &/*path*/, const std::string &/*content*/) -{ - -} +void ThreadExecutor::addFileContent(const std::string & /*path*/, const std::string & /*content*/) +{} unsigned int ThreadExecutor::check() { return 0; } -void ThreadExecutor::reportOut(const std::string &/*outmsg*/, Color) -{ +void ThreadExecutor::reportOut(const std::string & /*outmsg*/, Color) +{} +void ThreadExecutor::reportErr(const ErrorMessage & /*msg*/) +{} -} -void ThreadExecutor::reportErr(const ErrorMessage &/*msg*/) -{ +void ThreadExecutor::reportInfo(const ErrorMessage & /*msg*/) +{} -} - -void ThreadExecutor::reportInfo(const ErrorMessage &/*msg*/) -{ - -} - -void ThreadExecutor::bughuntingReport(const std::string &/*str*/) -{ -} +void ThreadExecutor::bughuntingReport(const std::string & /*str*/) +{} #endif diff --git a/democlient/democlient.cpp b/democlient/democlient.cpp index d27d68bd1..145a40110 100644 --- a/democlient/democlient.cpp +++ b/democlient/democlient.cpp @@ -46,7 +46,7 @@ public: void bughuntingReport(const std::string&) override {} - void reportOut(const std::string &outmsg) override { } + void reportOut(const std::string &outmsg) override {} void reportErr(const ErrorMessage &msg) override { const std::string s = msg.toString(true); diff --git a/gui/aboutdialog.h b/gui/aboutdialog.h index 18a225e3f..cdc1ca6a0 100644 --- a/gui/aboutdialog.h +++ b/gui/aboutdialog.h @@ -29,9 +29,9 @@ class QWidget; /// @{ /** -* @brief About dialog -* -*/ + * @brief About dialog + * + */ class AboutDialog : public QDialog { Q_OBJECT public: diff --git a/gui/application.cpp b/gui/application.cpp index 0131d0dcf..83f0d2120 100644 --- a/gui/application.cpp +++ b/gui/application.cpp @@ -23,5 +23,4 @@ Application::Application(const QString &name, const QString &path, : mName(name) , mPath(path) , mParameters(params) -{ -} +{} diff --git a/gui/application.h b/gui/application.h index 6539d3283..7a7684f23 100644 --- a/gui/application.h +++ b/gui/application.h @@ -22,73 +22,73 @@ #include /** -* @brief A class containing information of the application to execute. -* -* Each application has a name and a path. Name is displayed to the user -* and has no other meaning. It isn't used to start the application. -* Path contains the full path to the application containing the executable name. -* Parameters contains the command line arguments for the executable. -* -* User can also specify certain predefined strings to parameters. These strings -* will be replaced with appropriate values concerning the error. Strings are: -* (file) - Filename containing the error -* (line) - Line number containing the error -* (message) - Error message -* (severity) - Error severity -* -* Example opening a file with Kate and make Kate scroll to the correct line. -* Executable: kate -* Parameters: -l(line) (file) -*/ + * @brief A class containing information of the application to execute. + * + * Each application has a name and a path. Name is displayed to the user + * and has no other meaning. It isn't used to start the application. + * Path contains the full path to the application containing the executable name. + * Parameters contains the command line arguments for the executable. + * + * User can also specify certain predefined strings to parameters. These strings + * will be replaced with appropriate values concerning the error. Strings are: + * (file) - Filename containing the error + * (line) - Line number containing the error + * (message) - Error message + * (severity) - Error severity + * + * Example opening a file with Kate and make Kate scroll to the correct line. + * Executable: kate + * Parameters: -l(line) (file) + */ class Application { public: - Application() { } + Application() {} Application(const QString &name, const QString &path, const QString ¶ms); /** - * @brief Get application name. - * @return Application name. - */ + * @brief Get application name. + * @return Application name. + */ QString getName() const { return mName; } /** - * @brief Get application path. - * @return Application path. - */ + * @brief Get application path. + * @return Application path. + */ QString getPath() const { return mPath; } /** - * @brief Get application command line parameters. - * @return Application command line parameters. - */ + * @brief Get application command line parameters. + * @return Application command line parameters. + */ QString getParameters() const { return mParameters; } /** - * @brief Set application name. - * @param name Application name. - */ + * @brief Set application name. + * @param name Application name. + */ void setName(const QString &name) { mName = name; } /** - * @brief Set application path. - * @param path Application path. - */ + * @brief Set application path. + * @param path Application path. + */ void setPath(const QString &path) { mPath = path; } /** - * @brief Set application command line parameters. - * @param parameters Application command line parameters. - */ + * @brief Set application command line parameters. + * @param parameters Application command line parameters. + */ void setParameters(const QString ¶meters) { mParameters = parameters; } @@ -96,18 +96,18 @@ public: private: /** - * @brief Application's name - */ + * @brief Application's name + */ QString mName; /** - * @brief Application's path - */ + * @brief Application's path + */ QString mPath; /** - * @brief Application's parameters - */ + * @brief Application's parameters + */ QString mParameters; }; diff --git a/gui/applicationdialog.cpp b/gui/applicationdialog.cpp index d7cb420ca..f30abbcb6 100644 --- a/gui/applicationdialog.cpp +++ b/gui/applicationdialog.cpp @@ -60,9 +60,9 @@ void ApplicationDialog::browse() filter += tr("Executable files (*.exe);;All files(*.*)"); #endif // Q_OS_WIN QString selectedFile = QFileDialog::getOpenFileName(this, - tr("Select viewer application"), - getPath(SETTINGS_LAST_APP_PATH), - filter); + tr("Select viewer application"), + getPath(SETTINGS_LAST_APP_PATH), + filter); if (!selectedFile.isEmpty()) { setPath(SETTINGS_LAST_APP_PATH, selectedFile); diff --git a/gui/applicationdialog.h b/gui/applicationdialog.h index 9f69de6e4..09255d2b0 100644 --- a/gui/applicationdialog.h +++ b/gui/applicationdialog.h @@ -30,21 +30,21 @@ class Application; /// @{ /** -* @brief Dialog to edit a startable application. -* User can open errors with user specified applications. This is a dialog -* to modify/add an application to open errors with. -* -*/ + * @brief Dialog to edit a startable application. + * User can open errors with user specified applications. This is a dialog + * to modify/add an application to open errors with. + * + */ class ApplicationDialog : public QDialog { Q_OBJECT public: /** - * @brief Constructor. - * @param title Title for the dialog. - * @param app Application definition. - * @param parent Parent widget. - */ + * @brief Constructor. + * @param title Title for the dialog. + * @param app Application definition. + * @param parent Parent widget. + */ ApplicationDialog(const QString &title, Application &app, QWidget *parent = nullptr); @@ -55,24 +55,24 @@ protected slots: void ok(); /** - * @brief Slot to browse for an application - * - */ + * @brief Slot to browse for an application + * + */ void browse(); protected: /** - * @brief UI from the Qt designer - * - */ + * @brief UI from the Qt designer + * + */ Ui::ApplicationDialog mUI; private: /** - * @brief Underlying Application - */ + * @brief Underlying Application + */ Application& mApplication; }; /// @} diff --git a/gui/applicationlist.h b/gui/applicationlist.h index f4a2b7719..56da6751f 100644 --- a/gui/applicationlist.h +++ b/gui/applicationlist.h @@ -27,8 +27,8 @@ /** -* @brief List of applications user has specified to open errors with. -*/ + * @brief List of applications user has specified to open errors with. + */ class ApplicationList : public QObject { Q_OBJECT public: @@ -37,81 +37,81 @@ public: virtual ~ApplicationList(); /** - * @brief Load all applications - * - * @return true if loading succeeded, false if there is problem with - * application list. Most probably because of older version settings need - * to be upgraded. - */ + * @brief Load all applications + * + * @return true if loading succeeded, false if there is problem with + * application list. Most probably because of older version settings need + * to be upgraded. + */ bool loadSettings(); /** - * @brief Save all applications - */ + * @brief Save all applications + */ void saveSettings() const; /** - * @brief Get the amount of applications in the list - * @return The count of applications - */ + * @brief Get the amount of applications in the list + * @return The count of applications + */ int getApplicationCount() const; /** - * @brief Get specific application's name - * - * @param index Index of the application whose name to get - * @return Name of the application - */ + * @brief Get specific application's name + * + * @param index Index of the application whose name to get + * @return Name of the application + */ const Application& getApplication(const int index) const; Application& getApplication(const int index); /** - * @brief Return the default application. - * @return Index of the default application. - */ + * @brief Return the default application. + * @return Index of the default application. + */ int getDefaultApplication() const { return mDefaultApplicationIndex; } /** - * @brief Add a new application - * - * @param app Application to add. - */ + * @brief Add a new application + * + * @param app Application to add. + */ void addApplication(const Application &app); /** - * @brief Remove an application from the list - * - * @param index Index of the application to remove. - */ + * @brief Remove an application from the list + * + * @param index Index of the application to remove. + */ void removeApplication(const int index); /** - * @brief Set application as default application. - * @param index Index of the application to make the default one - */ + * @brief Set application as default application. + * @param index Index of the application to make the default one + */ void setDefault(const int index); /** - * @brief Remove all applications from this list and copy all applications from - * list given as a parameter. - * @param list Copying source - */ + * @brief Remove all applications from this list and copy all applications from + * list given as a parameter. + * @param list Copying source + */ void copy(const ApplicationList *list); protected: /** - * @brief Clear the list - * - */ + * @brief Clear the list + * + */ void clear(); /** - * @brief Find editor used by default in Windows. - * Check if Notepad++ is installed and use it. If not, use Notepad. - */ + * @brief Find editor used by default in Windows. + * Check if Notepad++ is installed and use it. If not, use Notepad. + */ bool findDefaultWindowsEditor(); private: @@ -119,15 +119,15 @@ private: bool checkAndAddApplication(const QString& appPath, const QString& name, const QString& parameters); /** - * @brief List of applications - * - */ + * @brief List of applications + * + */ QList mApplications; /** - * @brief Index of the default application. - * - */ + * @brief Index of the default application. + * + */ int mDefaultApplicationIndex; }; /// @} diff --git a/gui/checkstatistics.h b/gui/checkstatistics.h index caf80e023..fd82a298f 100644 --- a/gui/checkstatistics.h +++ b/gui/checkstatistics.h @@ -36,26 +36,26 @@ public: explicit CheckStatistics(QObject *parent = nullptr); /** - * @brief Add new checked item to statistics. - * - * @param tool Tool. - * @param type Type of the item to add. - */ + * @brief Add new checked item to statistics. + * + * @param tool Tool. + * @param type Type of the item to add. + */ void addItem(const QString &tool, ShowTypes::ShowType type); /** - * @brief Clear the statistics. - * - */ + * @brief Clear the statistics. + * + */ void clear(); /** - * @brief Return statistics for given type. - * - * @param tool Tool. - * @param type Type for which the statistics are returned. - * @return Number of items of given type. - */ + * @brief Return statistics for given type. + * + * @param tool Tool. + * @param type Type for which the statistics are returned. + * @return Number of items of given type. + */ unsigned getCount(const QString &tool, ShowTypes::ShowType type) const; /** Get tools with results */ diff --git a/gui/checkthread.cpp b/gui/checkthread.cpp index 4be2e7a8c..6e14ab419 100644 --- a/gui/checkthread.cpp +++ b/gui/checkthread.cpp @@ -241,12 +241,12 @@ void CheckThread::runAddonsAndTools(const ImportProject::FileSettings *fileSetti if (addon == CLANG_ANALYZER) { /* - // Using clang - args.insert(0,"--analyze"); - args.insert(1, "-Xanalyzer"); - args.insert(2, "-analyzer-output=text"); - args << fileName; - */ + // Using clang + args.insert(0,"--analyze"); + args.insert(1, "-Xanalyzer"); + args.insert(2, "-analyzer-output=text"); + args << fileName; + */ // Using clang-tidy args.insert(0,"-checks=-*,clang-analyzer-*"); args.insert(1, fileName); diff --git a/gui/checkthread.h b/gui/checkthread.h index 26000e3f5..766231f5d 100644 --- a/gui/checkthread.h +++ b/gui/checkthread.h @@ -31,9 +31,9 @@ class ThreadResult; /// @{ /** -* @brief Thread to run cppcheck -* -*/ + * @brief Thread to run cppcheck + * + */ class CheckThread : public QThread { Q_OBJECT public: @@ -41,16 +41,16 @@ public: virtual ~CheckThread(); /** - * @brief Set settings for cppcheck - * - * @param settings settings for cppcheck - */ + * @brief Set settings for cppcheck + * + * @param settings settings for cppcheck + */ void check(const Settings &settings); /** - * @brief Run whole program analysis - * @param files All files - */ + * @brief Run whole program analysis + * @param files All files + */ void analyseWholeProgram(const QStringList &files); void setAddonsAndTools(const QStringList &addonsAndTools) { @@ -70,9 +70,9 @@ public: } /** - * @brief method that is run in a thread - * - */ + * @brief method that is run in a thread + * + */ void run(); void stop(); @@ -92,21 +92,21 @@ public: signals: /** - * @brief cpp checking is done - * - */ + * @brief cpp checking is done + * + */ void done(); void fileChecked(const QString &file); protected: /** - * @brief States for the check thread. - * Whole purpose of these states is to allow stopping of the checking. When - * stopping we say for the thread (Stopping) that stop when current check - * has been completed. Thread must be stopped cleanly, just terminating thread - * likely causes unpredictable side-effects. - */ + * @brief States for the check thread. + * Whole purpose of these states is to allow stopping of the checking. When + * stopping we say for the thread (Stopping) that stop when current check + * has been completed. Thread must be stopped cleanly, just terminating thread + * likely causes unpredictable side-effects. + */ enum State { Running, /**< The thread is checking. */ Stopping, /**< The thread will stop after current work. */ @@ -115,14 +115,14 @@ protected: }; /** - * @brief Thread's current execution state. - */ + * @brief Thread's current execution state. + */ State mState; ThreadResult &mResult; /** - * @brief Cppcheck itself - */ + * @brief Cppcheck itself + */ CppCheck mCppcheck; private: diff --git a/gui/codeeditorstyle.cpp b/gui/codeeditorstyle.cpp index 9d78b6e70..7cfb2aef5 100644 --- a/gui/codeeditorstyle.cpp +++ b/gui/codeeditorstyle.cpp @@ -94,9 +94,9 @@ CodeEditorStyle CodeEditorStyle::loadSettings(QSettings *settings) // style section exists - load values settings->beginGroup(SETTINGS_STYLE_GROUP); QString type = settings->value( - SETTINGS_STYLE_TYPE, - QVariant(SETTINGS_STYLE_TYPE_LIGHT) - ).toString(); + SETTINGS_STYLE_TYPE, + QVariant(SETTINGS_STYLE_TYPE_LIGHT) + ).toString(); if (type == SETTINGS_STYLE_TYPE_LIGHT) { settings->endGroup(); return theStyle; @@ -108,53 +108,53 @@ CodeEditorStyle CodeEditorStyle::loadSettings(QSettings *settings) } if (type == SETTINGS_STYLE_TYPE_CUSTOM) { theStyle.widgetFGColor = settings->value( - SETTINGS_STYLE_WIDGETFG, - QVariant(defaultStyleLight.widgetFGColor)).value(); + SETTINGS_STYLE_WIDGETFG, + QVariant(defaultStyleLight.widgetFGColor)).value(); theStyle.widgetBGColor = settings->value( - SETTINGS_STYLE_WIDGETBG, - QVariant(defaultStyleLight.widgetBGColor)).value(); + SETTINGS_STYLE_WIDGETBG, + QVariant(defaultStyleLight.widgetBGColor)).value(); theStyle.highlightBGColor = settings->value( - SETTINGS_STYLE_HILIFG, - QVariant(defaultStyleLight.highlightBGColor)).value(); + SETTINGS_STYLE_HILIFG, + QVariant(defaultStyleLight.highlightBGColor)).value(); theStyle.lineNumFGColor = settings->value( - SETTINGS_STYLE_LINENUMFG, - QVariant(defaultStyleLight.lineNumFGColor)).value(); + SETTINGS_STYLE_LINENUMFG, + QVariant(defaultStyleLight.lineNumFGColor)).value(); theStyle.lineNumBGColor = settings->value( - SETTINGS_STYLE_LINENUMBG, - QVariant(defaultStyleLight.lineNumBGColor)).value(); + SETTINGS_STYLE_LINENUMBG, + QVariant(defaultStyleLight.lineNumBGColor)).value(); theStyle.keywordColor = settings->value( - SETTINGS_STYLE_KEYWORDFG, - QVariant(defaultStyleLight.keywordColor)).value(); + SETTINGS_STYLE_KEYWORDFG, + QVariant(defaultStyleLight.keywordColor)).value(); QVariant defKeyWWt(static_cast(defaultStyleLight.keywordWeight)); theStyle.keywordWeight = static_cast( - settings->value(SETTINGS_STYLE_KEYWORDWT, defKeyWWt).toInt()); + settings->value(SETTINGS_STYLE_KEYWORDWT, defKeyWWt).toInt()); theStyle.classColor = settings->value( - SETTINGS_STYLE_CLASSFG, - QVariant(defaultStyleLight.classColor)).value(); + SETTINGS_STYLE_CLASSFG, + QVariant(defaultStyleLight.classColor)).value(); QVariant defClsWt(static_cast(defaultStyleLight.classWeight)); theStyle.classWeight = static_cast( - settings->value(SETTINGS_STYLE_CLASSWT, defClsWt).toInt()); + settings->value(SETTINGS_STYLE_CLASSWT, defClsWt).toInt()); theStyle.quoteColor = settings->value( - SETTINGS_STYLE_QUOTEFG, - QVariant(defaultStyleLight.quoteColor)).value(); + SETTINGS_STYLE_QUOTEFG, + QVariant(defaultStyleLight.quoteColor)).value(); QVariant defQteWt(static_cast(defaultStyleLight.quoteWeight)); theStyle.quoteWeight = static_cast( - settings->value(SETTINGS_STYLE_QUOTEWT, defQteWt).toInt()); + settings->value(SETTINGS_STYLE_QUOTEWT, defQteWt).toInt()); theStyle.commentColor = settings->value( - SETTINGS_STYLE_COMMENTFG, - QVariant(defaultStyleLight.commentColor)).value(); + SETTINGS_STYLE_COMMENTFG, + QVariant(defaultStyleLight.commentColor)).value(); QVariant defCmtWt(static_cast(defaultStyleLight.commentWeight)); theStyle.commentWeight = static_cast( - settings->value(SETTINGS_STYLE_COMMENTWT, defCmtWt).toInt()); + settings->value(SETTINGS_STYLE_COMMENTWT, defCmtWt).toInt()); theStyle.symbolFGColor = settings->value( - SETTINGS_STYLE_SYMBOLFG, - QVariant(defaultStyleLight.symbolFGColor)).value(); + SETTINGS_STYLE_SYMBOLFG, + QVariant(defaultStyleLight.symbolFGColor)).value(); theStyle.symbolBGColor = settings->value( - SETTINGS_STYLE_SYMBOLBG, - QVariant(defaultStyleLight.symbolBGColor)).value(); + SETTINGS_STYLE_SYMBOLBG, + QVariant(defaultStyleLight.symbolBGColor)).value(); QVariant defSymWt(static_cast(defaultStyleLight.symbolWeight)); theStyle.symbolWeight = static_cast( - settings->value(SETTINGS_STYLE_SYMBOLWT, defSymWt).toInt()); + settings->value(SETTINGS_STYLE_SYMBOLWT, defSymWt).toInt()); } settings->endGroup(); return theStyle; diff --git a/gui/codeeditorstyle.h b/gui/codeeditorstyle.h index 53b2ef5e4..c5780725a 100644 --- a/gui/codeeditorstyle.h +++ b/gui/codeeditorstyle.h @@ -73,47 +73,47 @@ public: static void saveSettings(QSettings *settings, const CodeEditorStyle& theStyle); public: - bool mSystemTheme; - QColor widgetFGColor; - QColor widgetBGColor; - QColor highlightBGColor; - QColor lineNumFGColor; - QColor lineNumBGColor; - QColor keywordColor; - QFont::Weight keywordWeight; - QColor classColor; - QFont::Weight classWeight; - QColor quoteColor; - QFont::Weight quoteWeight; - QColor commentColor; - QFont::Weight commentWeight; - QColor symbolFGColor; - QColor symbolBGColor; - QFont::Weight symbolWeight; + bool mSystemTheme; + QColor widgetFGColor; + QColor widgetBGColor; + QColor highlightBGColor; + QColor lineNumFGColor; + QColor lineNumBGColor; + QColor keywordColor; + QFont::Weight keywordWeight; + QColor classColor; + QFont::Weight classWeight; + QColor quoteColor; + QFont::Weight quoteWeight; + QColor commentColor; + QFont::Weight commentWeight; + QColor symbolFGColor; + QColor symbolBGColor; + QFont::Weight symbolWeight; }; static const CodeEditorStyle defaultStyleLight( - /* editor FG/BG */ Qt::black, QColor(240, 240, 240), - /* highlight BG */ QColor(255, 220, 220), - /* line number FG/BG */ Qt::black, QColor(240, 240, 240), - /* keyword FG/Weight */ Qt::darkBlue, QFont::Bold, - /* class FG/Weight */ Qt::darkMagenta, QFont::Bold, - /* quote FG/Weight */ Qt::darkGreen, QFont::Normal, - /* comment FG/Weight */ Qt::gray, QFont::Normal, - /* Symbol FG/BG/Weight */ Qt::red, QColor(220, 220, 255), QFont::Normal -); + /* editor FG/BG */ Qt::black, QColor(240, 240, 240), + /* highlight BG */ QColor(255, 220, 220), + /* line number FG/BG */ Qt::black, QColor(240, 240, 240), + /* keyword FG/Weight */ Qt::darkBlue, QFont::Bold, + /* class FG/Weight */ Qt::darkMagenta, QFont::Bold, + /* quote FG/Weight */ Qt::darkGreen, QFont::Normal, + /* comment FG/Weight */ Qt::gray, QFont::Normal, + /* Symbol FG/BG/Weight */ Qt::red, QColor(220, 220, 255), QFont::Normal + ); // Styling derived from Eclipse Color Theme - 'RecognEyes' // http://www.eclipsecolorthemes.org/?view=theme&id=30 static const CodeEditorStyle defaultStyleDark( - /* editor FG/BG */ QColor(218, 218, 218), QColor(16, 16, 32), - /* highlight BG */ QColor(64, 64, 64), - /* line number FG/BG */ QColor(43, 145, 175), QColor(16, 16, 32), - /* keyword FG/Weight */ QColor(0, 204, 204), QFont::Bold, - /* class FG/Weight */ QColor(218, 0, 218), QFont::Bold, - /* quote FG/Weight */ QColor(0, 204, 0), QFont::Normal, - /* comment FG/Weight */ QColor(180, 180, 180), QFont::Normal, - /* Symbol FG/BG/Weight */ QColor(218, 32, 32), QColor(32, 32, 108), QFont::Normal -); + /* editor FG/BG */ QColor(218, 218, 218), QColor(16, 16, 32), + /* highlight BG */ QColor(64, 64, 64), + /* line number FG/BG */ QColor(43, 145, 175), QColor(16, 16, 32), + /* keyword FG/Weight */ QColor(0, 204, 204), QFont::Bold, + /* class FG/Weight */ QColor(218, 0, 218), QFont::Bold, + /* quote FG/Weight */ QColor(0, 204, 0), QFont::Normal, + /* comment FG/Weight */ QColor(180, 180, 180), QFont::Normal, + /* Symbol FG/BG/Weight */ QColor(218, 32, 32), QColor(32, 32, 108), QFont::Normal + ); #endif /* CODEEDITORSTYLE_H */ diff --git a/gui/codeeditstylecontrols.cpp b/gui/codeeditstylecontrols.cpp index 303281aba..0b3d4257c 100644 --- a/gui/codeeditstylecontrols.cpp +++ b/gui/codeeditstylecontrols.cpp @@ -30,9 +30,9 @@ SelectColorButton::SelectColorButton(QWidget* parent) : void SelectColorButton::updateColor() { QString btnColorStyle = QString( - "background-color:rgb(%1,%2,%3);" - "border-style:outset;" - "border-width: 1px;") + "background-color:rgb(%1,%2,%3);" + "border-style:outset;" + "border-width: 1px;") .arg(mColor.red()) .arg(mColor.green()) .arg(mColor.blue()); diff --git a/gui/codeeditstyledialog.cpp b/gui/codeeditstyledialog.cpp index 7406ea160..a3bca4a12 100644 --- a/gui/codeeditstyledialog.cpp +++ b/gui/codeeditstyledialog.cpp @@ -50,10 +50,10 @@ const QString StyleEditDialog::mSampleDocument( "}\n"); const QStringList StyleEditDialog::mErrSymbolsList = ( - QStringList(QStringList() - << "nLife" - << "dValue" - << "nValue")); + QStringList(QStringList() + << "nLife" + << "dValue" + << "nValue")); const int StyleEditDialog::mErrLineNum = 16; StyleEditDialog::StyleEditDialog(const CodeEditorStyle& newStyle, diff --git a/gui/codeeditstyledialog.h b/gui/codeeditstyledialog.h index f1b7ec78f..6efc90542 100644 --- a/gui/codeeditstyledialog.h +++ b/gui/codeeditstyledialog.h @@ -62,8 +62,8 @@ public slots: void weightChangedSymbol(const QFont::Weight& newWeight); private: - CodeEditorStyle mStyleIncoming; - CodeEditorStyle mStyleOutgoing; + CodeEditorStyle mStyleIncoming; + CodeEditorStyle mStyleOutgoing; CodeEditor *mSampleEditor; @@ -87,9 +87,9 @@ private: QPushButton *mBtnDefaultLight; QPushButton *mBtnDefaultDark; - static const QString mSampleDocument; + static const QString mSampleDocument; static const QStringList mErrSymbolsList; - static const int mErrLineNum; + static const int mErrLineNum; }; #endif //CODEEDITSTYLEDIALOG_H diff --git a/gui/common.cpp b/gui/common.cpp index a35c66304..31a58ee84 100644 --- a/gui/common.cpp +++ b/gui/common.cpp @@ -50,7 +50,7 @@ QString toFilterString(const QMap& filters, bool addAllSupporte if (addAllSupported) { entries << QCoreApplication::translate("toFilterString", "All supported files (%1)") - .arg(QStringList(filters.values()).join(" ")); + .arg(QStringList(filters.values()).join(" ")); } if (addAll) { diff --git a/gui/common.h b/gui/common.h index 77c8bef14..50e64cefd 100644 --- a/gui/common.h +++ b/gui/common.h @@ -29,8 +29,8 @@ #define CLANG_TIDY "clang-tidy" /** -* QSetting value names -*/ + * QSetting value names + */ // Window/dialog sizes #define SETTINGS_WINDOW_MAXIMIZED "Window maximized" diff --git a/gui/cppchecklibrarydata.cpp b/gui/cppchecklibrarydata.cpp index 06ae32058..68534e311 100644 --- a/gui/cppchecklibrarydata.cpp +++ b/gui/cppchecklibrarydata.cpp @@ -27,8 +27,7 @@ const unsigned int CppcheckLibraryData::Function::Arg::ANY = ~0U; const unsigned int CppcheckLibraryData::Function::Arg::VARIADIC = ~1U; CppcheckLibraryData::CppcheckLibraryData() -{ -} +{} static std::string unhandledElement(const QXmlStreamReader &xmlReader) { diff --git a/gui/cppchecklibrarydata.h b/gui/cppchecklibrarydata.h index 2124a4af9..ff688d9c2 100644 --- a/gui/cppchecklibrarydata.h +++ b/gui/cppchecklibrarydata.h @@ -40,7 +40,7 @@ public: QString itEndPattern; bool access_arrayLike; - int size_templateParameter; + int size_templateParameter; struct { QString templateParameter; @@ -64,8 +64,7 @@ public: struct Function { Function() : noreturn(Unknown), gccPure(false), gccConst(false), - leakignore(false), useretval(false) { - } + leakignore(false), useretval(false) {} QString comments; QString name; @@ -89,8 +88,7 @@ public: } formatstr; struct Arg { Arg() : nr(0), notbool(false), notnull(false), notuninit(false), - formatstr(false), strz(false) { - } + formatstr(false), strz(false) {} QString name; unsigned int nr; diff --git a/gui/csvreport.cpp b/gui/csvreport.cpp index b29769d29..9e75111b8 100644 --- a/gui/csvreport.cpp +++ b/gui/csvreport.cpp @@ -24,12 +24,10 @@ CsvReport::CsvReport(const QString &filename) : Report(filename) -{ -} +{} CsvReport::~CsvReport() -{ -} +{} bool CsvReport::create() { @@ -54,9 +52,9 @@ void CsvReport::writeFooter() void CsvReport::writeError(const ErrorItem &error) { /* - Error as CSV line - gui/test.cpp,23,error,Mismatching allocation and deallocation: k - */ + Error as CSV line + gui/test.cpp,23,error,Mismatching allocation and deallocation: k + */ const QString file = QDir::toNativeSeparators(error.errorPath.back().file); QString line = QString("%1,%2,").arg(file).arg(error.errorPath.back().line); diff --git a/gui/csvreport.h b/gui/csvreport.h index b2f50c397..9ebe0549f 100644 --- a/gui/csvreport.h +++ b/gui/csvreport.h @@ -28,43 +28,43 @@ /** -* @brief CSV text file report. -* This report exports results as CSV (comma separated values). CSV files are -* easy to import to many other programs. -* @todo This class should be inherited from TxtReport? -*/ + * @brief CSV text file report. + * This report exports results as CSV (comma separated values). CSV files are + * easy to import to many other programs. + * @todo This class should be inherited from TxtReport? + */ class CsvReport : public Report { public: explicit CsvReport(const QString &filename); virtual ~CsvReport(); /** - * @brief Create the report (file). - * @return true if succeeded, false if file could not be created. - */ + * @brief Create the report (file). + * @return true if succeeded, false if file could not be created. + */ virtual bool create() override; /** - * @brief Write report header. - */ + * @brief Write report header. + */ virtual void writeHeader() override; /** - * @brief Write report footer. - */ + * @brief Write report footer. + */ virtual void writeFooter() override; /** - * @brief Write error to report. - * @param error Error data. - */ + * @brief Write error to report. + * @param error Error data. + */ virtual void writeError(const ErrorItem &error) override; private: /** - * @brief Text stream writer for writing the report in text format. - */ + * @brief Text stream writer for writing the report in text format. + */ QTextStream mTxtWriter; }; /// @} diff --git a/gui/erroritem.cpp b/gui/erroritem.cpp index 7cde31289..f474da985 100644 --- a/gui/erroritem.cpp +++ b/gui/erroritem.cpp @@ -24,8 +24,7 @@ QErrorPathItem::QErrorPathItem(const ErrorMessage::FileLocation &loc) , line(loc.line) , column(loc.column) , info(QString::fromStdString(loc.getinfo())) -{ -} +{} bool operator==(const QErrorPathItem &i1, const QErrorPathItem &i2) { @@ -38,8 +37,7 @@ ErrorItem::ErrorItem() , inconclusive(false) , cwe(-1) , hash(0) -{ -} +{} ErrorItem::ErrorItem(const ErrorMessage &errmsg) : file0(QString::fromStdString(errmsg.file0)) diff --git a/gui/erroritem.h b/gui/erroritem.h index 8cb337bc4..f18641931 100644 --- a/gui/erroritem.h +++ b/gui/erroritem.h @@ -45,8 +45,8 @@ public: }; /** -* @brief A class containing data for one error path item -*/ + * @brief A class containing data for one error path item + */ class QErrorPathItem { public: QErrorPathItem() : line(0), column(-1) {} @@ -60,22 +60,22 @@ public: bool operator==(const QErrorPathItem &i1, const QErrorPathItem &i2); /** -* @brief A class containing error data for one error. -* -* The paths are stored with internal ("/") separators. Only when we show the -* path or copy if for user (to clipboard) we convert to native separators. -* Full path is stored instead of relative path for flexibility. It is easy -* to get the relative path from full path when needed. -*/ + * @brief A class containing error data for one error. + * + * The paths are stored with internal ("/") separators. Only when we show the + * path or copy if for user (to clipboard) we convert to native separators. + * Full path is stored instead of relative path for flexibility. It is easy + * to get the relative path from full path when needed. + */ class ErrorItem { public: ErrorItem(); explicit ErrorItem(const ErrorMessage &errmsg); /** - * @brief Convert error item to string. - * @return Error item as string. - */ + * @brief Convert error item to string. + * @return Error item as string. + */ QString toString() const; QString tool() const; @@ -105,8 +105,8 @@ public: Q_DECLARE_METATYPE(ErrorItem) /** -* @brief A class containing error data for one shown error line. -*/ + * @brief A class containing error data for one shown error line. + */ class ErrorLine { public: QString file; diff --git a/gui/filelist.h b/gui/filelist.h index 250d485cf..2ce133393 100644 --- a/gui/filelist.h +++ b/gui/filelist.h @@ -38,57 +38,57 @@ class FileList { public: /** - * @brief Add filename to the list. - * @param filepath Full path to the file. - */ + * @brief Add filename to the list. + * @param filepath Full path to the file. + */ void addFile(const QString &filepath); /** - * @brief Add files in the directory to the list. - * @param directory Full pathname to directory to add. - * @param recursive If true also files in subdirectories are added. - */ + * @brief Add files in the directory to the list. + * @param directory Full pathname to directory to add. + * @param recursive If true also files in subdirectories are added. + */ void addDirectory(const QString &directory, bool recursive = false); /** - * @brief Add list of filenames and directories to the list. - * @param paths List of paths to add. - */ + * @brief Add list of filenames and directories to the list. + * @param paths List of paths to add. + */ void addPathList(const QStringList &paths); /** - * @brief Return list of filenames (to check). - * @return list of filenames to check. - */ + * @brief Return list of filenames (to check). + * @return list of filenames to check. + */ QStringList getFileList() const; /** - * @brief Add list of paths to exclusion list. - * @param paths Paths to exclude. - */ + * @brief Add list of paths to exclusion list. + * @param paths Paths to exclude. + */ void addExcludeList(const QStringList &paths); /** - * @brief Return list of default filename extensions included. - * @return list of default filename extensions included. - */ + * @brief Return list of default filename extensions included. + * @return list of default filename extensions included. + */ static QStringList getDefaultFilters(); protected: /** - * @brief Test if filename matches the filename extensions filtering. - * @return true if filename matches filtering. - */ + * @brief Test if filename matches the filename extensions filtering. + * @return true if filename matches filtering. + */ static bool filterMatches(const QFileInfo &inf); /** - * @brief Get filtered list of paths. - * This method takes the list of paths and applies the exclude lists to - * it. And then returns the list of paths that did not match the - * exclude filters. - * @return Filtered list of paths. - */ + * @brief Get filtered list of paths. + * This method takes the list of paths and applies the exclude lists to + * it. And then returns the list of paths that did not match the + * exclude filters. + * @return Filtered list of paths. + */ QStringList applyExcludeList() const; private: diff --git a/gui/fileviewdialog.h b/gui/fileviewdialog.h index 8e9cfc8a1..b9a50e0cd 100644 --- a/gui/fileviewdialog.h +++ b/gui/fileviewdialog.h @@ -31,11 +31,11 @@ class QTextEdit; /** -* @brief File view -dialog. -* This dialog shows text files. It is used for showing the license file and -* the authors list. -* -*/ + * @brief File view -dialog. + * This dialog shows text files. It is used for showing the license file and + * the authors list. + * + */ class FileViewDialog : public QDialog { Q_OBJECT public: @@ -47,11 +47,11 @@ public: protected: /** - * @brief Load text file contents to edit control. - * - * @param filename File to load. - * @param edit Control where to load the file contents. - */ + * @brief Load text file contents to edit control. + * + * @param filename File to load. + * @param edit Control where to load the file contents. + */ void loadTextFile(const QString &filename, QTextEdit *edit); Ui::Fileview mUI; diff --git a/gui/helpdialog.cpp b/gui/helpdialog.cpp index ce24aa1c3..0aba2026a 100644 --- a/gui/helpdialog.cpp +++ b/gui/helpdialog.cpp @@ -82,7 +82,7 @@ HelpDialog::HelpDialog(QWidget *parent) : SLOT(setSource(QUrl))); connect(mHelpEngine->indexWidget(), - SIGNAL(linkActivated(QUrl, QString)), + SIGNAL(linkActivated(QUrl,QString)), mUi->textBrowser, SLOT(setSource(QUrl))); } diff --git a/gui/librarydialog.cpp b/gui/librarydialog.cpp index 60c65a214..aaf666cd7 100644 --- a/gui/librarydialog.cpp +++ b/gui/librarydialog.cpp @@ -79,10 +79,10 @@ void LibraryDialog::openCfg() QString selectedFilter; const QString filter(tr("Library files (*.cfg)")); const QString selectedFile = QFileDialog::getOpenFileName(this, - tr("Open library file"), - datadir, - filter, - &selectedFilter); + tr("Open library file"), + datadir, + filter, + &selectedFilter); if (selectedFile.isEmpty()) return; @@ -119,8 +119,8 @@ void LibraryDialog::openCfg() mUi->functions->clear(); for (CppcheckLibraryData::Function &function : mData.functions) { mUi->functions->addItem(new FunctionListItem(mUi->functions, - &function, - false)); + &function, + false)); } mUi->sortFunctions->setEnabled(!mData.functions.empty()); mUi->filter->setEnabled(!mData.functions.empty()); @@ -152,9 +152,9 @@ void LibraryDialog::saveCfgAs() const QString filter(tr("Library files (*.cfg)")); const QString path = Path::getPathFromFilename(mFileName.toStdString()).c_str(); QString selectedFile = QFileDialog::getSaveFileName(this, - tr("Save the library as"), - path, - filter); + tr("Save the library as"), + path, + filter); if (selectedFile.isEmpty()) return; @@ -260,8 +260,8 @@ void LibraryDialog::sortFunctions(bool sort) mUi->functions->clear(); for (CppcheckLibraryData::Function &function : mData.functions) { mUi->functions->addItem(new FunctionListItem(mUi->functions, - &function, - selfunction == &function)); + &function, + selfunction == &function)); } if (!mUi->filter->text().isEmpty()) filterFunctions(mUi->filter->text()); diff --git a/gui/main.cpp b/gui/main.cpp index c00eb5e93..3cc8ec141 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -103,24 +103,24 @@ static bool CheckArgs(const QStringList &args) static void ShowUsage() { QString helpMessage = MainWindow::tr( - "Cppcheck GUI.\n\n" - "Syntax:\n" - " cppcheck-gui [OPTIONS] [files or paths]\n\n" - "Options:\n" - " -h, --help Print this help\n" - " -p Open given project file and start checking it\n" - " -l Open given results xml file\n" - " -d Specify the directory that was checked to generate the results xml specified with -l\n" - " -v, --version Show program version\n" - " --data-dir= This option is for installation scripts so they can configure the directory where\n" - " datafiles are located (translations, cfg). The GUI is not started when this option\n" - " is used."); + "Cppcheck GUI.\n\n" + "Syntax:\n" + " cppcheck-gui [OPTIONS] [files or paths]\n\n" + "Options:\n" + " -h, --help Print this help\n" + " -p Open given project file and start checking it\n" + " -l Open given results xml file\n" + " -d Specify the directory that was checked to generate the results xml specified with -l\n" + " -v, --version Show program version\n" + " --data-dir= This option is for installation scripts so they can configure the directory where\n" + " datafiles are located (translations, cfg). The GUI is not started when this option\n" + " is used."); #if defined(_WIN32) QMessageBox msgBox(QMessageBox::Information, MainWindow::tr("Cppcheck GUI - Command line parameters"), helpMessage, QMessageBox::Ok - ); + ); (void)msgBox.exec(); #else std::cout << helpMessage.toStdString() << std::endl; diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index b5fbb907b..6b537db45 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -515,7 +515,7 @@ void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrar checkSettings.loadSummaries(); std::list sourcefiles; foreach (QString s, fileNames) - sourcefiles.push_back(s.toStdString()); + sourcefiles.push_back(s.toStdString()); AnalyzerInformation::writeFilesTxt(checkSettings.buildDir, sourcefiles, checkSettings.userDefines, checkSettings.project.fileSettings); } @@ -528,14 +528,14 @@ void MainWindow::analyzeCode(const QString& code, const QString& filename) // Initialize dummy ThreadResult as ErrorLogger ThreadResult result; result.setFiles(QStringList(filename)); - connect(&result, SIGNAL(progress(int, const QString&)), - mUI.mResults, SLOT(progress(int, const QString&))); - connect(&result, SIGNAL(error(const ErrorItem &)), - mUI.mResults, SLOT(error(const ErrorItem &))); - connect(&result, SIGNAL(log(const QString &)), - mUI.mResults, SLOT(log(const QString &))); - connect(&result, SIGNAL(debugError(const ErrorItem &)), - mUI.mResults, SLOT(debugError(const ErrorItem &))); + connect(&result, SIGNAL(progress(int,const QString&)), + mUI.mResults, SLOT(progress(int,const QString&))); + connect(&result, SIGNAL(error(const ErrorItem&)), + mUI.mResults, SLOT(error(const ErrorItem&))); + connect(&result, SIGNAL(log(const QString&)), + mUI.mResults, SLOT(log(const QString&))); + connect(&result, SIGNAL(debugError(const ErrorItem&)), + mUI.mResults, SLOT(debugError(const ErrorItem&))); // Create CppCheck instance CppCheck cppcheck(result, true, nullptr); @@ -578,10 +578,10 @@ QStringList MainWindow::selectFilesToAnalyze(QFileDialog::FileMode mode) filters[tr("Borland C++ Builder 6")] = "*.bpr"; QString lastFilter = mSettings->value(SETTINGS_LAST_ANALYZE_FILES_FILTER).toString(); selected = QFileDialog::getOpenFileNames(this, - tr("Select files to analyze"), - getPath(SETTINGS_LAST_CHECK_PATH), - toFilterString(filters), - &lastFilter); + tr("Select files to analyze"), + getPath(SETTINGS_LAST_CHECK_PATH), + toFilterString(filters), + &lastFilter); mSettings->setValue(SETTINGS_LAST_ANALYZE_FILES_FILTER, lastFilter); if (selected.isEmpty()) @@ -593,8 +593,8 @@ QStringList MainWindow::selectFilesToAnalyze(QFileDialog::FileMode mode) formatAndSetTitle(); } else if (mode == QFileDialog::DirectoryOnly) { QString dir = QFileDialog::getExistingDirectory(this, - tr("Select directory to analyze"), - getPath(SETTINGS_LAST_CHECK_PATH)); + tr("Select directory to analyze"), + getPath(SETTINGS_LAST_CHECK_PATH)); if (!dir.isEmpty()) { qDebug() << "Setting current directory to: " << dir; mCurrentDirectory = dir; @@ -884,7 +884,7 @@ Settings MainWindow::getCppcheckSettings() const QStringList undefines = mProjectFile->getUndefines(); foreach (QString undefine, undefines) - result.userUndefs.insert(undefine.toStdString()); + result.userUndefs.insert(undefine.toStdString()); const QStringList libraries = mProjectFile->getLibraries(); foreach (QString library, libraries) { @@ -938,7 +938,7 @@ Settings MainWindow::getCppcheckSettings() result.safeChecks.internalFunctions = mProjectFile->safeChecks.internalFunctions; result.safeChecks.externalVariables = mProjectFile->safeChecks.externalVariables; foreach (QString s, mProjectFile->getCheckUnknownFunctionReturn()) - result.checkUnknownFunctionReturn.insert(s.toStdString()); + result.checkUnknownFunctionReturn.insert(s.toStdString()); QString filesDir(getDataDir()); const QString pythonCmd = mSettings->value(SETTINGS_PYTHON_PATH).toString(); @@ -1210,10 +1210,10 @@ void MainWindow::openResults() QString selectedFilter; const QString filter(tr("XML files (*.xml)")); QString selectedFile = QFileDialog::getOpenFileName(this, - tr("Open the report file"), - getPath(SETTINGS_LAST_RESULT_PATH), - filter, - &selectedFilter); + tr("Open the report file"), + getPath(SETTINGS_LAST_RESULT_PATH), + filter, + &selectedFilter); if (!selectedFile.isEmpty()) { loadResults(selectedFile); @@ -1381,10 +1381,10 @@ void MainWindow::save() QString selectedFilter; const QString filter(tr("XML files (*.xml);;Text files (*.txt);;CSV files (*.csv)")); QString selectedFile = QFileDialog::getSaveFileName(this, - tr("Save the report file"), - getPath(SETTINGS_LAST_RESULT_PATH), - filter, - &selectedFilter); + tr("Save the report file"), + getPath(SETTINGS_LAST_RESULT_PATH), + filter, + &selectedFilter); if (!selectedFile.isEmpty()) { Report::Type type = Report::TXT; @@ -1415,8 +1415,7 @@ void MainWindow::save() } void MainWindow::resultsAdded() -{ -} +{} void MainWindow::toggleMainToolBar() { @@ -1501,9 +1500,9 @@ void MainWindow::openProjectFile() { const QString filter = tr("Project files (*.cppcheck);;All files(*.*)"); const QString filepath = QFileDialog::getOpenFileName(this, - tr("Select Project File"), - getPath(SETTINGS_LAST_PROJECT_PATH), - filter); + tr("Select Project File"), + getPath(SETTINGS_LAST_PROJECT_PATH), + filter); if (!filepath.isEmpty()) { const QFileInfo fi(filepath); @@ -1650,9 +1649,9 @@ void MainWindow::newProjectFile() { const QString filter = tr("Project files (*.cppcheck)"); QString filepath = QFileDialog::getSaveFileName(this, - tr("Select Project Filename"), - getPath(SETTINGS_LAST_PROJECT_PATH), - filter); + tr("Select Project Filename"), + getPath(SETTINGS_LAST_PROJECT_PATH), + filter); if (filepath.isEmpty()) return; diff --git a/gui/mainwindow.h b/gui/mainwindow.h index f6bcae5ff..4710de816 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -58,8 +58,8 @@ public: MainWindow &operator=(const MainWindow &) = delete; /** - * List of checked platforms. - */ + * List of checked platforms. + */ Platforms mPlatforms; /** @@ -254,11 +254,11 @@ private: void reAnalyzeSelected(QStringList files); /** - * @brief Analyze the project. - * @param projectFile Pointer to the project to analyze. - * @param checkLibrary Flag to indicate if the library should be checked. - * @param checkConfiguration Flag to indicate if the configuration should be checked. - */ + * @brief Analyze the project. + * @param projectFile Pointer to the project to analyze. + * @param checkLibrary Flag to indicate if the library should be checked. + * @param checkConfiguration Flag to indicate if the configuration should be checked. + */ void analyzeProject(const ProjectFile *projectFile, const bool checkLibrary = false, const bool checkConfiguration = false); /** @@ -373,9 +373,9 @@ private: void loadResults(const QString &selectedFile, const QString &sourceDirectory); /** - * @brief Load last project results to the GUI. - * @return Returns true if last results was loaded - */ + * @brief Load last project results to the GUI. + * @return Returns true if last results was loaded + */ bool loadLastResults(); /** diff --git a/gui/newsuppressiondialog.cpp b/gui/newsuppressiondialog.cpp index c4ba1ac7b..ed658cc50 100644 --- a/gui/newsuppressiondialog.cpp +++ b/gui/newsuppressiondialog.cpp @@ -13,11 +13,11 @@ NewSuppressionDialog::NewSuppressionDialog(QWidget *parent) : class QErrorLogger : public ErrorLogger { public: - void reportOut(const std::string &/*outmsg*/, Color) override {} + void reportOut(const std::string & /*outmsg*/, Color) override {} void reportErr(const ErrorMessage &msg) override { errorIds << QString::fromStdString(msg.id); } - void bughuntingReport(const std::string &/*str*/) override {} + void bughuntingReport(const std::string & /*str*/) override {} QStringList errorIds; }; diff --git a/gui/platforms.h b/gui/platforms.h index 5151b336d..94c6b6299 100644 --- a/gui/platforms.h +++ b/gui/platforms.h @@ -39,8 +39,8 @@ struct Platform { }; /** - * @brief List of checked platforms. - */ + * @brief List of checked platforms. + */ class Platforms : public QObject { Q_OBJECT diff --git a/gui/printablereport.cpp b/gui/printablereport.cpp index 734c6de2b..2770cc0ef 100644 --- a/gui/printablereport.cpp +++ b/gui/printablereport.cpp @@ -23,12 +23,10 @@ PrintableReport::PrintableReport() : Report(QString()) -{ -} +{} PrintableReport::~PrintableReport() -{ -} +{} bool PrintableReport::create() { diff --git a/gui/printablereport.h b/gui/printablereport.h index a5f9b9369..4750a6cea 100644 --- a/gui/printablereport.h +++ b/gui/printablereport.h @@ -26,46 +26,46 @@ /** -* @brief Printable (in-memory) report. -* This report formats results and exposes them for printing. -*/ + * @brief Printable (in-memory) report. + * This report formats results and exposes them for printing. + */ class PrintableReport : public Report { public: PrintableReport(); virtual ~PrintableReport(); /** - * @brief Create the report (file). - * @return true if succeeded, false if file could not be created. - */ + * @brief Create the report (file). + * @return true if succeeded, false if file could not be created. + */ virtual bool create() override; /** - * @brief Write report header. - */ + * @brief Write report header. + */ virtual void writeHeader() override; /** - * @brief Write report footer. - */ + * @brief Write report footer. + */ virtual void writeFooter() override; /** - * @brief Write error to report. - * @param error Error data. - */ + * @brief Write error to report. + * @param error Error data. + */ virtual void writeError(const ErrorItem &error) override; /** - * @brief Returns the formatted report. - */ + * @brief Returns the formatted report. + */ QString getFormattedReportText() const; private: /** - * @brief Stores the formatted report contents. - */ + * @brief Stores the formatted report contents. + */ QString mFormattedReport; }; /// @} diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp index 53ccb92fc..528c825a7 100644 --- a/gui/projectfile.cpp +++ b/gui/projectfile.cpp @@ -1070,7 +1070,7 @@ QStringList ProjectFile::fromNativeSeparators(const QStringList &paths) { QStringList ret; foreach (const QString &path, paths) - ret << QDir::fromNativeSeparators(path); + ret << QDir::fromNativeSeparators(path); return ret; } @@ -1156,9 +1156,9 @@ QString ProjectFile::getAddonFilePath(QString filesDir, const QString &addon) QStringList searchPaths; searchPaths << filesDir << (filesDir + "addons/") << (filesDir + "../addons/") #ifdef FILESDIR - << (QLatin1String(FILESDIR) + "/addons/") + << (QLatin1String(FILESDIR) + "/addons/") #endif - ; + ; foreach (QString path, searchPaths) { QString f = path + addon + ".py"; diff --git a/gui/projectfile.h b/gui/projectfile.h index c5d115f85..94f74ac2e 100644 --- a/gui/projectfile.h +++ b/gui/projectfile.h @@ -36,10 +36,10 @@ class QXmlStreamWriter; /** -* @brief A class that reads and writes project files. -* The project files contain project-specific settings for checking. For -* example a list of include paths. -*/ + * @brief A class that reads and writes project files. + * The project files contain project-specific settings for checking. For + * example a list of include paths. + */ class ProjectFile : public QObject { Q_OBJECT @@ -100,57 +100,57 @@ public: } /** - * @brief Get list of include directories. - * @return list of directories. - */ + * @brief Get list of include directories. + * @return list of directories. + */ QStringList getIncludeDirs() const { return ProjectFile::fromNativeSeparators(mIncludeDirs); } /** - * @brief Get list of defines. - * @return list of defines. - */ + * @brief Get list of defines. + * @return list of defines. + */ QStringList getDefines() const { return mDefines; } /** - * @brief Get list of undefines. - * @return list of undefines. - */ + * @brief Get list of undefines. + * @return list of undefines. + */ QStringList getUndefines() const { return mUndefines; } /** - * @brief Get list of paths to check. - * @return list of paths. - */ + * @brief Get list of paths to check. + * @return list of paths. + */ QStringList getCheckPaths() const { return ProjectFile::fromNativeSeparators(mPaths); } /** - * @brief Get list of paths to exclude from the check. - * @return list of paths. - */ + * @brief Get list of paths to exclude from the check. + * @return list of paths. + */ QStringList getExcludedPaths() const { return ProjectFile::fromNativeSeparators(mExcludedPaths); } /** - * @brief Get list of paths to exclude from the check. - * @return list of paths. - */ + * @brief Get list of paths to exclude from the check. + * @return list of paths. + */ QStringList getVsConfigurations() const { return mVsConfigurations; } /** - * @brief Get list libraries. - * @return list of libraries. - */ + * @brief Get list libraries. + * @return list of libraries. + */ QStringList getLibraries() const { return mLibraries; } @@ -164,32 +164,32 @@ public: } /** - * @brief Get "raw" suppressions. - * @return list of suppressions. - */ + * @brief Get "raw" suppressions. + * @return list of suppressions. + */ QList getSuppressions() const { return mSuppressions; } /** - * @brief Get list addons. - * @return list of addons. - */ + * @brief Get list addons. + * @return list of addons. + */ QStringList getAddons() const { return mAddons; } /** - * @brief Get path to addon python script - * @param filesDir Data files folder set by --data-dir - * @param addon addon i.e. "misra" to lookup - */ + * @brief Get path to addon python script + * @param filesDir Data files folder set by --data-dir + * @param addon addon i.e. "misra" to lookup + */ static QString getAddonFilePath(QString filesDir, const QString &addon); /** - * @brief Get list of addons and tools. - * @return list of addons and tools. - */ + * @brief Get list of addons and tools. + * @return list of addons and tools. + */ QStringList getAddonsAndTools() const; bool getClangAnalyzer() const { @@ -249,17 +249,17 @@ public: } /** - * @brief Get filename for the project file. - * @return file name. - */ + * @brief Get filename for the project file. + * @return file name. + */ QString getFilename() const { return mFilename; } /** - * @brief Set project root path. - * @param rootpath new project root path. - */ + * @brief Set project root path. + * @param rootpath new project root path. + */ void setRootPath(const QString &rootpath) { mRootPath = rootpath; } @@ -474,11 +474,11 @@ protected: void readTagWarnings(QXmlStreamReader &reader, const QString &tag); /** - * @brief Read string list - * @param stringlist destination string list - * @param reader XML stream reader - * @param elementname elementname for each string - */ + * @brief Read string list + * @param stringlist destination string list + * @param reader XML stream reader + * @param elementname elementname for each string + */ void readStringList(QStringList &stringlist, QXmlStreamReader &reader, const char elementname[]); /** diff --git a/gui/projectfiledialog.cpp b/gui/projectfiledialog.cpp index 6c919df88..f8d2921b2 100644 --- a/gui/projectfiledialog.cpp +++ b/gui/projectfiledialog.cpp @@ -309,19 +309,19 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile) // Human knowledge.. /* - mUI.mListUnknownFunctionReturn->clear(); - mUI.mListUnknownFunctionReturn->addItem("rand()"); - for (int row = 0; row < mUI.mListUnknownFunctionReturn->count(); ++row) { + mUI.mListUnknownFunctionReturn->clear(); + mUI.mListUnknownFunctionReturn->addItem("rand()"); + for (int row = 0; row < mUI.mListUnknownFunctionReturn->count(); ++row) { QListWidgetItem *item = mUI.mListUnknownFunctionReturn->item(row); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag const bool unknownValues = projectFile->getCheckUnknownFunctionReturn().contains(item->text()); item->setCheckState(unknownValues ? Qt::Checked : Qt::Unchecked); // AND initialize check state - } - mUI.mCheckSafeClasses->setChecked(projectFile->getSafeChecks().classes); - mUI.mCheckSafeExternalFunctions->setChecked(projectFile->getSafeChecks().externalFunctions); - mUI.mCheckSafeInternalFunctions->setChecked(projectFile->getSafeChecks().internalFunctions); - mUI.mCheckSafeExternalVariables->setChecked(projectFile->getSafeChecks().externalVariables); - */ + } + mUI.mCheckSafeClasses->setChecked(projectFile->getSafeChecks().classes); + mUI.mCheckSafeExternalFunctions->setChecked(projectFile->getSafeChecks().externalFunctions); + mUI.mCheckSafeInternalFunctions->setChecked(projectFile->getSafeChecks().internalFunctions); + mUI.mCheckSafeExternalVariables->setChecked(projectFile->getSafeChecks().externalVariables); + */ // Addons.. QSettings settings; @@ -383,20 +383,20 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const projectFile->setSuppressions(getSuppressions()); // Human knowledge /* - QStringList unknownReturnValues; - for (int row = 0; row < mUI.mListUnknownFunctionReturn->count(); ++row) { + QStringList unknownReturnValues; + for (int row = 0; row < mUI.mListUnknownFunctionReturn->count(); ++row) { QListWidgetItem *item = mUI.mListUnknownFunctionReturn->item(row); if (item->checkState() == Qt::Checked) unknownReturnValues << item->text(); - } - projectFile->setCheckUnknownFunctionReturn(unknownReturnValues); - ProjectFile::SafeChecks safeChecks; - safeChecks.classes = mUI.mCheckSafeClasses->isChecked(); - safeChecks.externalFunctions = mUI.mCheckSafeExternalFunctions->isChecked(); - safeChecks.internalFunctions = mUI.mCheckSafeInternalFunctions->isChecked(); - safeChecks.externalVariables = mUI.mCheckSafeExternalVariables->isChecked(); - projectFile->setSafeChecks(safeChecks); - */ + } + projectFile->setCheckUnknownFunctionReturn(unknownReturnValues); + ProjectFile::SafeChecks safeChecks; + safeChecks.classes = mUI.mCheckSafeClasses->isChecked(); + safeChecks.externalFunctions = mUI.mCheckSafeExternalFunctions->isChecked(); + safeChecks.internalFunctions = mUI.mCheckSafeInternalFunctions->isChecked(); + safeChecks.externalVariables = mUI.mCheckSafeExternalVariables->isChecked(); + projectFile->setSafeChecks(safeChecks); + */ // Addons QStringList list; if (mUI.mAddonThreadSafety->isChecked()) @@ -425,8 +425,8 @@ QString ProjectFileDialog::getExistingDirectory(const QString &caption, bool tra const QFileInfo inf(mProjectFile->getFilename()); const QString rootpath = inf.absolutePath(); QString selectedDir = QFileDialog::getExistingDirectory(this, - caption, - rootpath); + caption, + rootpath); if (selectedDir.isEmpty()) return QString(); @@ -491,8 +491,8 @@ void ProjectFileDialog::browseImportProject() filters[tr("Compile database")] = "compile_commands.json"; filters[tr("Borland C++ Builder 6")] = "*.bpr"; QString fileName = QFileDialog::getOpenFileName(this, tr("Import Project"), - dir.canonicalPath(), - toFilterString(filters)); + dir.canonicalPath(), + toFilterString(filters)); if (!fileName.isEmpty()) { mUI.mEditImportProject->setText(dir.relativeFilePath(fileName)); updatePathsAndDefines(); @@ -681,9 +681,9 @@ void ProjectFileDialog::addSingleSuppression(const Suppressions::Suppression &su (suppression.fileName.find(sep) == std::string::npos)) { QFileInfo inf(mProjectFile->getFilename()); QString rootpath = inf.absolutePath(); - if (QFile::exists(QString{"%1%2%3"} .arg(rootpath, - QDir::separator(), - QString::fromStdString(suppression.fileName)))) { + if (QFile::exists(QString{"%1%2%3"}.arg(rootpath, + QDir::separator(), + QString::fromStdString(suppression.fileName)))) { Suppressions::Suppression sup = suppression; sup.fileName = rootpath.toLatin1().constData(); sup.fileName += sep; @@ -849,9 +849,9 @@ int ProjectFileDialog::getSuppressionIndex(const QString &shortText) const void ProjectFileDialog::browseMisraFile() { const QString fileName = QFileDialog::getOpenFileName(this, - tr("Select MISRA rule texts file"), - QDir::homePath(), - tr("MISRA rule texts file (%1)").arg("*.txt")); + tr("Select MISRA rule texts file"), + QDir::homePath(), + tr("MISRA rule texts file (%1)").arg("*.txt")); if (!fileName.isEmpty()) { QSettings settings; mUI.mEditMisraFile->setText(fileName); diff --git a/gui/projectfiledialog.h b/gui/projectfiledialog.h index f7a951075..5c0025728 100644 --- a/gui/projectfiledialog.h +++ b/gui/projectfiledialog.h @@ -37,8 +37,8 @@ class QCheckBox; class ProjectFile; /** -* @brief A dialog for editing project file data. -*/ + * @brief A dialog for editing project file data. + */ class ProjectFileDialog : public QDialog { Q_OBJECT public: @@ -53,9 +53,9 @@ private: void updatePathsAndDefines(); /** - * @brief Return project root path from the dialog control. - * @return Project root path. - */ + * @brief Return project root path from the dialog control. + * @return Project root path. + */ QString getRootPath() const; QStringList getProjectConfigurations() const; @@ -67,53 +67,53 @@ private: QString getBuildDir() const; /** - * @brief Return include paths from the dialog control. - * @return List of include paths. - */ + * @brief Return include paths from the dialog control. + * @return List of include paths. + */ QStringList getIncludePaths() const; /** - * @brief Return define names from the dialog control. - * @return List of define names. - */ + * @brief Return define names from the dialog control. + * @return List of define names. + */ QStringList getDefines() const; /** - * @brief Return undefine names from the dialog control. - * @return List of undefine names. - */ + * @brief Return undefine names from the dialog control. + * @return List of undefine names. + */ QStringList getUndefines() const; /** - * @brief Return check paths from the dialog control. - * @return List of check paths. - */ + * @brief Return check paths from the dialog control. + * @return List of check paths. + */ QStringList getCheckPaths() const; /** - * @brief Return excluded paths from the dialog control. - * @return List of excluded paths. - */ + * @brief Return excluded paths from the dialog control. + * @return List of excluded paths. + */ QStringList getExcludedPaths() const; /** - * @brief Return selected libraries from the dialog control. - * @return List of libraries. - */ + * @brief Return selected libraries from the dialog control. + * @return List of libraries. + */ QStringList getLibraries() const; /** - * @brief Return suppressions from the dialog control. - * @return List of suppressions. - */ + * @brief Return suppressions from the dialog control. + * @return List of suppressions. + */ QList getSuppressions() const { return mSuppressions; } /** - * @brief Set project root path to dialog control. - * @param root Project root path to set to dialog control. - */ + * @brief Set project root path to dialog control. + * @param root Project root path to set to dialog control. + */ void setRootPath(const QString &root); /** Set build dir */ @@ -122,51 +122,51 @@ private: void setImportProject(const QString &importProject); /** - * @brief Set include paths to dialog control. - * @param includes List of include paths to set to dialog control. - */ + * @brief Set include paths to dialog control. + * @param includes List of include paths to set to dialog control. + */ void setIncludepaths(const QStringList &includes); /** - * @brief Set define names to dialog control. - * @param defines List of define names to set to dialog control. - */ + * @brief Set define names to dialog control. + * @param defines List of define names to set to dialog control. + */ void setDefines(const QStringList &defines); /** - * @brief Set undefine names to dialog control. - * @param undefines List of undefine names to set to dialog control. - */ + * @brief Set undefine names to dialog control. + * @param undefines List of undefine names to set to dialog control. + */ void setUndefines(const QStringList &undefines); /** - * @brief Set check paths to dialog control. - * @param paths List of path names to set to dialog control. - */ + * @brief Set check paths to dialog control. + * @param paths List of path names to set to dialog control. + */ void setCheckPaths(const QStringList &paths); /** - * @brief Set excluded paths to dialog control. - * @param paths List of path names to set to dialog control. - */ + * @brief Set excluded paths to dialog control. + * @param paths List of path names to set to dialog control. + */ void setExcludedPaths(const QStringList &paths); /** - * @brief Set libraries to dialog control. - * @param libraries List of libraries to set to dialog control. - */ + * @brief Set libraries to dialog control. + * @param libraries List of libraries to set to dialog control. + */ void setLibraries(const QStringList &libraries); /** - * @brief Add a single suppression to dialog control. - * @param suppression A suppressions to add to dialog control. - */ + * @brief Add a single suppression to dialog control. + * @param suppression A suppressions to add to dialog control. + */ void addSingleSuppression(const Suppressions::Suppression &suppression); /** - * @brief Set suppressions to dialog control. - * @param suppressions List of suppressions to set to dialog control. - */ + * @brief Set suppressions to dialog control. + * @param suppressions List of suppressions to set to dialog control. + */ void setSuppressions(const QList &suppressions); protected slots: @@ -175,89 +175,89 @@ protected slots: void ok(); /** - * @brief Browse for build dir. - */ + * @brief Browse for build dir. + */ void browseBuildDir(); /** - * @brief Clear 'import project'. - */ + * @brief Clear 'import project'. + */ void clearImportProject(); /** - * @brief Browse for solution / project / compile database. - */ + * @brief Browse for solution / project / compile database. + */ void browseImportProject(); /** - * @brief Add new path to check. - */ + * @brief Add new path to check. + */ void addCheckPath(); /** - * @brief Edit path in the list. - */ + * @brief Edit path in the list. + */ void editCheckPath(); /** - * @brief Remove path from the list. - */ + * @brief Remove path from the list. + */ void removeCheckPath(); /** - * @brief Browse for include directory. - * Allow user to add new include directory to the list. - */ + * @brief Browse for include directory. + * Allow user to add new include directory to the list. + */ void addIncludeDir(); /** - * @brief Remove include directory from the list. - */ + * @brief Remove include directory from the list. + */ void removeIncludeDir(); /** - * @brief Edit include directory in the list. - */ + * @brief Edit include directory in the list. + */ void editIncludeDir(); /** - * @brief Add new path to exclude list. - */ + * @brief Add new path to exclude list. + */ void addExcludePath(); /** - * @brief Add new file to exclude list. - */ + * @brief Add new file to exclude list. + */ void addExcludeFile(); /** - * @brief Edit excluded path in the list. - */ + * @brief Edit excluded path in the list. + */ void editExcludePath(); /** - * @brief Remove excluded path from the list. - */ + * @brief Remove excluded path from the list. + */ void removeExcludePath(); /** - * @brief Move include path up in the list. - */ + * @brief Move include path up in the list. + */ void moveIncludePathUp(); /** - * @brief Move include path down in the list. - */ + * @brief Move include path down in the list. + */ void moveIncludePathDown(); /** - * @brief Add suppression to the list - */ + * @brief Add suppression to the list + */ void addSuppression(); /** - * @brief Remove selected suppression from the list - */ + * @brief Remove selected suppression from the list + */ void removeSuppression(); /** @@ -288,21 +288,21 @@ protected: void saveSettings() const; /** - * @brief Add new indlude directory. - * @param dir Directory to add. - */ + * @brief Add new indlude directory. + * @param dir Directory to add. + */ void addIncludeDir(const QString &dir); /** - * @brief Add new path to check. - * @param path Path to add. - */ + * @brief Add new path to check. + * @param path Path to add. + */ void addCheckPath(const QString &path); /** - * @brief Add new path to ignore list. - * @param path Path to add. - */ + * @brief Add new path to ignore list. + * @param path Path to add. + */ void addExcludePath(const QString &path); /** diff --git a/gui/report.cpp b/gui/report.cpp index b4e252f3c..9a2eb223b 100644 --- a/gui/report.cpp +++ b/gui/report.cpp @@ -21,8 +21,7 @@ Report::Report(const QString &filename) : QObject(), mFilename(filename) -{ -} +{} Report::~Report() { diff --git a/gui/report.h b/gui/report.h index 80acad73d..2ffaf8b2e 100644 --- a/gui/report.h +++ b/gui/report.h @@ -29,8 +29,8 @@ class ErrorItem; /// @{ /** -* @brief A base class for reports. -*/ + * @brief A base class for reports. + */ class Report : public QObject { public: enum Type { @@ -43,55 +43,55 @@ public: virtual ~Report(); /** - * @brief Create the report (file). - * @return true if succeeded, false if file could not be created. - */ + * @brief Create the report (file). + * @return true if succeeded, false if file could not be created. + */ virtual bool create(); /** - * @brief Open the existing report (file). - * @return true if succeeded, false if file could not be created. - */ + * @brief Open the existing report (file). + * @return true if succeeded, false if file could not be created. + */ virtual bool open(); /** - * @brief Close the report (file). - */ + * @brief Close the report (file). + */ void close(); /** - * @brief Write report header. - */ + * @brief Write report header. + */ virtual void writeHeader() = 0; /** - * @brief Write report footer. - */ + * @brief Write report footer. + */ virtual void writeFooter() = 0; /** - * @brief Write error to report. - * @param error Error data. - */ + * @brief Write error to report. + * @param error Error data. + */ virtual void writeError(const ErrorItem &error) = 0; protected: /** - * @brief Get the file object where the report is written to. - */ + * @brief Get the file object where the report is written to. + */ QFile* getFile(); private: /** - * @brief Filename of the report. - */ + * @brief Filename of the report. + */ QString mFilename; /** - * @brief Fileobject for the report file. - */ + * @brief Fileobject for the report file. + */ QFile mFile; }; /// @} diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp index 5ca374f04..43f36f45c 100644 --- a/gui/resultstree.cpp +++ b/gui/resultstree.cpp @@ -98,8 +98,7 @@ ResultsTree::ResultsTree(QWidget * parent) : } ResultsTree::~ResultsTree() -{ -} +{} void ResultsTree::keyPressEvent(QKeyEvent *event) { @@ -198,10 +197,10 @@ bool ResultsTree::addErrorItem(const ErrorItem &item) //file item as a parent QStandardItem* fileItem = ensureFileItem(loc.file, item.file0, hide); QStandardItem* stditem = addBacktraceFiles(fileItem, - line, - hide, - severityToIcon(line.severity), - false); + line, + hide, + severityToIcon(line.severity), + false); if (!stditem) return false; @@ -269,10 +268,10 @@ bool ResultsTree::addErrorItem(const ErrorItem &item) } QStandardItem *ResultsTree::addBacktraceFiles(QStandardItem *parent, - const ErrorLine &item, - const bool hide, - const QString &icon, - bool childOfMessage) + const ErrorLine &item, + const bool hide, + const QString &icon, + bool childOfMessage) { if (!parent) { return nullptr; @@ -864,8 +863,8 @@ QString ResultsTree::askFileDir(const QString &file) msgbox.exec(); QString dir = QFileDialog::getExistingDirectory(this, title, - getPath(SETTINGS_LAST_SOURCE_PATH), - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + getPath(SETTINGS_LAST_SOURCE_PATH), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); if (dir.isEmpty()) return QString(); diff --git a/gui/resultstree.h b/gui/resultstree.h index c52ff2a7b..0e32f4944 100644 --- a/gui/resultstree.h +++ b/gui/resultstree.h @@ -41,9 +41,9 @@ class QSettings; /** -* @brief Cppcheck's results are shown in this tree -* -*/ + * @brief Cppcheck's results are shown in this tree + * + */ class ResultsTree : public QTreeView { Q_OBJECT public: @@ -52,16 +52,16 @@ public: void initialize(QSettings *settings, ApplicationList *list, ThreadHandler *checkThreadHandler); /** - * @brief Add a new item to the tree - * - * @param item Error item data - */ + * @brief Add a new item to the tree + * + * @param item Error item data + */ bool addErrorItem(const ErrorItem &item); /** - * @brief Clear all errors from the tree - * - */ + * @brief Clear all errors from the tree + * + */ void clear(); /** @@ -75,28 +75,28 @@ public: void clearRecheckFile(const QString &filename); /** - * @brief Function to filter the displayed list of errors. - * Refreshes the tree. - * - * @param filter String that must be found in the summary, description, file or id - */ + * @brief Function to filter the displayed list of errors. + * Refreshes the tree. + * + * @param filter String that must be found in the summary, description, file or id + */ void filterResults(const QString& filter); /** - * @brief Function to show results that were previous hidden with HideResult() - */ + * @brief Function to show results that were previous hidden with HideResult() + */ void showHiddenResults(); /** - * @brief Refresh tree by checking which of the items should be shown - * and which should be hidden - */ + * @brief Refresh tree by checking which of the items should be shown + * and which should be hidden + */ void refreshTree(); /** - * @brief Save results to a text stream - * - */ + * @brief Save results to a text stream + * + */ void saveResults(Report *report) const; /** @@ -105,69 +105,69 @@ public: void updateFromOldReport(const QString &filename); /** - * @brief Update tree settings - * - * @param showFullPath Show full path of files in the tree - * @param saveFullPath Save full path of files in reports - * @param saveAllErrors Save all visible errors - * @param showErrorId Show error id - * @param showInconclusive Show inconclusive column - */ + * @brief Update tree settings + * + * @param showFullPath Show full path of files in the tree + * @param saveFullPath Save full path of files in reports + * @param saveAllErrors Save all visible errors + * @param showErrorId Show error id + * @param showInconclusive Show inconclusive column + */ void updateSettings(bool showFullPath, bool saveFullPath, bool saveAllErrors, bool showErrorId, bool showInconclusive); /** - * @brief Set the directory we are checking - * - * This is used to split error file path to relative if necessary - * @param dir Directory we are checking - */ + * @brief Set the directory we are checking + * + * This is used to split error file path to relative if necessary + * @param dir Directory we are checking + */ void setCheckDirectory(const QString &dir); /** - * @brief Get the directory we are checking - * - * @return Directory containing source files - */ + * @brief Get the directory we are checking + * + * @return Directory containing source files + */ QString getCheckDirectory(); /** - * @brief Check if there are any visible results in view. - * @return true if there is at least one visible warning/error. - */ + * @brief Check if there are any visible results in view. + * @return true if there is at least one visible warning/error. + */ bool hasVisibleResults() const; /** - * @brief Do we have results from check? - * @return true if there is at least one warning/error, hidden or visible. - */ + * @brief Do we have results from check? + * @return true if there is at least one warning/error, hidden or visible. + */ bool hasResults() const; /** - * @brief Save all settings - * Column widths - */ + * @brief Save all settings + * Column widths + */ void saveSettings() const; /** - * @brief Change all visible texts language - * - */ + * @brief Change all visible texts language + * + */ void translate(); /** - * @brief Show optional column "Id" - */ + * @brief Show optional column "Id" + */ void showIdColumn(bool show); /** - * @brief Show optional column "Inconclusve" - */ + * @brief Show optional column "Inconclusve" + */ void showInconclusiveColumn(bool show); /** - * @brief Returns true if column "Id" is shown - */ + * @brief Returns true if column "Id" is shown + */ bool showIdColumn() const { return mShowErrorId; } @@ -181,24 +181,24 @@ public: signals: /** - * @brief Signal that results have been hidden or shown - * - * @param hidden true if there are some hidden results, or false if there are not - */ + * @brief Signal that results have been hidden or shown + * + * @param hidden true if there are some hidden results, or false if there are not + */ void resultsHidden(bool hidden); /** - * @brief Signal to perform selected files recheck - * - * @param selectedItems list of selected files - */ + * @brief Signal to perform selected files recheck + * + * @param selectedItems list of selected files + */ void checkSelected(QStringList selectedItems); /** - * @brief Signal for selection change in result tree. - * - * @param current Model index to specify new selected item. - */ + * @brief Signal for selection change in result tree. + * + * @param current Model index to specify new selected item. + */ void treeSelectionChanged(const QModelIndex ¤t); /** Suppress Ids */ @@ -209,67 +209,67 @@ signals: public slots: /** - * @brief Function to show/hide certain type of errors - * Refreshes the tree. - * - * @param type Type of error to show/hide - * @param show Should specified errors be shown (true) or hidden (false) - */ + * @brief Function to show/hide certain type of errors + * Refreshes the tree. + * + * @param type Type of error to show/hide + * @param show Should specified errors be shown (true) or hidden (false) + */ void showResults(ShowTypes::ShowType type, bool show); /** - * @brief Show/hide cppcheck errors. - * Refreshes the tree. - * - * @param show Should specified errors be shown (true) or hidden (false) - */ + * @brief Show/hide cppcheck errors. + * Refreshes the tree. + * + * @param show Should specified errors be shown (true) or hidden (false) + */ void showCppcheckResults(bool show); /** - * @brief Show/hide clang-tidy/clang-analyzer errors. - * Refreshes the tree. - * - * @param show Should specified errors be shown (true) or hidden (false) - */ + * @brief Show/hide clang-tidy/clang-analyzer errors. + * Refreshes the tree. + * + * @param show Should specified errors be shown (true) or hidden (false) + */ void showClangResults(bool show); protected slots: /** - * @brief Slot to quickstart an error with default application - * - * @param index Model index to specify which error item to open - */ + * @brief Slot to quickstart an error with default application + * + * @param index Model index to specify which error item to open + */ void quickStartApplication(const QModelIndex &index); /** - * @brief Slot for context menu item to open an error with specified application - * - * @param application Index of the application to open the error - */ + * @brief Slot for context menu item to open an error with specified application + * + * @param application Index of the application to open the error + */ void context(int application); /** - * @brief Slot for context menu item to copy selection to clipboard - */ + * @brief Slot for context menu item to copy selection to clipboard + */ void copy(); /** - * @brief Slot for context menu item to hide the current error message - * - */ + * @brief Slot for context menu item to hide the current error message + * + */ void hideResult(); /** - * @brief Slot for rechecking selected files - * - */ + * @brief Slot for rechecking selected files + * + */ void recheckSelectedFiles(); /** - * @brief Slot for context menu item to hide all messages with the current message Id - * - */ + * @brief Slot for context menu item to hide all messages with the current message Id + * + */ void hideAllIdResult(); /** Slot for context menu item to suppress all messages with the current message id */ @@ -279,8 +279,8 @@ protected slots: void suppressHash(); /** - * @brief Slot for context menu item to open the folder containing the current file. - */ + * @brief Slot for context menu item to open the folder containing the current file. + */ void openContainingFolder(); /** @@ -289,94 +289,94 @@ protected slots: void editContract(); /** - * @brief Slot for selection change in the results tree. - * - * @param current Model index to specify new selected item. - * @param previous Model index to specify previous selected item. - */ + * @brief Slot for selection change in the results tree. + * + * @param current Model index to specify new selected item. + * @param previous Model index to specify previous selected item. + */ virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); protected: /** - * @brief Hides/shows full file path on all error file items according to mShowFullPath - * - */ + * @brief Hides/shows full file path on all error file items according to mShowFullPath + * + */ void refreshFilePaths(); /** - * @brief Hides/shows full file path on all error file items according to mShowFullPath - * @param item Parent item whose children's paths to change - */ + * @brief Hides/shows full file path on all error file items according to mShowFullPath + * @param item Parent item whose children's paths to change + */ void refreshFilePaths(QStandardItem *item); /** - * @brief Removes checking directory from given path if mShowFullPath is false - * - * @param path Path to remove checking directory - * @param saving are we saving? Check mSaveFullPath instead - * @return Path that has checking directory removed - */ + * @brief Removes checking directory from given path if mShowFullPath is false + * + * @param path Path to remove checking directory + * @param saving are we saving? Check mSaveFullPath instead + * @return Path that has checking directory removed + */ QString stripPath(const QString &path, bool saving) const; /** - * @brief Save all errors under specified item - * @param report Report that errors are saved to - * @param fileItem Item whose errors to save - */ + * @brief Save all errors under specified item + * @param report Report that errors are saved to + * @param fileItem Item whose errors to save + */ void saveErrors(Report *report, const QStandardItem *fileItem) const; /** - * @brief Convert a severity string to a icon filename - * - * @param severity Severity - */ + * @brief Convert a severity string to a icon filename + * + * @param severity Severity + */ QString severityToIcon(Severity::SeverityType severity) const; /** - * @brief Helper function to open an error within target with application* - * - * @param target Error tree item to open - * @param application Index of the application to open with. Giving -1 - * (default value) will open the default application. - */ + * @brief Helper function to open an error within target with application* + * + * @param target Error tree item to open + * @param application Index of the application to open with. Giving -1 + * (default value) will open the default application. + */ void startApplication(QStandardItem *target, int application = -1); /** - * @brief Helper function to copy filename/full path to the clipboard - * - * @param target Error tree item to open - * @param fullPath Are we copying full path or only filename? - */ + * @brief Helper function to copy filename/full path to the clipboard + * + * @param target Error tree item to open + * @param fullPath Are we copying full path or only filename? + */ void copyPathToClipboard(QStandardItem *target, bool fullPath); /** - * @brief Helper function returning the filename/full path of the error tree item \a target. - * - * @param target The error tree item containing the filename/full path - * @param fullPath Whether or not to retrieve the full path or only the filename. - */ + * @brief Helper function returning the filename/full path of the error tree item \a target. + * + * @param target The error tree item containing the filename/full path + * @param fullPath Whether or not to retrieve the full path or only the filename. + */ QString getFilePath(QStandardItem *target, bool fullPath); /** - * @brief Context menu event (user right clicked on the tree) - * - * @param e Event - */ + * @brief Context menu event (user right clicked on the tree) + * + * @param e Event + */ void contextMenuEvent(QContextMenuEvent * e); /** - * @brief Add a new error item beneath a file or a backtrace item beneath an error - * - * @param parent Parent for the item. Either a file item or an error item - * @param item Error line data - * @param hide Should this be hidden (true) or shown (false) - * @param icon Should a default backtrace item icon be added - * @param childOfMessage Is this a child element of a message? - * @return newly created QStandardItem * - */ + * @brief Add a new error item beneath a file or a backtrace item beneath an error + * + * @param parent Parent for the item. Either a file item or an error item + * @param item Error line data + * @param hide Should this be hidden (true) or shown (false) + * @param icon Should a default backtrace item icon be added + * @param childOfMessage Is this a child element of a message? + * @return newly created QStandardItem * + */ QStandardItem *addBacktraceFiles(QStandardItem *parent, const ErrorLine &item, const bool hide, @@ -384,135 +384,135 @@ protected: bool childOfMessage); /** - * @brief Convert Severity to translated string for GUI. - * @param severity Severity to convert - * @return Severity as translated string - */ + * @brief Convert Severity to translated string for GUI. + * @param severity Severity to convert + * @return Severity as translated string + */ static QString severityToTranslatedString(Severity::SeverityType severity); /** - * @brief Load all settings - * Column widths - */ + * @brief Load all settings + * Column widths + */ void loadSettings(); /** - * @brief Ask directory where file is located. - * @param file File name. - * @return Directory user chose. - */ + * @brief Ask directory where file is located. + * @param file File name. + * @return Directory user chose. + */ QString askFileDir(const QString &file); /** - * @brief Create new normal item. - * - * Normal item has left alignment and text set also as tooltip. - * @param name name for the item - * @return new QStandardItem - */ + * @brief Create new normal item. + * + * Normal item has left alignment and text set also as tooltip. + * @param name name for the item + * @return new QStandardItem + */ static QStandardItem *createNormalItem(const QString &name); /** - * @brief Create new normal item. - * - * Normal item has left alignment and text set also as tooltip. - * @param checked checked - * @return new QStandardItem - */ + * @brief Create new normal item. + * + * Normal item has left alignment and text set also as tooltip. + * @param checked checked + * @return new QStandardItem + */ static QStandardItem *createCheckboxItem(bool checked); /** - * @brief Create new line number item. - * - * Line number item has right align and text set as tooltip. - * @param linenumber name for the item - * @return new QStandardItem - */ + * @brief Create new line number item. + * + * Line number item has right align and text set as tooltip. + * @param linenumber name for the item + * @return new QStandardItem + */ static QStandardItem *createLineNumberItem(const QString &linenumber); /** - * @brief Finds a file item - * - * @param name name of the file item to find - * @return pointer to file item or null if none found - */ + * @brief Finds a file item + * + * @param name name of the file item to find + * @return pointer to file item or null if none found + */ QStandardItem *findFileItem(const QString &name) const; /** - * @brief Ensures there's a item in the model for the specified file - * - * @param fullpath Full path to the file item. - * @param file0 Source file - * @param hide is the error (we want this file item for) hidden? - * @return QStandardItem to be used as a parent for all errors for specified file - */ + * @brief Ensures there's a item in the model for the specified file + * + * @param fullpath Full path to the file item. + * @param file0 Source file + * @param hide is the error (we want this file item for) hidden? + * @return QStandardItem to be used as a parent for all errors for specified file + */ QStandardItem *ensureFileItem(const QString &fullpath, const QString &file0, bool hide); /** - * @brief Item model for tree - * - */ + * @brief Item model for tree + * + */ QStandardItemModel mModel; /** - * @brief Program settings - * - */ + * @brief Program settings + * + */ QSettings *mSettings; /** - * @brief A string used to filter the results for display. - * - */ + * @brief A string used to filter the results for display. + * + */ QString mFilter; /** - * @brief List of applications to open errors with - * - */ + * @brief List of applications to open errors with + * + */ ApplicationList *mApplications; /** - * @brief Right clicked item (used by context menu slots) - * - */ + * @brief Right clicked item (used by context menu slots) + * + */ QStandardItem *mContextItem; /** - * @brief Should full path of files be shown (true) or relative (false) - * - */ + * @brief Should full path of files be shown (true) or relative (false) + * + */ bool mShowFullPath; /** - * @brief Should full path of files be saved - * - */ + * @brief Should full path of files be saved + * + */ bool mSaveFullPath; /** - * @brief Save all errors (true) or only visible (false) - * - */ + * @brief Save all errors (true) or only visible (false) + * + */ bool mSaveAllErrors; /** - * @brief true if optional column "Id" is shown - * - */ + * @brief true if optional column "Id" is shown + * + */ bool mShowErrorId; /** - * @brief Path we are currently checking - * - */ + * @brief Path we are currently checking + * + */ QString mCheckPath; /** - * @brief Are there any visible errors - * - */ + * @brief Are there any visible errors + * + */ bool mVisibleErrors; private: diff --git a/gui/resultsview.cpp b/gui/resultsview.cpp index cfb4ad3c7..8470258a0 100644 --- a/gui/resultsview.cpp +++ b/gui/resultsview.cpp @@ -328,7 +328,7 @@ void ResultsView::checkingFinished() msg.exec(); } //If we have errors but they aren't visible, tell user about it else if (!mUI.mTree->hasVisibleResults()) { - QString text = tr("Errors were found, but they are configured to be hidden.\n"\ + QString text = tr("Errors were found, but they are configured to be hidden.\n" \ "To toggle what kind of errors are shown, open view menu."); QMessageBox msg(QMessageBox::Information, tr("Cppcheck"), diff --git a/gui/resultsview.h b/gui/resultsview.h index 0339ff58f..41b53e8eb 100644 --- a/gui/resultsview.h +++ b/gui/resultsview.h @@ -36,9 +36,9 @@ class CheckStatistics; /// @{ /** -* @brief Widget to show cppcheck progressbar and result -* -*/ + * @brief Widget to show cppcheck progressbar and result + * + */ class ResultsView : public QWidget { Q_OBJECT public: @@ -72,18 +72,18 @@ public: void clearContracts(); /** - * @brief Write statistics in file - * - * @param filename Filename to save statistics to - */ + * @brief Write statistics in file + * + * @param filename Filename to save statistics to + */ void saveStatistics(const QString &filename) const; /** - * @brief Save results to a file - * - * @param filename Filename to save results to - * @param type Type of the report. - */ + * @brief Save results to a file + * + * @param filename Filename to save results to + * @param type Type of the report. + */ void save(const QString &filename, Report::Type type) const; /** @@ -92,15 +92,15 @@ public: void updateFromOldReport(const QString &filename) const; /** - * @brief Update tree settings - * - * @param showFullPath Show full path of files in the tree - * @param saveFullPath Save full path of files in reports - * @param saveAllErrors Save all visible errors - * @param showNoErrorsMessage Show "no errors"? - * @param showErrorId Show error id? - * @param showInconclusive Show inconclusive? - */ + * @brief Update tree settings + * + * @param showFullPath Show full path of files in the tree + * @param saveFullPath Save full path of files in reports + * @param saveAllErrors Save all visible errors + * @param showNoErrorsMessage Show "no errors"? + * @param showErrorId Show error id? + * @param showInconclusive Show inconclusive? + */ void updateSettings(bool showFullPath, bool saveFullPath, bool saveAllErrors, @@ -119,68 +119,68 @@ public: void updateStyleSetting(QSettings *settings); /** - * @brief Set the directory we are checking - * - * This is used to split error file path to relative if necessary - * @param dir Directory we are checking - */ + * @brief Set the directory we are checking + * + * This is used to split error file path to relative if necessary + * @param dir Directory we are checking + */ void setCheckDirectory(const QString &dir); /** - * @brief Get the directory we are checking - * - * @return Directory containing source files - */ + * @brief Get the directory we are checking + * + * @return Directory containing source files + */ QString getCheckDirectory(); /** - * @brief Inform the view that checking has started - * - * @param count Count of files to be checked. - */ + * @brief Inform the view that checking has started + * + * @param count Count of files to be checked. + */ void checkingStarted(int count); /** - * @brief Inform the view that checking finished. - * - */ + * @brief Inform the view that checking finished. + * + */ void checkingFinished(); /** - * @brief Do we have visible results to show? - * - * @return true if there is at least one warning/error to show. - */ + * @brief Do we have visible results to show? + * + * @return true if there is at least one warning/error to show. + */ bool hasVisibleResults() const; /** - * @brief Do we have results from check? - * - * @return true if there is at least one warning/error, hidden or visible. - */ + * @brief Do we have results from check? + * + * @return true if there is at least one warning/error, hidden or visible. + */ bool hasResults() const; /** - * @brief Save View's settings - * - * @param settings program settings. - */ + * @brief Save View's settings + * + * @param settings program settings. + */ void saveSettings(QSettings *settings); /** - * @brief Translate this view - * - */ + * @brief Translate this view + * + */ void translate(); void disableProgressbar(); /** - * @brief Read errors from report XML file. - * @param filename Report file to read. - * - */ + * @brief Read errors from report XML file. + * @param filename Report file to read. + * + */ void readErrorsXml(const QString &filename); /** @@ -205,23 +205,23 @@ public: signals: /** - * @brief Signal to be emitted when we have results - * - */ + * @brief Signal to be emitted when we have results + * + */ void gotResults(); /** - * @brief Signal that results have been hidden or shown - * - * @param hidden true if there are some hidden results, or false if there are not - */ + * @brief Signal that results have been hidden or shown + * + * @param hidden true if there are some hidden results, or false if there are not + */ void resultsHidden(bool hidden); /** - * @brief Signal to perform recheck of selected files - * - * @param selectedFilesList list of selected files - */ + * @brief Signal to perform recheck of selected files + * + * @param selectedFilesList list of selected files + */ void checkSelected(QStringList selectedFilesList); /** Suppress Ids */ @@ -240,88 +240,88 @@ signals: void deleteVariableContract(QString var); /** - * @brief Show/hide certain type of errors - * Refreshes the tree. - * - * @param type Type of error to show/hide - * @param show Should specified errors be shown (true) or hidden (false) - */ + * @brief Show/hide certain type of errors + * Refreshes the tree. + * + * @param type Type of error to show/hide + * @param show Should specified errors be shown (true) or hidden (false) + */ void showResults(ShowTypes::ShowType type, bool show); /** - * @brief Show/hide cppcheck errors. - * Refreshes the tree. - * - * @param show Should specified errors be shown (true) or hidden (false) - */ + * @brief Show/hide cppcheck errors. + * Refreshes the tree. + * + * @param show Should specified errors be shown (true) or hidden (false) + */ void showCppcheckResults(bool show); /** - * @brief Show/hide clang-tidy/clang-analyzer errors. - * Refreshes the tree. - * - * @param show Should specified errors be shown (true) or hidden (false) - */ + * @brief Show/hide clang-tidy/clang-analyzer errors. + * Refreshes the tree. + * + * @param show Should specified errors be shown (true) or hidden (false) + */ void showClangResults(bool show); /** - * @brief Collapse all results in the result list. - */ + * @brief Collapse all results in the result list. + */ void collapseAllResults(); /** - * @brief Expand all results in the result list. - */ + * @brief Expand all results in the result list. + */ void expandAllResults(); /** - * @brief Show hidden results in the result list. - */ + * @brief Show hidden results in the result list. + */ void showHiddenResults(); public slots: /** - * @brief Slot for updating the checking progress - * - * @param value Current progress value - * @param description Description to accompany the progress - */ + * @brief Slot for updating the checking progress + * + * @param value Current progress value + * @param description Description to accompany the progress + */ void progress(int value, const QString& description); /** - * @brief Slot for new error to be displayed - * - * @param item Error data - */ + * @brief Slot for new error to be displayed + * + * @param item Error data + */ void error(const ErrorItem &item); /** - * @brief Filters the results in the result list. - */ + * @brief Filters the results in the result list. + */ void filterResults(const QString& filter); /** - * @brief Update detailed message when selected item is changed. - * - * @param index Position of new selected item. - */ + * @brief Update detailed message when selected item is changed. + * + * @param index Position of new selected item. + */ void updateDetails(const QModelIndex &index); /** - * @brief Slot opening a print dialog to print the current report - */ + * @brief Slot opening a print dialog to print the current report + */ void print(); /** - * @brief Slot printing the current report to the printer. - * @param printer The printer used for printing the report. - */ + * @brief Slot printing the current report to the printer. + * @param printer The printer used for printing the report. + */ void print(QPrinter* printer); /** - * @brief Slot opening a print preview dialog - */ + * @brief Slot opening a print preview dialog + */ void printPreview(); /** @@ -364,8 +364,8 @@ public slots: protected: /** - * @brief Should we show a "No errors found dialog" every time no errors were found? - */ + * @brief Should we show a "No errors found dialog" every time no errors were found? + */ bool mShowNoErrorsMessage; Ui::ResultsView mUI; diff --git a/gui/scratchpad.h b/gui/scratchpad.h index 5fb6ae436..d60cd22c9 100644 --- a/gui/scratchpad.h +++ b/gui/scratchpad.h @@ -28,22 +28,22 @@ class MainWindow; /// @{ /** -* @brief A window with a text field that . -*/ + * @brief A window with a text field that . + */ class ScratchPad : public QDialog { Q_OBJECT public: explicit ScratchPad(MainWindow& mainWindow); /** - * @brief Translate dialog - */ + * @brief Translate dialog + */ void translate(); private slots: /** - * @brief Called when check button is clicked. - */ + * @brief Called when check button is clicked. + */ void checkButtonClicked(); private: diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index 44afaaf6a..0a07c73af 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -70,7 +70,7 @@ SettingsDialog::SettingsDialog(ApplicationList *list, mCurrentStyle = new CodeEditorStyle(CodeEditorStyle::loadSettings(&settings)); manageStyleControls(); - connect(mUI.mEditPythonPath, SIGNAL(textEdited(const QString &)), + connect(mUI.mEditPythonPath, SIGNAL(textEdited(const QString&)), this, SLOT(validateEditPythonPath())); connect(mUI.mButtons, &QDialogButtonBox::accepted, this, &SettingsDialog::ok); @@ -83,7 +83,7 @@ SettingsDialog::SettingsDialog(ApplicationList *list, this, SLOT(editApplication())); connect(mUI.mBtnDefaultApplication, SIGNAL(clicked()), this, SLOT(defaultApplication())); - connect(mUI.mListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), + connect(mUI.mListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(editApplication())); connect(mUI.mBtnBrowsePythonPath, &QPushButton::clicked, this, &SettingsDialog::browsePythonPath); @@ -379,8 +379,8 @@ void SettingsDialog::editCodeEditorStyle() void SettingsDialog::browseClangPath() { QString selectedDir = QFileDialog::getExistingDirectory(this, - tr("Select clang path"), - QDir::rootPath()); + tr("Select clang path"), + QDir::rootPath()); if (!selectedDir.isEmpty()) { mUI.mEditClangPath->setText(selectedDir); diff --git a/gui/settingsdialog.h b/gui/settingsdialog.h index be65af159..67be4e137 100644 --- a/gui/settingsdialog.h +++ b/gui/settingsdialog.h @@ -33,9 +33,9 @@ class CodeEditorStyle; /// @{ /** -* @brief Settings dialog -* -*/ + * @brief Settings dialog + * + */ class SettingsDialog : public QDialog { Q_OBJECT public: @@ -47,87 +47,87 @@ public: SettingsDialog &operator=(const SettingsDialog &) = delete; /** - * @brief Save all values to QSettings - * - */ + * @brief Save all values to QSettings + * + */ void saveSettingValues() const; /** - * @brief Get checkbox value for mShowFullPath - * - * @return should full path of errors be shown in the tree - */ + * @brief Get checkbox value for mShowFullPath + * + * @return should full path of errors be shown in the tree + */ bool showFullPath() const; /** - * @brief Get checkbox value for mSaveFullPath - * - * @return should full path of files be saved when creating a report - */ + * @brief Get checkbox value for mSaveFullPath + * + * @return should full path of files be saved when creating a report + */ bool saveFullPath() const; /** - * @brief Get checkbox value for mNoErrorsMessage - * - * @return Should "no errors message" be hidden - */ + * @brief Get checkbox value for mNoErrorsMessage + * + * @return Should "no errors message" be hidden + */ bool showNoErrorsMessage() const; /** - * @brief Get checkbox value for mShowIdColumn - * - * @return Should error id column be displayed - */ + * @brief Get checkbox value for mShowIdColumn + * + * @return Should error id column be displayed + */ bool showErrorId() const; /** - * @brief Get checkbox value for mEnableInconclusive - * - * @return Should inconclusive column be displayed - */ + * @brief Get checkbox value for mEnableInconclusive + * + * @return Should inconclusive column be displayed + */ bool showInconclusive() const; /** - * @brief Get checkbox value for mSaveAllErrors - * - * @return should all errors be saved to report - */ + * @brief Get checkbox value for mSaveAllErrors + * + * @return should all errors be saved to report + */ bool saveAllErrors() const; protected slots: /** - * @brief Slot for clicking OK. - * - */ + * @brief Slot for clicking OK. + * + */ void ok(); /** @brief Slot for validating input value in @c editPythonPath */ void validateEditPythonPath(); /** - * @brief Slot for adding a new application to the list - * - */ + * @brief Slot for adding a new application to the list + * + */ void addApplication(); /** - * @brief Slot for deleting an application from the list - * - */ + * @brief Slot for deleting an application from the list + * + */ void removeApplication(); /** - * @brief Slot for modifying an application in the list - * - */ + * @brief Slot for modifying an application in the list + * + */ void editApplication(); /** - * @brief Slot for making the selected application as the default (first) - * - */ + * @brief Slot for making the selected application as the default (first) + * + */ void defaultApplication(); /** @brief Slot for browsing for the python binary */ @@ -153,22 +153,22 @@ protected slots: protected: /** - * @brief Clear all applications from the list and re insert them from mTempApplications - * - */ + * @brief Clear all applications from the list and re insert them from mTempApplications + * + */ void populateApplicationList(); /** - * @brief Load saved values - * Loads dialog size and column widths. - * - */ + * @brief Load saved values + * Loads dialog size and column widths. + * + */ void loadSettings(); /** - * @brief Save settings - * Save dialog size and column widths. - */ + * @brief Save settings + * Save dialog size and column widths. + */ void saveSettings() const; /** @@ -181,24 +181,24 @@ protected: static void saveCheckboxValue(QSettings *settings, QCheckBox *box, const QString &name); /** - * @brief Convert bool to Qt::CheckState - * - * @param yes value to convert - * @return value converted to Qt::CheckState - */ + * @brief Convert bool to Qt::CheckState + * + * @param yes value to convert + * @return value converted to Qt::CheckState + */ static Qt::CheckState boolToCheckState(bool yes); /** - * @brief Converts Qt::CheckState to bool - * - * @param state Qt::CheckState to convert - * @return converted value - */ + * @brief Converts Qt::CheckState to bool + * + * @param state Qt::CheckState to convert + * @return converted value + */ static bool checkStateToBool(Qt::CheckState state); /** - * @brief Populate the translations list. - */ + * @brief Populate the translations list. + */ void initTranslationsList(); /** @@ -207,28 +207,28 @@ protected: CodeEditorStyle *mCurrentStyle; /** - * @brief List of applications user has specified - * - */ + * @brief List of applications user has specified + * + */ ApplicationList *mApplications; /** - * @brief Temporary list of applications - * This will be copied to actual list of applications (mApplications) - * when user clicks ok. - */ + * @brief Temporary list of applications + * This will be copied to actual list of applications (mApplications) + * when user clicks ok. + */ ApplicationList *mTempApplications; /** - * @brief List of translations. - * - */ + * @brief List of translations. + * + */ TranslationHandler *mTranslator; /** - * @brief Dialog from UI designer - * - */ + * @brief Dialog from UI designer + * + */ Ui::Settings mUI; private: void manageStyleControls(); diff --git a/gui/showtypes.h b/gui/showtypes.h index 6e23e6098..fa2edfbec 100644 --- a/gui/showtypes.h +++ b/gui/showtypes.h @@ -27,20 +27,20 @@ /// @{ /** - * @brief A class for different show types we have. - * This class contains enum type for the different show types we have. Each - * show type presents one severity selectable in the GUI. In addition there - * are several supporting functions. - * - * Notice that the "visibility" settings are automatically loaded when the - * class is constructed and saved when the class is destroyed. - */ + * @brief A class for different show types we have. + * This class contains enum type for the different show types we have. Each + * show type presents one severity selectable in the GUI. In addition there + * are several supporting functions. + * + * Notice that the "visibility" settings are automatically loaded when the + * class is constructed and saved when the class is destroyed. + */ class ShowTypes { public: /** - * @brief Show types we have (i.e. severities in the GUI). - */ + * @brief Show types we have (i.e. severities in the GUI). + */ enum ShowType { ShowStyle = 0, ShowWarnings, diff --git a/gui/statsdialog.cpp b/gui/statsdialog.cpp index 1f2ee6d3d..36e223475 100644 --- a/gui/statsdialog.cpp +++ b/gui/statsdialog.cpp @@ -35,7 +35,7 @@ static const QString CPPCHECK("cppcheck"); StatsDialog::StatsDialog(QWidget *parent) : QDialog(parent), - mStatistics(nullptr) + mStatistics(nullptr) { mUI.setupUi(this); @@ -129,13 +129,13 @@ void StatsDialog::setScanDuration(double seconds) void StatsDialog::pdfExport() { const QString Stat = QString( - "

%1 %2

\n" - "

%3 : %4

\n" - "

%5 : %6

\n" - "

%7 : %8

\n" - "

%9 : %10

\n" - "

%11 : %12

\n" - "

%13 : %14

\n") + "

%1 %2

\n" + "

%3 : %4

\n" + "

%5 : %6

\n" + "

%7 : %8

\n" + "

%9 : %10

\n" + "

%11 : %12

\n" + "

%13 : %14

\n") .arg(tr("Statistics")) .arg(QDate::currentDate().toString("dd.MM.yyyy")) .arg(tr("Errors")) @@ -193,13 +193,13 @@ void StatsDialog::copyToClipboard() // Plain text summary const QString settings = QString( - "%1\n" - "\t%2:\t%3\n" - "\t%4:\t%5\n" - "\t%6:\t%7\n" - "\t%8:\t%9\n" - "\t%10:\t%11\n" - ) + "%1\n" + "\t%2:\t%3\n" + "\t%4:\t%5\n" + "\t%6:\t%7\n" + "\t%8:\t%9\n" + "\t%10:\t%11\n" + ) .arg(projSettings) .arg(project) .arg(mUI.mProject->text()) @@ -213,11 +213,11 @@ void StatsDialog::copyToClipboard() .arg(mUI.mUndefines->text()); const QString previous = QString( - "%1\n" - "\t%2:\t%3\n" - "\t%4:\t%5\n" - "\t%6:\t%7\n" - ) + "%1\n" + "\t%2:\t%3\n" + "\t%4:\t%5\n" + "\t%6:\t%7\n" + ) .arg(prevScan) .arg(selPath) .arg(mUI.mPath->text()) @@ -227,14 +227,14 @@ void StatsDialog::copyToClipboard() .arg(mUI.mScanDuration->text()); const QString statistics = QString( - "%1\n" - "\t%2:\t%3\n" - "\t%4:\t%5\n" - "\t%6:\t%7\n" - "\t%8:\t%9\n" - "\t%10:\t%11\n" - "\t%12:\t%13\n" - ) + "%1\n" + "\t%2:\t%3\n" + "\t%4:\t%5\n" + "\t%6:\t%7\n" + "\t%8:\t%9\n" + "\t%10:\t%11\n" + "\t%12:\t%13\n" + ) .arg(stats) .arg(errors) .arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors)) @@ -253,15 +253,15 @@ void StatsDialog::copyToClipboard() // HTML summary const QString htmlSettings = QString( - "

%1

\n" - "\n" - " \n" - " \n" - " \n" - " \n" - " \n" - "
%2:%3
%4:%5
%6:%7
%8:%9
%10:%11
\n" - ) + "

%1

\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
%2:%3
%4:%5
%6:%7
%8:%9
%10:%11
\n" + ) .arg(projSettings) .arg(project) .arg(mUI.mProject->text()) @@ -275,13 +275,13 @@ void StatsDialog::copyToClipboard() .arg(mUI.mUndefines->text()); const QString htmlPrevious = QString( - "

%1

\n" - "\n" - " \n" - " \n" - " \n" - "
%2:%3
%4:%5
%6:%7
\n" - ) + "

%1

\n" + "\n" + " \n" + " \n" + " \n" + "
%2:%3
%4:%5
%6:%7
\n" + ) .arg(prevScan) .arg(selPath) .arg(mUI.mPath->text()) @@ -291,15 +291,15 @@ void StatsDialog::copyToClipboard() .arg(mUI.mScanDuration->text()); const QString htmlStatistics = QString( - "

%1

\n" - " %2:%3\n" - " %4:%5\n" - " %6:%7\n" - " %8:%9\n" - " %10:%11\n" - " %12:%13\n" - "\n" - ) + "

%1

\n" + " %2:%3\n" + " %4:%5\n" + " %6:%7\n" + " %8:%9\n" + " %10:%11\n" + " %12:%13\n" + "\n" + ) .arg(stats) .arg(errors) .arg(mStatistics->getCount(CPPCHECK,ShowTypes::ShowErrors)) diff --git a/gui/statsdialog.h b/gui/statsdialog.h index 03bea3874..3f2dadefc 100644 --- a/gui/statsdialog.h +++ b/gui/statsdialog.h @@ -32,37 +32,37 @@ class CheckStatistics; /// @{ /** -* @brief A dialog that shows project and scan statistics. -* -*/ + * @brief A dialog that shows project and scan statistics. + * + */ class StatsDialog : public QDialog { Q_OBJECT public: explicit StatsDialog(QWidget *parent = nullptr); /** - * @brief Sets the project to extract statistics from - */ + * @brief Sets the project to extract statistics from + */ void setProject(const ProjectFile *projectFile); /** - * @brief Sets the string to display beside "Path Selected:" - */ + * @brief Sets the string to display beside "Path Selected:" + */ void setPathSelected(const QString& path); /** - * @brief Sets the number to display beside "Number of Files Scanned:" - */ + * @brief Sets the number to display beside "Number of Files Scanned:" + */ void setNumberOfFilesScanned(int num); /** - * @brief Sets the number of seconds to display beside "Scan Duration:" - */ + * @brief Sets the number of seconds to display beside "Scan Duration:" + */ void setScanDuration(double seconds); /** - * @brief Sets the numbers of different error/warnings found." - */ + * @brief Sets the numbers of different error/warnings found." + */ void setStatistics(const CheckStatistics *stats); private slots: diff --git a/gui/test/benchmark/simple/benchmarksimple.h b/gui/test/benchmark/simple/benchmarksimple.h index afd29ea8e..ed953ec4d 100644 --- a/gui/test/benchmark/simple/benchmarksimple.h +++ b/gui/test/benchmark/simple/benchmarksimple.h @@ -20,7 +20,7 @@ #include #include "errorlogger.h" -class BenchmarkSimple: public QObject, public ErrorLogger { +class BenchmarkSimple : public QObject, public ErrorLogger { Q_OBJECT private slots: @@ -31,8 +31,6 @@ private slots: private: // Empty implementations of ErrorLogger methods. // We don't care about the output in the benchmark tests. - void reportOut(const std::string & outmsg) override { - } - void reportErr(const ErrorMessage &msg) override { - } + void reportOut(const std::string & outmsg) override {} + void reportErr(const ErrorMessage &msg) override {} }; diff --git a/gui/test/cppchecklibrarydata/testcppchecklibrarydata.h b/gui/test/cppchecklibrarydata/testcppchecklibrarydata.h index 8cee20d7f..91fcb6e71 100644 --- a/gui/test/cppchecklibrarydata/testcppchecklibrarydata.h +++ b/gui/test/cppchecklibrarydata/testcppchecklibrarydata.h @@ -19,7 +19,7 @@ #include #include "cppchecklibrarydata.h" -class TestCppcheckLibraryData: public QObject { +class TestCppcheckLibraryData : public QObject { Q_OBJECT private slots: diff --git a/gui/test/data/benchmark/simple.cpp b/gui/test/data/benchmark/simple.cpp index fda0a38ef..5572a20ca 100644 --- a/gui/test/data/benchmark/simple.cpp +++ b/gui/test/data/benchmark/simple.cpp @@ -60,7 +60,7 @@ void CheckOther::incrementBooleanError(const Token *tok) "incrementboolean", "The use of a variable of type bool with the ++ postfix operator is always true and deprecated by the C++ Standard.\n" "The operand of a postfix increment operator may be of type bool but it is deprecated by C++ Standard (Annex D-1) and the operand is always set to true\n" - ); + ); } //--------------------------------------------------------------------------- @@ -204,7 +204,7 @@ void CheckOther::checkSizeofForNumericParameter() || Token::Match(tok, "sizeof ( - %num% )") || Token::Match(tok, "sizeof %num%") || Token::Match(tok, "sizeof - %num%") - ) { + ) { sizeofForNumericParameterError(tok); } } @@ -292,9 +292,9 @@ void CheckOther::checkRedundantAssignmentInSwitch() } tok2 = endOfConditional; } else - ++ indentLevel; + ++indentLevel; } else if (tok2->str() == "}") { - -- indentLevel; + --indentLevel; // End of the switch block if (indentLevel < 0) @@ -343,7 +343,7 @@ void CheckOther::checkSwitchCaseFallThrough() while (tok) { // Check the contents of the switch statement - std::stack > ifnest; + std::stack> ifnest; std::stack loopnest; std::stack scopenest; bool justbreak = true; @@ -618,14 +618,14 @@ void CheckOther::checkIncorrectLogicOperator() enum Relation { Equal, NotEqual, Less, LessEqual, More, MoreEqual }; struct Condition { const char *before; - Position position1; + Position position1; const char *op1TokStr; const char *op2TokStr; - Position position2; + Position position2; const char *op3TokStr; const char *after; - Relation relation; - bool state; + Relation relation; + bool state; } conditions[] = { { "!!&&", NA, "!=", "||", NA, "!=", "!!&&", NotEqual, true }, // (x != 1) || (x != 3) <- always true { "(", NA, "==", "&&", NA, "==", ")", NotEqual, false }, // (x == 1) && (x == 3) <- always false @@ -669,11 +669,11 @@ void CheckOther::checkIncorrectLogicOperator() if (!Token::Match(nextTok, conditions[i].after)) continue; - if ((conditions[i].relation == Equal && MathLib::isEqual(firstConstant, secondConstant)) || - (conditions[i].relation == NotEqual && MathLib::isNotEqual(firstConstant, secondConstant)) || - (conditions[i].relation == Less && MathLib::isLess(firstConstant, secondConstant)) || + if ((conditions[i].relation == Equal && MathLib::isEqual(firstConstant, secondConstant)) || + (conditions[i].relation == NotEqual && MathLib::isNotEqual(firstConstant, secondConstant)) || + (conditions[i].relation == Less && MathLib::isLess(firstConstant, secondConstant)) || (conditions[i].relation == LessEqual && MathLib::isLessEqual(firstConstant, secondConstant)) || - (conditions[i].relation == More && MathLib::isGreater(firstConstant, secondConstant)) || + (conditions[i].relation == More && MathLib::isGreater(firstConstant, secondConstant)) || (conditions[i].relation == MoreEqual && MathLib::isGreaterEqual(firstConstant, secondConstant))) incorrectLogicOperatorError(term1Tok, conditions[i].state); } @@ -878,7 +878,7 @@ void CheckOther::sizeofForNumericParameterError(const Token *tok) " return sizeof(10);\n" " }\n" " returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 10." - ); + ); } void CheckOther::sizeofForArrayParameterError(const Token *tok) @@ -895,7 +895,7 @@ void CheckOther::sizeofForArrayParameterError(const Token *tok) " }\n" " returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 100 (the " "size of the array in bytes)." - ); + ); } void CheckOther::invalidScanfError(const Token *tok) @@ -984,8 +984,8 @@ void CheckOther::checkMemsetZeroBytes() */ class ScopeInfo { public: - ScopeInfo() : _token(NULL), _parent(NULL) { } - ScopeInfo(const Token *token, ScopeInfo *parent_) : _token(token), _parent(parent_) { } + ScopeInfo() : _token(NULL), _parent(NULL) {} + ScopeInfo(const Token *token, ScopeInfo *parent_) : _token(token), _parent(parent_) {} ~ScopeInfo(); ScopeInfo *parent() { @@ -1053,8 +1053,7 @@ public: _read(read), _write(write), _modified(modified), - _allocateMemory(allocateMemory) { - } + _allocateMemory(allocateMemory) {} /** variable is used.. set both read+write */ void use() { @@ -1446,7 +1445,7 @@ static int doAssignment(Variables &variables, const Token *tok, bool dereference if (addressOf || var2->_type == Variables::array || var2->_type == Variables::pointer) { - bool replace = true; + bool replace = true; // check if variable declared in same scope if (scope == var1->_scope) @@ -1640,7 +1639,7 @@ void CheckOther::functionVariableUsage() while (tok->str() != "{") tok = tok->next(); tok = tok->link(); - if (! tok) + if (!tok) break; } @@ -2253,7 +2252,7 @@ void CheckOther::checkVariableScope() break; } } - if (! tok) + if (!tok) break; } @@ -2268,7 +2267,7 @@ void CheckOther::checkVariableScope() if (indentlevel > 0 && Token::Match(tok, "[{};]")) { // First token of statement.. const Token *tok1 = tok->next(); - if (! tok1) + if (!tok1) continue; if ((tok1->str() == "return") || @@ -2531,7 +2530,7 @@ void CheckOther::checkStructMemberUsage() } } - if (! used) { + if (!used) { unusedStructMemberError(tok->next(), structname, varname); } } @@ -2799,7 +2798,7 @@ void CheckOther::checkMathFunctions() // pow ( x , y) If x is zero, and y is negative --> division by zero else if (tok->varId() == 0 && Token::Match(tok, "pow ( %num% , %num% )") && - MathLib::isNullValue(tok->tokAt(2)->str()) && + MathLib::isNullValue(tok->tokAt(2)->str()) && MathLib::isNegative(tok->tokAt(4)->str())) { mathfunctionCallError(tok, 2); } diff --git a/gui/test/data/files/dir1/dir11/foo11.cpp b/gui/test/data/files/dir1/dir11/foo11.cpp index e4294ad5e..803876e0b 100644 --- a/gui/test/data/files/dir1/dir11/foo11.cpp +++ b/gui/test/data/files/dir1/dir11/foo11.cpp @@ -1 +1 @@ -Dummy test file. +Dummy test file . diff --git a/gui/test/data/files/dir1/foo1.cpp b/gui/test/data/files/dir1/foo1.cpp index e4294ad5e..803876e0b 100644 --- a/gui/test/data/files/dir1/foo1.cpp +++ b/gui/test/data/files/dir1/foo1.cpp @@ -1 +1 @@ -Dummy test file. +Dummy test file . diff --git a/gui/test/data/files/dir2/foo1.cpp b/gui/test/data/files/dir2/foo1.cpp index e4294ad5e..803876e0b 100644 --- a/gui/test/data/files/dir2/foo1.cpp +++ b/gui/test/data/files/dir2/foo1.cpp @@ -1 +1 @@ -Dummy test file. +Dummy test file . diff --git a/gui/test/data/files/foo1.cpp b/gui/test/data/files/foo1.cpp index e4294ad5e..803876e0b 100644 --- a/gui/test/data/files/foo1.cpp +++ b/gui/test/data/files/foo1.cpp @@ -1 +1 @@ -Dummy test file. +Dummy test file . diff --git a/gui/test/data/files/foo4.c b/gui/test/data/files/foo4.c index e4294ad5e..803876e0b 100644 --- a/gui/test/data/files/foo4.c +++ b/gui/test/data/files/foo4.c @@ -1 +1 @@ -Dummy test file. +Dummy test file . diff --git a/gui/test/filelist/testfilelist.cpp b/gui/test/filelist/testfilelist.cpp index 8a790646c..66cd246f9 100644 --- a/gui/test/filelist/testfilelist.cpp +++ b/gui/test/filelist/testfilelist.cpp @@ -109,8 +109,8 @@ void TestFileList::filterFiles() QCOMPARE(files.size(), 5); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); - QVERIFY(! files.contains(base + "/foo1.cpp")); - QVERIFY(! files.contains(base + "/foo3.cpp")); + QVERIFY(!files.contains(base + "/foo1.cpp")); + QVERIFY(!files.contains(base + "/foo3.cpp")); } void TestFileList::filterFiles2() @@ -124,8 +124,8 @@ void TestFileList::filterFiles2() QCOMPARE(files.size(), 5); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); - QVERIFY(! files.contains(base + "/foo1.cpp")); - QVERIFY(! files.contains(base + "/foo3.cpp")); + QVERIFY(!files.contains(base + "/foo1.cpp")); + QVERIFY(!files.contains(base + "/foo3.cpp")); } void TestFileList::filterFiles3() @@ -139,10 +139,10 @@ void TestFileList::filterFiles3() QCOMPARE(files.size(), 6); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); - QVERIFY(! files.contains(base + "/foo1.cpp")); - QVERIFY(! files.contains(base + "/foo3.cpp")); - QVERIFY(! files.contains(base + "/dir1/foo1.cpp")); - QVERIFY(! files.contains(base + "/dir2/foo1.cpp")); + QVERIFY(!files.contains(base + "/foo1.cpp")); + QVERIFY(!files.contains(base + "/foo3.cpp")); + QVERIFY(!files.contains(base + "/dir1/foo1.cpp")); + QVERIFY(!files.contains(base + "/dir2/foo1.cpp")); } void TestFileList::filterFiles4() @@ -156,12 +156,12 @@ void TestFileList::filterFiles4() QCOMPARE(files.size(), 8); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); - QVERIFY(! files.contains(base + "/dir1/foo1.cpp")); - QVERIFY(! files.contains(base + "/dir1/dir11/foo11.cpp")); + QVERIFY(!files.contains(base + "/dir1/foo1.cpp")); + QVERIFY(!files.contains(base + "/dir1/dir11/foo11.cpp")); } /* -void TestFileList::filterFiles5() -{ + void TestFileList::filterFiles5() + { FileList list; QStringList filters; filters << QDir(QString(SRCDIR) + "/../data/files/dir1/").absolutePath() + "/"; @@ -173,6 +173,6 @@ void TestFileList::filterFiles5() QString base = dir.canonicalPath(); QVERIFY(! files.contains(base + "/dir1/foo1.cpp")); QVERIFY(! files.contains(base + "/dir1/dir11/foo11.cpp")); -} -*/ + } + */ QTEST_MAIN(TestFileList) diff --git a/gui/test/filelist/testfilelist.h b/gui/test/filelist/testfilelist.h index c02a3dfb4..f575b8296 100644 --- a/gui/test/filelist/testfilelist.h +++ b/gui/test/filelist/testfilelist.h @@ -19,7 +19,7 @@ #include #include -class TestFileList: public QObject { +class TestFileList : public QObject { Q_OBJECT private slots: diff --git a/gui/test/projectfile/testprojectfile.h b/gui/test/projectfile/testprojectfile.h index dddc5eb71..580c832c2 100644 --- a/gui/test/projectfile/testprojectfile.h +++ b/gui/test/projectfile/testprojectfile.h @@ -19,7 +19,7 @@ #include #include -class TestProjectFile: public QObject { +class TestProjectFile : public QObject { Q_OBJECT private slots: diff --git a/gui/test/translationhandler/testtranslationhandler.h b/gui/test/translationhandler/testtranslationhandler.h index 976bd2b5c..cfabca32a 100644 --- a/gui/test/translationhandler/testtranslationhandler.h +++ b/gui/test/translationhandler/testtranslationhandler.h @@ -19,7 +19,7 @@ #include #include -class TestTranslationHandler: public QObject { +class TestTranslationHandler : public QObject { Q_OBJECT private slots: diff --git a/gui/test/xmlreportv2/testxmlreportv2.h b/gui/test/xmlreportv2/testxmlreportv2.h index 600b5c958..d8e687767 100644 --- a/gui/test/xmlreportv2/testxmlreportv2.h +++ b/gui/test/xmlreportv2/testxmlreportv2.h @@ -19,7 +19,7 @@ #include #include -class TestXmlReportV2: public QObject { +class TestXmlReportV2 : public QObject { Q_OBJECT private slots: diff --git a/gui/threadhandler.h b/gui/threadhandler.h index 2d8f38bd7..90ec68eef 100644 --- a/gui/threadhandler.h +++ b/gui/threadhandler.h @@ -38,9 +38,9 @@ class ImportProject; /** -* @brief This class handles creating threadresult and starting threads -* -*/ + * @brief This class handles creating threadresult and starting threads + * + */ class ThreadHandler : public QObject { Q_OBJECT public: @@ -48,28 +48,28 @@ public: virtual ~ThreadHandler(); /** - * @brief Set the number of threads to use - * @param count The number of threads to use - */ + * @brief Set the number of threads to use + * @param count The number of threads to use + */ void setThreadCount(const int count); /** - * @brief Initialize the threads (connect all signals to resultsview's slots) - * - * @param view View to show error results - */ + * @brief Initialize the threads (connect all signals to resultsview's slots) + * + * @param view View to show error results + */ void initialize(ResultsView *view); /** - * @brief Load settings - * @param settings QSettings to load settings from - */ + * @brief Load settings + * @param settings QSettings to load settings from + */ void loadSettings(const QSettings &settings); /** - * @brief Save settings - * @param settings QSettings to save settings to - */ + * @brief Save settings + * @param settings QSettings to save settings to + */ void saveSettings(QSettings &settings) const; void setAddonsAndTools(const QStringList &addonsAndTools) { @@ -89,72 +89,72 @@ public: } /** - * @brief Clear all files from cppcheck - * - */ + * @brief Clear all files from cppcheck + * + */ void clearFiles(); /** - * @brief Set files to check - * - * @param files files to check - */ + * @brief Set files to check + * + * @param files files to check + */ void setFiles(const QStringList &files); /** - * @brief Set project to check - * - * @param prj project to check - */ + * @brief Set project to check + * + * @param prj project to check + */ void setProject(const ImportProject &prj); /** - * @brief Start the threads to check the files - * - * @param settings Settings for checking - */ + * @brief Start the threads to check the files + * + * @param settings Settings for checking + */ void check(const Settings &settings); /** - * @brief Set files to check - * - * @param all true if all files, false if modified files - */ + * @brief Set files to check + * + * @param all true if all files, false if modified files + */ void setCheckFiles(bool all); /** - * @brief Set selected files to check - * - * @param files list of files to be checked - */ + * @brief Set selected files to check + * + * @param files list of files to be checked + */ void setCheckFiles(const QStringList& files); /** - * @brief Is checking running? - * - * @return true if check is running, false otherwise. - */ + * @brief Is checking running? + * + * @return true if check is running, false otherwise. + */ bool isChecking() const; /** - * @brief Have we checked files already? - * - * @return true check has been previously run and recheck can be done - */ + * @brief Have we checked files already? + * + * @return true check has been previously run and recheck can be done + */ bool hasPreviousFiles() const; /** - * @brief Return count of files we checked last time. - * - * @return count of files that were checked last time. - */ + * @brief Return count of files we checked last time. + * + * @return count of files that were checked last time. + */ int getPreviousFilesCount() const; /** - * @brief Return the time elapsed while scanning the previous time. - * - * @return the time elapsed in milliseconds. - */ + * @brief Return the time elapsed while scanning the previous time. + * + * @return the time elapsed in milliseconds. + */ int getPreviousScanDuration() const; /** @@ -164,24 +164,24 @@ public: QStringList getReCheckFiles(bool all) const; /** - * @brief Get start time of last check - * - * @return start time of last check - */ + * @brief Get start time of last check + * + * @return start time of last check + */ QDateTime getCheckStartTime() const; /** - * @brief Set start time of check - * - * @param checkStartTime saved start time of the last check - */ + * @brief Set start time of check + * + * @param checkStartTime saved start time of the last check + */ void setCheckStartTime(QDateTime checkStartTime); signals: /** - * @brief Signal that all threads are done - * - */ + * @brief Signal that all threads are done + * + */ void done(); void log(const QString &msg); @@ -193,21 +193,21 @@ signals: public slots: /** - * @brief Slot to stop all threads - * - */ + * @brief Slot to stop all threads + * + */ void stop(); protected slots: /** - * @brief Slot that a single thread is done - * - */ + * @brief Slot that a single thread is done + * + */ void threadDone(); protected: /** - * @brief List of files checked last time (used when rechecking) - * - */ + * @brief List of files checked last time (used when rechecking) + * + */ QStringList mLastFiles; /** @brief date and time when current checking started */ @@ -219,39 +219,39 @@ protected: QDateTime mLastCheckTime; /** - * @brief Timer used for measuring scan duration - * - */ + * @brief Timer used for measuring scan duration + * + */ QTime mTime; /** - * @brief The previous scan duration in milliseconds. - * - */ + * @brief The previous scan duration in milliseconds. + * + */ int mScanDuration; /** - * @brief Function to delete all threads - * - */ + * @brief Function to delete all threads + * + */ void removeThreads(); /** - * @brief Thread results are stored here - * - */ + * @brief Thread results are stored here + * + */ ThreadResult mResults; /** - * @brief List of threads currently in use - * - */ + * @brief List of threads currently in use + * + */ QList mThreads; /** - * @brief The amount of threads currently running - * - */ + * @brief The amount of threads currently running + * + */ int mRunningThreadCount; bool mAnalyseWholeProgram; diff --git a/gui/threadresult.cpp b/gui/threadresult.cpp index c108162d8..b2d173e4e 100644 --- a/gui/threadresult.cpp +++ b/gui/threadresult.cpp @@ -43,7 +43,7 @@ void ThreadResult::fileChecked(const QString &file) QMutexLocker locker(&mutex); mProgress += QFile(file).size(); - mFilesChecked ++; + mFilesChecked++; if (mMaxProgress > 0) { const int value = static_cast(PROGRESS_MAX * mProgress / mMaxProgress); diff --git a/gui/threadresult.h b/gui/threadresult.h index c5282075b..63e998516 100644 --- a/gui/threadresult.h +++ b/gui/threadresult.h @@ -33,9 +33,9 @@ class ErrorItem; /// @{ /** -* @brief Threads use this class to obtain new files to process and to publish results -* -*/ + * @brief Threads use this class to obtain new files to process and to publish results + * + */ class ThreadResult : public QObject, public ErrorLogger { Q_OBJECT public: @@ -43,36 +43,36 @@ public: virtual ~ThreadResult(); /** - * @brief Get next unprocessed file - * @return File path - */ + * @brief Get next unprocessed file + * @return File path + */ QString getNextFile(); ImportProject::FileSettings getNextFileSettings(); /** - * @brief Set list of files to check - * @param files List of files to check - */ + * @brief Set list of files to check + * @param files List of files to check + */ void setFiles(const QStringList &files); void setProject(const ImportProject &prj); /** - * @brief Clear files to check - * - */ + * @brief Clear files to check + * + */ void clearFiles(); /** - * @brief Get the number of files to check - * - */ + * @brief Get the number of files to check + * + */ int getFileCount() const; /** - * ErrorLogger methods - */ + * ErrorLogger methods + */ void reportOut(const std::string &outmsg, Color c = Color::Reset) override; void reportErr(const ErrorMessage &msg) override; void bughuntingReport(const std::string &str) override; @@ -80,37 +80,37 @@ public: public slots: /** - * @brief Slot threads use to signal this class that a specific file is checked - * @param file File that is checked - */ + * @brief Slot threads use to signal this class that a specific file is checked + * @param file File that is checked + */ void fileChecked(const QString &file); signals: /** - * @brief Progress signal - * @param value Current progress - * @param description Description of the current stage - */ + * @brief Progress signal + * @param value Current progress + * @param description Description of the current stage + */ void progress(int value, const QString& description); /** - * @brief Signal of a new error - * - * @param item Error data - */ + * @brief Signal of a new error + * + * @param item Error data + */ void error(const ErrorItem &item); /** - * @brief Signal of a new log message - * - * @param logline Log line - */ + * @brief Signal of a new log message + * + * @param logline Log line + */ void log(const QString &logline); /** - * @brief Signal of a debug error - * - * @param item Error data - */ + * @brief Signal of a debug error + * + * @param item Error data + */ void debugError(const ErrorItem &item); /** @brief bug hunting report */ @@ -119,41 +119,41 @@ signals: protected: /** - * @brief Mutex - * - */ + * @brief Mutex + * + */ mutable QMutex mutex; /** - * @brief List of files to check - * - */ + * @brief List of files to check + * + */ QStringList mFiles; std::list mFileSettings; /** - * @brief Max progress - * - */ + * @brief Max progress + * + */ quint64 mMaxProgress; /** - * @brief Current progress - * - */ + * @brief Current progress + * + */ quint64 mProgress; /** - * @brief Current number of files checked - * - */ + * @brief Current number of files checked + * + */ unsigned long mFilesChecked; /** - * @brief Total number of files - * - */ + * @brief Total number of files + * + */ unsigned long mTotalFiles; }; /// @} diff --git a/gui/translationhandler.cpp b/gui/translationhandler.cpp index 5c27eb4ec..5cd30d1e5 100644 --- a/gui/translationhandler.cpp +++ b/gui/translationhandler.cpp @@ -31,12 +31,12 @@ static void unused() { // NOTE: Keeping semi-colons at end of macro for style preference -#if ((QT_VERSION >= 0x040000)&&(QT_VERSION < 0x050000)) +#if ((QT_VERSION >= 0x040000) && (QT_VERSION < 0x050000)) Q_UNUSED(QT_TRANSLATE_NOOP("QDialogButtonBox", "OK")); Q_UNUSED(QT_TRANSLATE_NOOP("QDialogButtonBox", "Cancel")); Q_UNUSED(QT_TRANSLATE_NOOP("QDialogButtonBox", "Close")); Q_UNUSED(QT_TRANSLATE_NOOP("QDialogButtonBox", "Save")); -#elif ((QT_VERSION >= 0x050000)&&(QT_VERSION < 0x060000)) +#elif ((QT_VERSION >= 0x050000) && (QT_VERSION < 0x060000)) Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "OK")); Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Cancel")); Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Close")); @@ -69,8 +69,7 @@ TranslationHandler::TranslationHandler(QObject *parent) : } TranslationHandler::~TranslationHandler() -{ -} +{} const QStringList TranslationHandler::getNames() const { diff --git a/gui/translationhandler.h b/gui/translationhandler.h index b423ace94..ac04df0ab 100644 --- a/gui/translationhandler.h +++ b/gui/translationhandler.h @@ -29,36 +29,36 @@ class QTranslator; /// @{ /** -* @brief Information for one translation. -* -*/ + * @brief Information for one translation. + * + */ struct TranslationInfo { /** - * @brief Readable name for the translation (e.g. "English"). - * - */ + * @brief Readable name for the translation (e.g. "English"). + * + */ QString mName; /** - * @brief Filename for the translation. - * - */ + * @brief Filename for the translation. + * + */ QString mFilename; /** - * @brief ISO 639 language code for the translation (e.g. "en"). - * - */ + * @brief ISO 639 language code for the translation (e.g. "en"). + * + */ QString mCode; }; /** -* @brief A class handling the available translations. -* -* This class contains a list of available translations. The class also keeps -* track which translation is the currently active translation. -* -*/ + * @brief A class handling the available translations. + * + * This class contains a list of available translations. The class also keeps + * track which translation is the currently active translation. + * + */ class TranslationHandler : QObject { Q_OBJECT public: @@ -66,82 +66,82 @@ public: virtual ~TranslationHandler(); /** - * @brief Get a list of available translation names. - * @return List of available translation names. - * - */ + * @brief Get a list of available translation names. + * @return List of available translation names. + * + */ const QStringList getNames() const; /** - * @brief Get a list of available translations. - * @return List of available translations. - * - */ + * @brief Get a list of available translations. + * @return List of available translations. + * + */ QList getTranslations() const { return mTranslations; } /** - * @brief Set active translation. - * @param code ISO 639 language code for new selected translation. - * @return true if succeeds, false otherwise. - * - */ + * @brief Set active translation. + * @param code ISO 639 language code for new selected translation. + * @return true if succeeds, false otherwise. + * + */ bool setLanguage(const QString &code); /** - * @brief Get currently selected translation. - * @return ISO 639 language code for current translation. - * - */ + * @brief Get currently selected translation. + * @return ISO 639 language code for current translation. + * + */ QString getCurrentLanguage() const; /** - * @brief Get translation suggestion for the system. - * This function checks the current system locale and determines which of - * the available translations is best as current translation. If none of - * the available translations is good then it returns English ("en"). - * @return Suggested translation ISO 639 language code. - * - */ + * @brief Get translation suggestion for the system. + * This function checks the current system locale and determines which of + * the available translations is best as current translation. If none of + * the available translations is good then it returns English ("en"). + * @return Suggested translation ISO 639 language code. + * + */ QString suggestLanguage() const; protected: /** - * @brief Add new translation to list of available translations. - * @param name Name of the translation ("English"). - * @param filename Filename of the translation. - * - */ + * @brief Add new translation to list of available translations. + * @param name Name of the translation ("English"). + * @param filename Filename of the translation. + * + */ void addTranslation(const char *name, const char *filename); /** - * @brief Find language in the list and return its index. - * @param code ISO 639 language code. - * @return Index at list, or -1 if not found. - * - */ + * @brief Find language in the list and return its index. + * @param code ISO 639 language code. + * @return Index at list, or -1 if not found. + * + */ int getLanguageIndexByCode(const QString &code) const; private: /** - * @brief ISO 639 language code of the currently selected translation. - * - */ + * @brief ISO 639 language code of the currently selected translation. + * + */ QString mCurrentLanguage; /** - * @brief List of available translations. - * - */ + * @brief List of available translations. + * + */ QList mTranslations; /** - * @brief Translator class instance. - * - */ + * @brief Translator class instance. + * + */ QTranslator *mTranslator; }; diff --git a/gui/txtreport.cpp b/gui/txtreport.cpp index 303d1ba37..65188a9a5 100644 --- a/gui/txtreport.cpp +++ b/gui/txtreport.cpp @@ -23,12 +23,10 @@ TxtReport::TxtReport(const QString &filename) : Report(filename) -{ -} +{} TxtReport::~TxtReport() -{ -} +{} bool TxtReport::create() { @@ -52,9 +50,9 @@ void TxtReport::writeFooter() void TxtReport::writeError(const ErrorItem &error) { /* - Error example from the core program in text - [gui/test.cpp:23] -> [gui/test.cpp:14]: (error) Mismatching allocation and deallocation: k - */ + Error example from the core program in text + [gui/test.cpp:23] -> [gui/test.cpp:14]: (error) Mismatching allocation and deallocation: k + */ QString line; diff --git a/gui/txtreport.h b/gui/txtreport.h index 5ba3e349d..875d93685 100644 --- a/gui/txtreport.h +++ b/gui/txtreport.h @@ -28,9 +28,9 @@ /** -* @brief Text file report. -* This report mimics the output of the command line cppcheck. -*/ + * @brief Text file report. + * This report mimics the output of the command line cppcheck. + */ class TxtReport : public Report { Q_OBJECT @@ -39,32 +39,32 @@ public: virtual ~TxtReport(); /** - * @brief Create the report (file). - * @return true if succeeded, false if file could not be created. - */ + * @brief Create the report (file). + * @return true if succeeded, false if file could not be created. + */ virtual bool create() override; /** - * @brief Write report header. - */ + * @brief Write report header. + */ virtual void writeHeader() override; /** - * @brief Write report footer. - */ + * @brief Write report footer. + */ virtual void writeFooter() override; /** - * @brief Write error to report. - * @param error Error data. - */ + * @brief Write error to report. + * @param error Error data. + */ virtual void writeError(const ErrorItem &error) override; private: /** - * @brief Text stream writer for writing the report in text format. - */ + * @brief Text stream writer for writing the report in text format. + */ QTextStream mTxtWriter; }; /// @} diff --git a/gui/xmlreport.cpp b/gui/xmlreport.cpp index 030340a84..312b23f90 100644 --- a/gui/xmlreport.cpp +++ b/gui/xmlreport.cpp @@ -27,8 +27,7 @@ static const char VersionAttribute[] = "version"; XmlReport::XmlReport(const QString &filename) : Report(filename) -{ -} +{} QString XmlReport::quoteMessage(const QString &message) { diff --git a/gui/xmlreport.h b/gui/xmlreport.h index 813b9d511..988ce52bf 100644 --- a/gui/xmlreport.h +++ b/gui/xmlreport.h @@ -30,8 +30,8 @@ class ErrorItem; /** -* @brief Base class for XML report classes. -*/ + * @brief Base class for XML report classes. + */ class XmlReport : public Report { public: explicit XmlReport(const QString &filename); diff --git a/gui/xmlreportv2.cpp b/gui/xmlreportv2.cpp index e9a8beaa0..66339224d 100644 --- a/gui/xmlreportv2.cpp +++ b/gui/xmlreportv2.cpp @@ -51,8 +51,7 @@ XmlReportV2::XmlReportV2(const QString &filename) : XmlReport(filename), mXmlReader(nullptr), mXmlWriter(nullptr) -{ -} +{} XmlReportV2::~XmlReportV2() { @@ -100,13 +99,13 @@ void XmlReportV2::writeFooter() void XmlReportV2::writeError(const ErrorItem &error) { /* - Error example from the core program in xml - - - - - */ + + + + */ mXmlWriter->writeStartElement(ErrorElementName); mXmlWriter->writeAttribute(IdAttribute, error.errorId); @@ -192,13 +191,13 @@ QList XmlReportV2::read() ErrorItem XmlReportV2::readError(QXmlStreamReader *reader) { /* - Error example from the core program in xml - - - - - */ + + + + */ ErrorItem item; diff --git a/gui/xmlreportv2.h b/gui/xmlreportv2.h index ae3635ae6..edc0d42bc 100644 --- a/gui/xmlreportv2.h +++ b/gui/xmlreportv2.h @@ -30,63 +30,63 @@ class QXmlStreamWriter; /** -* @brief XML file report version 2. -* This report outputs XML-formatted report. The XML format must match command -* line version's XML output. -*/ + * @brief XML file report version 2. + * This report outputs XML-formatted report. The XML format must match command + * line version's XML output. + */ class XmlReportV2 : public XmlReport { public: explicit XmlReportV2(const QString &filename); virtual ~XmlReportV2(); /** - * @brief Create the report (file). - * @return true if succeeded, false if file could not be created. - */ + * @brief Create the report (file). + * @return true if succeeded, false if file could not be created. + */ virtual bool create() override; /** - * @brief Open existing report file. - */ + * @brief Open existing report file. + */ virtual bool open() override; /** - * @brief Write report header. - */ + * @brief Write report header. + */ virtual void writeHeader() override; /** - * @brief Write report footer. - */ + * @brief Write report footer. + */ virtual void writeFooter() override; /** - * @brief Write error to report. - * @param error Error data. - */ + * @brief Write error to report. + * @param error Error data. + */ virtual void writeError(const ErrorItem &error) override; /** - * @brief Read contents of the report file. - */ + * @brief Read contents of the report file. + */ virtual QList read() override; protected: /** - * @brief Read and parse error item from XML stream. - * @param reader XML stream reader to use. - */ + * @brief Read and parse error item from XML stream. + * @param reader XML stream reader to use. + */ ErrorItem readError(QXmlStreamReader *reader); private: /** - * @brief XML stream reader for reading the report in XML format. - */ + * @brief XML stream reader for reading the report in XML format. + */ QXmlStreamReader *mXmlReader; /** - * @brief XML stream writer for writing the report in XML format. - */ + * @brief XML stream writer for writing the report in XML format. + */ QXmlStreamWriter *mXmlWriter; }; /// @} diff --git a/lib/analyzer.h b/lib/analyzer.h index 7eca2facb..d236ed859 100644 --- a/lib/analyzer.h +++ b/lib/analyzer.h @@ -23,7 +23,7 @@ #include class Token; -template +template class ValuePtr; struct Analyzer { @@ -86,7 +86,9 @@ struct Analyzer { return get(Incremental); } - bool isSymbolicMatch() const { return get(SymbolicMatch); } + bool isSymbolicMatch() const { + return get(SymbolicMatch); + } bool matches() const { return get(Match); diff --git a/lib/analyzerinfo.cpp b/lib/analyzerinfo.cpp index e0eb15032..dd068ba55 100644 --- a/lib/analyzerinfo.cpp +++ b/lib/analyzerinfo.cpp @@ -1,20 +1,20 @@ /* -* Cppcheck - A tool for static C/C++ code analysis -* Copyright (C) 2007-2021 Cppcheck team. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2021 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "analyzerinfo.h" diff --git a/lib/analyzerinfo.h b/lib/analyzerinfo.h index b82a0d18c..b5ed8879e 100644 --- a/lib/analyzerinfo.h +++ b/lib/analyzerinfo.h @@ -1,20 +1,20 @@ /* -* Cppcheck - A tool for static C/C++ code analysis -* Copyright (C) 2007-2021 Cppcheck team. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2021 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ //--------------------------------------------------------------------------- #ifndef analyzerinfoH @@ -34,18 +34,18 @@ class ErrorMessage; /// @{ /** -* @brief Analyzer information -* -* Store various analysis information: -* - checksum -* - error messages -* - whole program analysis data -* -* The information can be used for various purposes. It allows: -* - 'make' - only analyze TUs that are changed and generate full report -* - should be possible to add distributed analysis later -* - multi-threaded whole program analysis -*/ + * @brief Analyzer information + * + * Store various analysis information: + * - checksum + * - error messages + * - whole program analysis data + * + * The information can be used for various purposes. It allows: + * - 'make' - only analyze TUs that are changed and generate full report + * - should be possible to add distributed analysis later + * - multi-threaded whole program analysis + */ class CPPCHECKLIB AnalyzerInformation { public: ~AnalyzerInformation(); diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 3e823ddf2..91ff2d724 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -37,7 +37,7 @@ #include #include -template)> +template )> void visitAstNodesGeneric(T *ast, std::function visitor) { std::stack tokens; @@ -344,7 +344,7 @@ static bool hasToken(const Token * startTok, const Token * stopTok, const Token return false; } -template )> +template )> static T* previousBeforeAstLeftmostLeafGeneric(T* tok) { if (!tok) @@ -364,7 +364,7 @@ Token* previousBeforeAstLeftmostLeaf(Token* tok) return previousBeforeAstLeftmostLeafGeneric(tok); } -template )> +template )> static T* nextAfterAstRightmostLeafGeneric(T* tok) { const Token * rightmostLeaf = tok; @@ -474,7 +474,7 @@ bool astIsRHS(const Token* tok) return parent->astOperand2() == tok; } -template )> +template )> static T* getCondTokImpl(T* tok) { if (!tok) @@ -489,7 +489,7 @@ static T* getCondTokImpl(T* tok) return tok->next()->astOperand2(); } -template )> +template )> static T* getCondTokFromEndImpl(T* endBlock) { if (!Token::simpleMatch(endBlock, "}")) @@ -1065,7 +1065,7 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2 return isSameExpression(cpp, macro, refTok1, refTok2, library, pure, followVar, errors); } if (tok1->varId() != tok2->varId() || tok1->str() != tok2->str() || tok1->originalName() != tok2->originalName()) { - if ((Token::Match(tok1,"<|>") && Token::Match(tok2,"<|>")) || + if ((Token::Match(tok1,"<|>") && Token::Match(tok2,"<|>")) || (Token::Match(tok1,"<=|>=") && Token::Match(tok2,"<=|>="))) { return isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), library, pure, followVar, errors) && isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), library, pure, followVar, errors); @@ -1244,10 +1244,10 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token if (!isNot && cond1->str() == "&&" && cond2->str() == "&&") { for (const Token* tok1: { - cond1->astOperand1(), cond1->astOperand2() + cond1->astOperand1(), cond1->astOperand2() }) { for (const Token* tok2: { - cond2->astOperand1(), cond2->astOperand2() + cond2->astOperand1(), cond2->astOperand2() }) { if (isSameExpression(cpp, true, tok1, tok2, library, pure, followVar, errors)) { if (isOppositeCond(isNot, cpp, tok1->astSibling(), tok2->astSibling(), library, pure, followVar, errors)) @@ -1372,15 +1372,15 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token // is condition opposite? return ((comp1 == "==" && comp2 == "!=") || (comp1 == "!=" && comp2 == "==") || - (comp1 == "<" && comp2 == ">=") || + (comp1 == "<" && comp2 == ">=") || (comp1 == "<=" && comp2 == ">") || - (comp1 == ">" && comp2 == "<=") || + (comp1 == ">" && comp2 == "<=") || (comp1 == ">=" && comp2 == "<") || (!isNot && ((comp1 == "<" && comp2 == ">") || (comp1 == ">" && comp2 == "<") || (comp1 == "==" && (comp2 == "!=" || comp2 == ">" || comp2 == "<")) || ((comp1 == "!=" || comp1 == ">" || comp1 == "<") && comp2 == "==") - ))); + ))); } bool isOppositeExpression(bool cpp, const Token * const tok1, const Token * const tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors) @@ -1425,7 +1425,7 @@ bool isConstFunctionCall(const Token* ftok, const Library& library) if (!Function::returnsConst(f)) { std::vector fs = f->getOverloadedFunctions(); if (std::any_of(fs.begin(), fs.end(), [&](const Function* g) { - if (f == g) + if (f == g) return false; if (f->argumentList.size() != g->argumentList.size()) return false; @@ -1435,7 +1435,7 @@ bool isConstFunctionCall(const Token* ftok, const Library& library) return true; return false; })) - return true; + return true; } return false; } else if (f->argumentList.empty()) { @@ -1551,11 +1551,11 @@ bool isUniqueExpression(const Token* tok) if (varType) return v.type() && v.type()->name() == varType->name() && v.name() != var->name(); return v.isFloatingType() == var->isFloatingType() && - v.isEnumType() == var->isEnumType() && - v.isClass() == var->isClass() && - v.isArray() == var->isArray() && - v.isPointer() == var->isPointer() && - v.name() != var->name(); + v.isEnumType() == var->isEnumType() && + v.isClass() == var->isClass() && + v.isArray() == var->isArray() && + v.isPointer() == var->isPointer() && + v.name() != var->name(); }); if (other) return false; @@ -2102,7 +2102,9 @@ Token* findVariableChanged(Token *start, const Token *end, int indirect, const n return nullptr; if (depth < 0) return start; - auto getExprTok = memoize([&] { return findExpression(start, exprid); }); + auto getExprTok = memoize([&] { + return findExpression(start, exprid); + }); for (Token *tok = start; tok != end; tok = tok->next()) { if (tok->exprId() != exprid) { if (globalvar && Token::Match(tok, "%name% (")) @@ -2279,7 +2281,7 @@ const Token *findLambdaStartToken(const Token *last) return nullptr; } -template +template T* findLambdaEndTokenGeneric(T* first) { if (!first || first->str() != "[") @@ -2548,7 +2550,7 @@ bool isGlobalData(const Token *expr, bool cpp) bool globalData = false; bool var = false; visitAstNodes(expr, - [expr, cpp, &globalData, &var](const Token *tok) { + [expr, cpp, &globalData, &var](const Token *tok) { if (tok->varId()) var = true; if (tok->varId() && !tok->variable()) { @@ -2905,7 +2907,7 @@ static bool hasVolatileCastOrVar(const Token *expr) { bool ret = false; visitAstNodes(expr, - [&ret](const Token *tok) { + [&ret](const Token *tok) { if (Token::simpleMatch(tok, "( volatile")) ret = true; else if (tok->variable() && tok->variable()->isVolatile()) @@ -2927,7 +2929,7 @@ std::set FwdAnalysis::getExprVarIds(const Token* expr, bool* localOu bool local = true; bool unknownVarId = false; visitAstNodes(expr, - [&](const Token *tok) { + [&](const Token *tok) { if (tok->str() == "[" && mWhat == What::UnusedValue) return ChildrenToVisit::op1; if (tok->varId() == 0 && tok->isName() && tok->previous()->str() != ".") { diff --git a/lib/check.h b/lib/check.h index b9ed64b19..cd47c0b84 100644 --- a/lib/check.h +++ b/lib/check.h @@ -62,8 +62,7 @@ public: /** This constructor is used when running checks. */ Check(const std::string &aname, const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : mTokenizer(tokenizer), mSettings(settings), mErrorLogger(errorLogger), mName(aname) { - } + : mTokenizer(tokenizer), mSettings(settings), mErrorLogger(errorLogger), mName(aname) {} virtual ~Check() { if (!mTokenizer) @@ -116,7 +115,7 @@ public: } // Return true if an error is reported. - virtual bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list &fileInfo, const Settings& /*settings*/, ErrorLogger &/*errorLogger*/) { + virtual bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list &fileInfo, const Settings& /*settings*/, ErrorLogger & /*errorLogger*/) { (void)ctu; (void)fileInfo; //(void)settings; diff --git a/lib/check64bit.h b/lib/check64bit.h index 521c3502c..f1fbba34f 100644 --- a/lib/check64bit.h +++ b/lib/check64bit.h @@ -43,13 +43,11 @@ class Tokenizer; class CPPCHECKLIB Check64BitPortability : public Check { public: /** This constructor is used when registering the Check64BitPortability */ - Check64BitPortability() : Check(myName()) { - } + Check64BitPortability() : Check(myName()) {} /** This constructor is used when running checks. */ Check64BitPortability(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkassert.h b/lib/checkassert.h index e4835e381..dbced6948 100644 --- a/lib/checkassert.h +++ b/lib/checkassert.h @@ -42,12 +42,10 @@ class Tokenizer; class CPPCHECKLIB CheckAssert : public Check { public: - CheckAssert() : Check(myName()) { - } + CheckAssert() : Check(myName()) {} CheckAssert(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** run checks, the token list is not simplified */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkautovariables.h b/lib/checkautovariables.h index 171ee6020..9681ac0a6 100644 --- a/lib/checkautovariables.h +++ b/lib/checkautovariables.h @@ -42,13 +42,11 @@ class Variable; class CPPCHECKLIB CheckAutoVariables : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckAutoVariables() : Check(myName()) { - } + CheckAutoVariables() : Check(myName()) {} /** This constructor is used when running checks. */ CheckAutoVariables(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index d075c893a..bc79340e4 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -69,7 +69,7 @@ void CheckBool::incrementBooleanError(const Token *tok) "Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n" "The operand of a postfix increment operator may be of type bool but it is deprecated by C++ Standard (Annex D-1) and the operand is always set to true. You should assign it the value 'true' instead.", CWE398, Certainty::normal - ); + ); } //--------------------------------------------------------------------------- diff --git a/lib/checkbool.h b/lib/checkbool.h index 10f0312a3..bbff56e29 100644 --- a/lib/checkbool.h +++ b/lib/checkbool.h @@ -41,13 +41,11 @@ class Tokenizer; class CPPCHECKLIB CheckBool : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckBool() : Check(myName()) { - } + CheckBool() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckBool(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkboost.cpp b/lib/checkboost.cpp index 3b04e6b63..5d2bdba7f 100644 --- a/lib/checkboost.cpp +++ b/lib/checkboost.cpp @@ -58,5 +58,5 @@ void CheckBoost::boostForeachError(const Token *tok) { reportError(tok, Severity::error, "boostForeachError", "BOOST_FOREACH caches the end() iterator. It's undefined behavior if you modify the container inside.", CWE664, Certainty::normal - ); + ); } diff --git a/lib/checkboost.h b/lib/checkboost.h index b8a3fab01..3fb59b7bd 100644 --- a/lib/checkboost.h +++ b/lib/checkboost.h @@ -40,13 +40,11 @@ class Token; class CPPCHECKLIB CheckBoost : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckBoost() : Check(myName()) { - } + CheckBoost() : Check(myName()) {} /** This constructor is used when running checks. */ CheckBoost(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 14f7efab9..6332188bf 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -191,7 +191,7 @@ static bool getDimensionsEtc(const Token * const arrayToken, const Settings *set *dimensions = array->variable()->dimensions(); if (dimensions->size() >= 1 && ((*dimensions)[0].num <= 1 || !(*dimensions)[0].tok)) { visitAstNodes(arrayToken, - [&](const Token *child) { + [&](const Token *child) { if (child->originalName() == "->") { *mightBeLarger = true; return ChildrenToVisit::none; @@ -940,14 +940,14 @@ void CheckBufferOverrun::objectIndex() std::copy_if(idx->values().begin(), idx->values().end(), std::back_inserter(idxValues), - [&](const ValueFlow::Value& vidx) { + [&](const ValueFlow::Value& vidx) { if (!vidx.isIntValue()) return false; return vidx.path == v.path || vidx.path == 0; }); if (idxValues.empty() || - std::any_of(idxValues.begin(), idxValues.end(), [&](const ValueFlow::Value& vidx) { - if (vidx.isImpossible()) + std::any_of(idxValues.begin(), idxValues.end(), [&](const ValueFlow::Value& vidx) { + if (vidx.isImpossible()) return (vidx.intvalue == 0); else return (vidx.intvalue != 0); diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h index 44ba1150b..141e23ad8 100644 --- a/lib/checkbufferoverrun.h +++ b/lib/checkbufferoverrun.h @@ -60,13 +60,11 @@ class CPPCHECKLIB CheckBufferOverrun : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckBufferOverrun() : Check(myName()) { - } + CheckBufferOverrun() : Check(myName()) {} /** This constructor is used when running checks. */ CheckBufferOverrun(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { CheckBufferOverrun checkBufferOverrun(tokenizer, settings, errorLogger); diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index e2310b398..bdba8e013 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -105,10 +105,8 @@ static bool isVclTypeInit(const Type *type) CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) : Check(myName(), tokenizer, settings, errorLogger), - mSymbolDatabase(tokenizer?tokenizer->getSymbolDatabase():nullptr) -{ - -} + mSymbolDatabase(tokenizer?tokenizer->getSymbolDatabase():nullptr) +{} //--------------------------------------------------------------------------- // ClassCheck: Check that all class constructors are ok. @@ -458,23 +456,23 @@ void CheckClass::copyconstructors() copyConstructorShallowCopyError(cv, cv->str()); // throw error if count mismatch /* FIXME: This doesn't work. See #4154 - for (std::map::const_iterator i = allocatedVars.begin(); i != allocatedVars.end(); ++i) { + for (std::map::const_iterator i = allocatedVars.begin(); i != allocatedVars.end(); ++i) { copyConstructorMallocError(copyCtor, i->second, i->second->str()); - } - */ + } + */ } } } /* This doesn't work. See #4154 -void CheckClass::copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& varname) -{ + void CheckClass::copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& varname) + { std::list callstack; callstack.push_back(cctor); callstack.push_back(alloc); reportError(callstack, Severity::warning, "copyCtorNoAllocation", "Copy constructor does not allocate memory for member '" + varname + "' although memory has been allocated in other constructors."); -} -*/ + } + */ void CheckClass::copyConstructorShallowCopyError(const Token *tok, const std::string& varname) { @@ -1034,7 +1032,7 @@ void CheckClass::initializationListUsage() // Access local var member in rhs => do not warn bool localmember = false; visitAstNodes(tok->next()->astOperand2(), - [&](const Token *rhs) { + [&](const Token *rhs) { if (rhs->str() == "." && rhs->astOperand1() && rhs->astOperand1()->variable() && rhs->astOperand1()->variable()->isLocal()) localmember = true; return ChildrenToVisit::op1_and_op2; @@ -1044,7 +1042,7 @@ void CheckClass::initializationListUsage() bool allowed = true; visitAstNodes(tok->next()->astOperand2(), - [&](const Token *tok2) { + [&](const Token *tok2) { const Variable* var2 = tok2->variable(); if (var2) { if (var2->scope() == owner && tok2->strAt(-1)!=".") { // Is there a dependency between two member variables? @@ -1111,7 +1109,7 @@ static bool checkFunctionUsage(const Function *privfunc, const Scope* scope) } const std::map::const_iterator end = scope->definedTypesMap.end(); - for (std::map::const_iterator iter = scope->definedTypesMap.begin(); iter != end; ++ iter) { + for (std::map::const_iterator iter = scope->definedTypesMap.begin(); iter != end; ++iter) { const Type *type = (*iter).second; if (type->enclosingScope == scope && checkFunctionUsage(privfunc, type->classScope)) return true; @@ -1643,7 +1641,7 @@ CheckClass::Bool CheckClass::isInverted(const Token *tok, const Token *rhs) if (Token::simpleMatch(itr, "!=") && (isTrueKeyword(itr->astOperand1()) || isTrueKeyword(itr->astOperand2()))) { res = !res; } else if (Token::simpleMatch(itr, "!=") && ((Token::simpleMatch(itr->astOperand1(), "this") && Token::simpleMatch(itr->astOperand2(), "&") && Token::simpleMatch(itr->astOperand2()->next(), rhs->str().c_str(), rhs->str().size())) - || (Token::simpleMatch(itr->astOperand2(), "this") && Token::simpleMatch(itr->astOperand1(), "&") && Token::simpleMatch(itr->astOperand1()->next(), rhs->str().c_str(), rhs->str().size())))) { + || (Token::simpleMatch(itr->astOperand2(), "this") && Token::simpleMatch(itr->astOperand1(), "&") && Token::simpleMatch(itr->astOperand1()->next(), rhs->str().c_str(), rhs->str().size())))) { res = !res; } else if (Token::simpleMatch(itr, "!=") && (isFalseKeyword(itr->astOperand1()) || isFalseKeyword(itr->astOperand2()))) { //Do nothing @@ -1654,7 +1652,7 @@ CheckClass::Bool CheckClass::isInverted(const Token *tok, const Token *rhs) } else if (Token::simpleMatch(itr, "==") && (isTrueKeyword(itr->astOperand1()) || isTrueKeyword(itr->astOperand2()))) { //Do nothing } else if (Token::simpleMatch(itr, "==") && ((Token::simpleMatch(itr->astOperand1(), "this") && Token::simpleMatch(itr->astOperand2(), "&") && Token::simpleMatch(itr->astOperand2()->next(), rhs->str().c_str(), rhs->str().size())) - || (Token::simpleMatch(itr->astOperand2(), "this") && Token::simpleMatch(itr->astOperand1(), "&") && Token::simpleMatch(itr->astOperand1()->next(), rhs->str().c_str(), rhs->str().size())))) { + || (Token::simpleMatch(itr->astOperand2(), "this") && Token::simpleMatch(itr->astOperand1(), "&") && Token::simpleMatch(itr->astOperand1()->next(), rhs->str().c_str(), rhs->str().size())))) { //Do nothing } else { return Bool::BAILOUT; @@ -1692,7 +1690,7 @@ bool CheckClass::hasAssignSelf(const Function *func, const Token *rhs, const Tok bool ret = false; visitAstNodes(tok->next()->astOperand2(), - [&](const Token *tok2) { + [&](const Token *tok2) { if (!Token::Match(tok2, "==|!=")) return ChildrenToVisit::op1_and_op2; if (Token::simpleMatch(tok2->astOperand1(), "this")) @@ -2296,7 +2294,7 @@ void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const st namespace { // avoid one-definition-rule violation struct VarInfo { VarInfo(const Variable *_var, const Token *_tok) - : var(_var), tok(_tok) { } + : var(_var), tok(_tok) {} const Variable *var; const Token *tok; @@ -2406,9 +2404,9 @@ void CheckClass::selfInitializationError(const Token* tok, const std::string& va void CheckClass::checkVirtualFunctionCallInConstructor() { - if (! mSettings->severity.isEnabled(Severity::warning)) + if (!mSettings->severity.isEnabled(Severity::warning)) return; - std::map > virtualFunctionCallsMap; + std::map> virtualFunctionCallsMap; for (const Scope *scope : mSymbolDatabase->functionScopes) { if (scope->function == nullptr || !scope->function->hasBody() || !(scope->function->isConstructor() || @@ -2432,9 +2430,9 @@ void CheckClass::checkVirtualFunctionCallInConstructor() } const std::list & CheckClass::getVirtualFunctionCalls(const Function & function, - std::map > & virtualFunctionCallsMap) + std::map> & virtualFunctionCallsMap) { - const std::map >::const_iterator found = virtualFunctionCallsMap.find(&function); + const std::map>::const_iterator found = virtualFunctionCallsMap.find(&function); if (found != virtualFunctionCallsMap.end()) return found->second; @@ -2489,7 +2487,7 @@ const std::list & CheckClass::getVirtualFunctionCalls(const Funct } void CheckClass::getFirstVirtualFunctionCallStack( - std::map > & virtualFunctionCallsMap, + std::map> & virtualFunctionCallsMap, const Token * callToken, std::list & pureFuncStack) { @@ -2498,7 +2496,7 @@ void CheckClass::getFirstVirtualFunctionCallStack( pureFuncStack.push_back(callFunction->tokenDef); return; } - std::map >::const_iterator found = virtualFunctionCallsMap.find(callFunction); + std::map>::const_iterator found = virtualFunctionCallsMap.find(callFunction); if (found == virtualFunctionCallsMap.end() || found->second.empty()) { pureFuncStack.clear(); return; @@ -2604,8 +2602,8 @@ void CheckClass::checkDuplInheritedMembersRecursive(const Type* typeCurrent, con } void CheckClass::duplInheritedMembersError(const Token *tok1, const Token* tok2, - const std::string &derivedName, const std::string &baseName, - const std::string &variableName, bool derivedIsStruct, bool baseIsStruct) + const std::string &derivedName, const std::string &baseName, + const std::string &variableName, bool derivedIsStruct, bool baseIsStruct) { ErrorPath errorPath; errorPath.emplace_back(tok2, "Parent variable '" + baseName + "::" + variableName + "'"); @@ -2878,7 +2876,7 @@ Check::FileInfo *CheckClass::getFileInfo(const Tokenizer *tokenizer, const Setti // the full definition must be compared bool fullDefinition = std::all_of(classScope->functionList.begin(), classScope->functionList.end(), - [](const Function& f) { + [](const Function& f) { return f.hasBody(); }); if (!fullDefinition) diff --git a/lib/checkclass.h b/lib/checkclass.h index 7aa00d140..377ed14ad 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -44,8 +44,7 @@ class Token; class CPPCHECKLIB CheckClass : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckClass() : Check(myName()), mSymbolDatabase(nullptr) { - } + CheckClass() : Check(myName()), mSymbolDatabase(nullptr) {} /** @brief This constructor is used when running checks. */ CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger); @@ -310,7 +309,7 @@ private: // constructors helper function /** @brief Information about a member variable. Used when checking for uninitialized variables */ struct Usage { - explicit Usage(const Variable *var) : var(var), assign(false), init(false) { } + explicit Usage(const Variable *var) : var(var), assign(false), init(false) {} /** Variable that this usage is for */ const Variable *var; @@ -374,7 +373,7 @@ private: */ const std::list & getVirtualFunctionCalls( const Function & function, - std::map > & virtualFunctionCallsMap); + std::map> & virtualFunctionCallsMap); /** * @brief looks for the first virtual function call stack @@ -383,7 +382,7 @@ private: * @param[in,out] pureFuncStack list to append the stack */ void getFirstVirtualFunctionCallStack( - std::map > & virtualFunctionCallsMap, + std::map> & virtualFunctionCallsMap, const Token *callToken, std::list & pureFuncStack); diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 5e677c3c6..2e310e9c0 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -596,7 +596,7 @@ void CheckCondition::multiCondition2() bool nonlocal = false; // nonlocal variable used in condition std::set vars; // variables used in condition visitAstNodes(condTok, - [&](const Token *cond) { + [&](const Token *cond) { if (Token::Match(cond, "%name% (")) { functionCall = true; nonConstFunctionCall = isNonConstFunctionCall(cond, mSettings->library); @@ -628,7 +628,7 @@ void CheckCondition::multiCondition2() std::vector varsInCond; visitAstNodes(condTok, - [&varsInCond](const Token *cond) { + [&varsInCond](const Token *cond) { if (cond->variable()) { const Variable *var = cond->variable(); if (std::find(varsInCond.begin(), varsInCond.end(), var) == varsInCond.end()) @@ -885,22 +885,22 @@ static std::string invertOperatorForOperandSwap(std::string s) return s; } -template +template static bool checkIntRelation(const std::string &op, const T value1, const T value2) { return (op == "==" && value1 == value2) || (op == "!=" && value1 != value2) || - (op == ">" && value1 > value2) || + (op == ">" && value1 > value2) || (op == ">=" && value1 >= value2) || - (op == "<" && value1 < value2) || + (op == "<" && value1 < value2) || (op == "<=" && value1 <= value2); } static bool checkFloatRelation(const std::string &op, const double value1, const double value2) { - return (op == ">" && value1 > value2) || + return (op == ">" && value1 > value2) || (op == ">=" && value1 >= value2) || - (op == "<" && value1 < value2) || + (op == "<" && value1 < value2) || (op == "<=" && value1 <= value2); } @@ -1172,7 +1172,7 @@ void CheckCondition::checkIncorrectLogicOperator() const double d2 = (isfloat) ? MathLib::toDoubleNumber(value2) : 0; const MathLib::bigint i1 = (isfloat) ? 0 : MathLib::toLongNumber(value1); const MathLib::bigint i2 = (isfloat) ? 0 : MathLib::toLongNumber(value2); - const bool useUnsignedInt = (std::numeric_limits::max()==i1)||(std::numeric_limits::max()==i2); + const bool useUnsignedInt = (std::numeric_limits::max()==i1) || (std::numeric_limits::max()==i2); const MathLib::biguint u1 = (useUnsignedInt) ? MathLib::toLongNumber(value1) : 0; const MathLib::biguint u2 = (useUnsignedInt) ? MathLib::toLongNumber(value2) : 0; // evaluate if expression is always true/false diff --git a/lib/checkcondition.h b/lib/checkcondition.h index cb492236f..dcf7501cd 100644 --- a/lib/checkcondition.h +++ b/lib/checkcondition.h @@ -47,13 +47,11 @@ class ValueType; class CPPCHECKLIB CheckCondition : public Check { public: /** This constructor is used when registering the CheckAssignIf */ - CheckCondition() : Check(myName()) { - } + CheckCondition() : Check(myName()) {} /** This constructor is used when running checks. */ CheckCondition(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { CheckCondition checkCondition(tokenizer, settings, errorLogger); diff --git a/lib/checkexceptionsafety.h b/lib/checkexceptionsafety.h index a169ae83f..b6d27b37f 100644 --- a/lib/checkexceptionsafety.h +++ b/lib/checkexceptionsafety.h @@ -54,13 +54,11 @@ static const struct CWE CWE480(480U); // Use of Incorrect Operator class CPPCHECKLIB CheckExceptionSafety : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckExceptionSafety() : Check(myName()) { - } + CheckExceptionSafety() : Check(myName()) {} /** This constructor is used when running checks. */ CheckExceptionSafety(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { if (tokenizer->isC()) diff --git a/lib/checkfunctions.h b/lib/checkfunctions.h index 4e1623b18..953489d99 100644 --- a/lib/checkfunctions.h +++ b/lib/checkfunctions.h @@ -51,13 +51,11 @@ namespace ValueFlow { class CPPCHECKLIB CheckFunctions : public Check { public: /** This constructor is used when registering the CheckFunctions */ - CheckFunctions() : Check(myName()) { - } + CheckFunctions() : Check(myName()) {} /** This constructor is used when running checks. */ CheckFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { @@ -81,13 +79,13 @@ public: void checkProhibitedFunctions(); /** - * @brief Invalid function usage (invalid input value / overlapping data) - * - * %Check that given function parameters are valid according to the standard - * - wrong radix given for strtol/strtoul - * - overlapping data when using sprintf/snprintf - * - wrong input value according to library - */ + * @brief Invalid function usage (invalid input value / overlapping data) + * + * %Check that given function parameters are valid according to the standard + * - wrong radix given for strtol/strtoul + * - overlapping data when using sprintf/snprintf + * - wrong input value according to library + */ void invalidFunctionUsage(); /** @brief %Check for ignored return values. */ diff --git a/lib/checkinternal.cpp b/lib/checkinternal.cpp index 9a854bf15..702a1d177 100644 --- a/lib/checkinternal.cpp +++ b/lib/checkinternal.cpp @@ -360,28 +360,28 @@ void CheckInternal::multiComparePatternError(const Token* tok, const std::string { reportError(tok, Severity::error, "multiComparePatternError", "Bad multicompare pattern (a %cmd% must be first unless it is %or%,%op%,%cop%,%name%,%oror%) inside Token::" + funcname + "() call: \"" + pattern + "\"" - ); + ); } void CheckInternal::simplePatternError(const Token* tok, const std::string& pattern, const std::string &funcname) { reportError(tok, Severity::warning, "simplePatternError", "Found simple pattern inside Token::" + funcname + "() call: \"" + pattern + "\"" - ); + ); } void CheckInternal::complexPatternError(const Token* tok, const std::string& pattern, const std::string &funcname) { reportError(tok, Severity::error, "complexPatternError", "Found complex pattern inside Token::" + funcname + "() call: \"" + pattern + "\"" - ); + ); } void CheckInternal::missingPercentCharacterError(const Token* tok, const std::string& pattern, const std::string& funcname) { reportError(tok, Severity::error, "missingPercentCharacter", "Missing percent end character in Token::" + funcname + "() pattern: \"" + pattern + "\"" - ); + ); } void CheckInternal::unknownPatternError(const Token* tok, const std::string& pattern) @@ -406,7 +406,7 @@ void CheckInternal::extraWhitespaceError(const Token* tok, const std::string& pa { reportError(tok, Severity::warning, "extraWhitespaceError", "Found extra whitespace inside Token::" + funcname + "() call: \"" + pattern + "\"" - ); + ); } #endif // #ifdef CHECK_INTERNAL diff --git a/lib/checkinternal.h b/lib/checkinternal.h index b9f5d3ae1..da3959592 100644 --- a/lib/checkinternal.h +++ b/lib/checkinternal.h @@ -36,13 +36,11 @@ class CPPCHECKLIB CheckInternal : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckInternal() : Check(myName()) { - } + CheckInternal() : Check(myName()) {} /** This constructor is used when running checks. */ CheckInternal(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { if (!settings->checks.isEnabled(Checks::internalCheck)) diff --git a/lib/checkio.cpp b/lib/checkio.cpp index b655e820a..b72c4763c 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -108,8 +108,7 @@ struct Filepointer { AppendMode append_mode; std::string filename; explicit Filepointer(OpenMode mode_ = OpenMode::UNKNOWN_OM) - : mode(mode_), mode_indent(0), lastOperation(Operation::NONE), op_indent(0), append_mode(AppendMode::UNKNOWN_AM) { - } + : mode(mode_), mode_indent(0), lastOperation(Operation::NONE), op_indent(0), append_mode(AppendMode::UNKNOWN_AM) {} }; namespace { @@ -494,7 +493,7 @@ static bool findFormat(nonneg int arg, const Token *firstArg, *formatArgTok = argTok->nextArgument(); if (!argTok->values().empty()) { std::list::const_iterator value = std::find_if( - argTok->values().begin(), argTok->values().end(), std::mem_fn(&ValueFlow::Value::isTokValue)); + argTok->values().begin(), argTok->values().end(), std::mem_fn(&ValueFlow::Value::isTokValue)); if (value != argTok->values().end() && value->isTokValue() && value->tokvalue && value->tokvalue->tokType() == Token::eString) { *formatStringTok = value->tokvalue; @@ -1214,7 +1213,7 @@ void CheckIO::checkFormatString(const Token * const tok, break; case 'p': if (argInfo.typeToken->tokType() == Token::eString) - ;// string literals are passed as pointers to literal start, okay + ; // string literals are passed as pointers to literal start, okay else if (argInfo.isKnownType() && !argInfo.isArrayOrPointer()) invalidPrintfArgTypeError_p(tok, numFormat, &argInfo); done = true; @@ -1702,9 +1701,9 @@ bool CheckIO::ArgumentInfo::isLibraryType(const Settings *settings) const } void CheckIO::wrongPrintfScanfArgumentsError(const Token* tok, - const std::string &functionName, - nonneg int numFormat, - nonneg int numFunction) + const std::string &functionName, + nonneg int numFormat, + nonneg int numFunction) { const Severity::SeverityType severity = numFormat > numFunction ? Severity::error : Severity::warning; if (severity != Severity::error && !mSettings->severity.isEnabled(Severity::warning)) @@ -1724,7 +1723,7 @@ void CheckIO::wrongPrintfScanfArgumentsError(const Token* tok, } void CheckIO::wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName, - nonneg int index, nonneg int numFunction) + nonneg int index, nonneg int numFunction) { if (!mSettings->severity.isEnabled(Severity::warning)) return; diff --git a/lib/checkio.h b/lib/checkio.h index 8a79e5655..3d0c67483 100644 --- a/lib/checkio.h +++ b/lib/checkio.h @@ -43,13 +43,11 @@ class ErrorLogger; class CPPCHECKLIB CheckIO : public Check { public: /** @brief This constructor is used when registering CheckIO */ - CheckIO() : Check(myName()) { - } + CheckIO() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckIO(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks on the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { @@ -121,7 +119,7 @@ private: nonneg int numFormat, nonneg int numFunction); void wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName, - nonneg int index, nonneg int numFunction); + nonneg int index, nonneg int numFunction); void invalidScanfArgTypeError_s(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); void invalidScanfArgTypeError_int(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo, bool isUnsigned); void invalidScanfArgTypeError_float(const Token* tok, nonneg int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 6562772b5..3a59f4ae8 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -257,12 +257,12 @@ static bool isLocalVarNoAutoDealloc(const Token *varTok, const bool isCpp) } /** checks if nameToken is a name of a function in a function call: -* func(arg) -* or -* func(arg) -* @param nameToken Function name token -* @return opening parenthesis token or NULL if not a function call -*/ + * func(arg) + * or + * func(arg) + * @param nameToken Function name token + * @return opening parenthesis token or NULL if not a function call + */ static const Token * isFunctionCall(const Token * nameToken) { diff --git a/lib/checkleakautovar.h b/lib/checkleakautovar.h index 60da36afc..3fd573121 100644 --- a/lib/checkleakautovar.h +++ b/lib/checkleakautovar.h @@ -108,13 +108,11 @@ public: class CPPCHECKLIB CheckLeakAutoVar : public Check { public: /** This constructor is used when registering the CheckLeakAutoVar */ - CheckLeakAutoVar() : Check(myName()) { - } + CheckLeakAutoVar() : Check(myName()) {} /** This constructor is used when running checks. */ CheckLeakAutoVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { CheckLeakAutoVar checkLeakAutoVar(tokenizer, settings, errorLogger); @@ -133,10 +131,10 @@ private: nonneg int recursiveCount); /** Check token inside expression. - * @param tok token inside expression. - * @param varInfo Variable info - * @return next token to process (if no other checks needed for this token). NULL if other checks could be performed. - */ + * @param tok token inside expression. + * @param varInfo Variable info + * @return next token to process (if no other checks needed for this token). NULL if other checks could be performed. + */ const Token * checkTokenInsideExpression(const Token * const tok, VarInfo *varInfo); /** parse function call */ diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 72580f6e6..05d4dcf20 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -82,11 +82,11 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, tok2 = tok2->link(); tok2 = tok2 ? tok2->next() : nullptr; } - if (! tok2) + if (!tok2) return No; if (tok2->str() == "::") tok2 = tok2->next(); - if (! tok2->isName()) + if (!tok2->isName()) return No; if (!Token::Match(tok2, "%name% ::|. %type%")) { @@ -169,7 +169,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok tok2 = tok2->link(); tok2 = tok2 ? tok2->next() : nullptr; } - if (! tok2) + if (!tok2) return No; if (!Token::Match(tok2, "%name% (")) @@ -275,7 +275,7 @@ void CheckMemoryLeak::memoryLeak(const Token *tok, const std::string &varname, A { if (alloctype == CheckMemoryLeak::File || alloctype == CheckMemoryLeak::Pipe || - alloctype == CheckMemoryLeak::Fd || + alloctype == CheckMemoryLeak::Fd || alloctype == CheckMemoryLeak::OtherRes) resourceLeakError(tok, varname); else @@ -681,7 +681,7 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam if (memberDealloc != CheckMemoryLeak::No && memberDealloc != dealloc) dealloc = CheckMemoryLeak::Many; - if (dealloc != CheckMemoryLeak::Many && memberAlloc != CheckMemoryLeak::No && memberAlloc != Many && memberAlloc != dealloc) { + if (dealloc != CheckMemoryLeak::Many && memberAlloc != CheckMemoryLeak::No && memberAlloc != Many && memberAlloc != dealloc) { std::list callstack; callstack.push_back(tok); mismatchAllocDealloc(callstack, classname + "::" + varname); diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index 65055ff72..8ce09862e 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -88,8 +88,7 @@ public: void operator=(const CheckMemoryLeak &) = delete; CheckMemoryLeak(const Tokenizer *t, ErrorLogger *e, const Settings *s) - : mTokenizer_(t), mErrorLogger_(e), mSettings_(s) { - } + : mTokenizer_(t), mErrorLogger_(e), mSettings_(s) {} /** @brief What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */ enum AllocType { No, Malloc, New, NewArray, File, Fd, Pipe, OtherMem, OtherRes, Many }; @@ -172,13 +171,11 @@ public: class CPPCHECKLIB CheckMemoryLeakInFunction : private Check, public CheckMemoryLeak { public: /** @brief This constructor is used when registering this class */ - CheckMemoryLeakInFunction() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) { - } + CheckMemoryLeakInFunction() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) {} /** @brief This constructor is used when running checks */ CheckMemoryLeakInFunction(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) { - } + : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { CheckMemoryLeakInFunction checkMemoryLeak(tokenizer, settings, errorLogger); @@ -234,12 +231,10 @@ private: class CPPCHECKLIB CheckMemoryLeakInClass : private Check, private CheckMemoryLeak { public: - CheckMemoryLeakInClass() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) { - } + CheckMemoryLeakInClass() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) {} CheckMemoryLeakInClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) { - } + : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) {} void runChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) OVERRIDE { if (!tokenizr->isCPP()) @@ -281,12 +276,10 @@ private: class CPPCHECKLIB CheckMemoryLeakStructMember : private Check, private CheckMemoryLeak { public: - CheckMemoryLeakStructMember() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) { - } + CheckMemoryLeakStructMember() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) {} CheckMemoryLeakStructMember(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) { - } + : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { CheckMemoryLeakStructMember checkMemoryLeak(tokenizer, settings, errorLogger); @@ -302,8 +295,7 @@ private: void checkStructVariable(const Variable * const variable); - void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/) const OVERRIDE { - } + void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/) const OVERRIDE {} static std::string myName() { return "Memory leaks (struct members)"; @@ -320,12 +312,10 @@ private: class CPPCHECKLIB CheckMemoryLeakNoVar : private Check, private CheckMemoryLeak { public: - CheckMemoryLeakNoVar() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) { - } + CheckMemoryLeakNoVar() : Check(myName()), CheckMemoryLeak(nullptr, nullptr, nullptr) {} CheckMemoryLeakNoVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) { - } + : Check(myName(), tokenizer, settings, errorLogger), CheckMemoryLeak(tokenizer, errorLogger, settings) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { CheckMemoryLeakNoVar checkMemoryLeak(tokenizer, settings, errorLogger); diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index ff8f38a1c..017a88e34 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -46,13 +46,11 @@ class Tokenizer; class CPPCHECKLIB CheckNullPointer : public Check { public: /** @brief This constructor is used when registering the CheckNullPointer */ - CheckNullPointer() : Check(myName()) { - } + CheckNullPointer() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckNullPointer(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkother.cpp b/lib/checkother.cpp index b70266635..053e419c7 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -139,7 +139,7 @@ void CheckOther::checkCastIntToCharAndBackError(const Token *tok, const std::str "variable with EOF can have unexpected results. For instance a loop \"while (EOF != (c = $symbol());\" " "loops forever on some compilers/platforms and on other compilers/platforms it will stop " "when the file contains a matching character.", CWE197, Certainty::normal - ); + ); } @@ -450,7 +450,7 @@ void CheckOther::checkRedundantAssignment() isInitialization = true; bool trivial = true; visitAstNodes(tok->astOperand2(), - [&](const Token *rhs) { + [&](const Token *rhs) { if (Token::simpleMatch(rhs, "{ 0 }")) return ChildrenToVisit::none; if (Token::Match(rhs, "%str%|%num%|%name%") && !rhs->varId()) @@ -1218,7 +1218,7 @@ static bool canBeConst(const Variable *var) return false; else { const Variable* argVar = tok3->astOperand1()->function()->getArgumentVar(argNr); - if (!argVar|| (!argVar->isConst() && argVar->isReference())) + if (!argVar || (!argVar->isConst() && argVar->isReference())) return false; } } else if (parent->isUnaryOp("&")) { @@ -1268,8 +1268,7 @@ void CheckOther::checkPassByReference() bool inconclusive = false; - if (var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER) { - } else if (var->type() && !var->type()->isEnumType()) { // Check if type is a struct or class. + if (var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER) {} else if (var->type() && !var->type()->isEnumType()) { // Check if type is a struct or class. // Ensure that it is a large object. if (!var->type()->classScope) inconclusive = true; @@ -1399,7 +1398,7 @@ void CheckOther::checkConstVariable() if (Function::returnsReference(function) && !Function::returnsConst(function)) { std::vector returns = Function::findReturns(function); if (std::any_of(returns.begin(), returns.end(), [&](const Token* retTok) { - if (retTok->varId() == var->declarationId()) + if (retTok->varId() == var->declarationId()) return true; while (retTok && retTok->isCast()) retTok = retTok->astOperand2(); @@ -1407,7 +1406,7 @@ void CheckOther::checkConstVariable() retTok = retTok->astOperand2(); return hasLifetimeToken(getParentLifetime(retTok), var->nameToken()); })) - continue; + continue; } // Skip if address is taken if (Token::findmatch(var->nameToken(), "& %varid%", scope->bodyEnd, var->declarationId())) @@ -2076,7 +2075,7 @@ namespace { for (const Scope &scope : symbolDatabase->scopeList) { // only add const functions that do not have a non-const overloaded version // since it is pretty much impossible to tell which is being called. - using StringFunctionMap = std::map >; + using StringFunctionMap = std::map>; StringFunctionMap functionsByName; for (const Function &func : scope.functionList) { functionsByName[func.tokenDef->str()].push_back(&func); @@ -2127,7 +2126,7 @@ void CheckOther::checkDuplicateExpression() tok->astOperand2()->isArithmeticalOp() || tok->astOperand2()->str() == "." || Token::Match(tok->astOperand2()->previous(), "%name% (") - ) && + ) && tok->next()->tokType() != Token::eType && isSameExpression(mTokenizer->isCPP(), true, tok->next(), nextAssign->next(), mSettings->library, true, false) && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand2(), nextAssign->astOperand2(), mSettings->library, true, false) && @@ -2931,7 +2930,7 @@ void CheckOther::checkEvaluationOrder() // Is expression used? bool foundError = false; visitAstNodes((parent->astOperand1() != tok2) ? parent->astOperand1() : parent->astOperand2(), - [&](const Token *tok3) { + [&](const Token *tok3) { if (tok3->str() == "&" && !tok3->astOperand2()) return ChildrenToVisit::none; // don't handle address-of for now if (tok3->str() == "(" && Token::simpleMatch(tok3->previous(), "sizeof")) diff --git a/lib/checkother.h b/lib/checkother.h index 16a63d3eb..915f2254f 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -50,13 +50,11 @@ class ErrorLogger; class CPPCHECKLIB CheckOther : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckOther() : Check(myName()) { - } + CheckOther() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckOther(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkpostfixoperator.h b/lib/checkpostfixoperator.h index 232e22a76..4bb8dd0d0 100644 --- a/lib/checkpostfixoperator.h +++ b/lib/checkpostfixoperator.h @@ -42,13 +42,11 @@ class Token; class CPPCHECKLIB CheckPostfixOperator : public Check { public: /** This constructor is used when registering the CheckPostfixOperator */ - CheckPostfixOperator() : Check(myName()) { - } + CheckPostfixOperator() : Check(myName()) {} /** This constructor is used when running checks. */ CheckPostfixOperator(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { if (tokenizer->isC()) diff --git a/lib/checksizeof.cpp b/lib/checksizeof.cpp index a4ecea599..78285648d 100644 --- a/lib/checksizeof.cpp +++ b/lib/checksizeof.cpp @@ -101,7 +101,7 @@ void CheckSizeof::sizeofForArrayParameterError(const Token *tok) " }\n" "returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 100 (the " "size of the array in bytes).", CWE467, Certainty::normal - ); + ); } void CheckSizeof::checkSizeofForPointerSize() diff --git a/lib/checksizeof.h b/lib/checksizeof.h index 8e5ce2051..750fad556 100644 --- a/lib/checksizeof.h +++ b/lib/checksizeof.h @@ -41,13 +41,11 @@ class Tokenizer; class CPPCHECKLIB CheckSizeof : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckSizeof() : Check(myName()) { - } + CheckSizeof() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckSizeof(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) OVERRIDE { diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 54e657b71..f3fec3749 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -988,7 +988,7 @@ void CheckStl::invalidContainer() const ValueFlow::Value* v = nullptr; ErrorPath errorPath; PathAnalysis::Info info = - PathAnalysis{endToken, library} .forwardFind([&](const PathAnalysis::Info& info) { + PathAnalysis{endToken, library}.forwardFind([&](const PathAnalysis::Info& info) { if (!info.tok->variable()) return false; if (info.tok->varId() == 0) @@ -1152,7 +1152,7 @@ void CheckStl::stlOutOfBounds() std::vector conds; visitAstNodes(condition, - [&](const Token *cond) { + [&](const Token *cond) { if (Token::Match(cond, "%oror%|&&")) return ChildrenToVisit::op1_and_op2; if (cond->isComparisonOp()) diff --git a/lib/checkstl.h b/lib/checkstl.h index 3168d1b27..8d7d2a6e9 100644 --- a/lib/checkstl.h +++ b/lib/checkstl.h @@ -46,13 +46,11 @@ class ErrorLogger; class CPPCHECKLIB CheckStl : public Check { public: /** This constructor is used when registering the CheckClass */ - CheckStl() : Check(myName()) { - } + CheckStl() : Check(myName()) {} /** This constructor is used when running checks. */ CheckStl(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** run checks, the token list is not simplified */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkstring.h b/lib/checkstring.h index 86841e2e6..1d09dc912 100644 --- a/lib/checkstring.h +++ b/lib/checkstring.h @@ -41,13 +41,11 @@ class Tokenizer; class CPPCHECKLIB CheckString : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckString() : Check(myName()) { - } + CheckString() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckString(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checktype.cpp b/lib/checktype.cpp index b1aa3ddb5..bf4921e61 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -242,7 +242,7 @@ void CheckType::checkSignConversion() if (!tok1) continue; const ValueFlow::Value* negativeValue = - ValueFlow::findValue(tok1->values(), mSettings, [&](const ValueFlow::Value& v) { + ValueFlow::findValue(tok1->values(), mSettings, [&](const ValueFlow::Value& v) { return !v.isImpossible() && v.isIntValue() && (v.intvalue <= -1 || v.wideintvalue <= -1); }); if (!negativeValue) diff --git a/lib/checktype.h b/lib/checktype.h index e51da8d1d..36802d6d9 100644 --- a/lib/checktype.h +++ b/lib/checktype.h @@ -40,13 +40,11 @@ class Tokenizer; class CPPCHECKLIB CheckType : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckType() : Check(myName()) { - } + CheckType() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckType(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 79436317b..4ff956518 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -306,7 +306,7 @@ static void conditionAlwaysTrueOrFalse(const Token *tok, const std::mapstr() == "!") { bool t=false,f=false; conditionAlwaysTrueOrFalse(tok->astOperand1(), variableValue, &t, &f); - if (t||f) { + if (t || f) { *alwaysTrue = !t; *alwaysFalse = !f; } @@ -562,7 +562,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var const Token *errorToken = nullptr; visitAstNodes(tok->next(), - [&](const Token *child) { + [&](const Token *child) { if (child->isUnaryOp("&")) return ChildrenToVisit::none; if (child->str() == "," || child->str() == "{" || child->isConstOp()) @@ -910,7 +910,7 @@ const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Va // for loop; skip loop body if there is third expression if (Token::simpleMatch(tok, ") {") && Token::simpleMatch(tok->link()->previous(), "for (") && - Token::simpleMatch(tok->link()->astOperand2(), ";") && + Token::simpleMatch(tok->link()->astOperand2(), ";") && Token::simpleMatch(tok->link()->astOperand2()->astOperand2(), ";")) { tok = tok->linkAt(1); } diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index d466f9415..c97fe2562 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -55,13 +55,11 @@ struct VariableValue { class CPPCHECKLIB CheckUninitVar : public Check { public: /** @brief This constructor is used when registering the CheckUninitVar */ - CheckUninitVar() : Check(myName()) { - } + CheckUninitVar() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckUninitVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index 9468bac00..39f10f829 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -223,7 +223,7 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const char Fi } if (funcname) { - FunctionUsage &func = mFunctions[ funcname->str()]; + FunctionUsage &func = mFunctions[funcname->str()]; const std::string& called_from_file = tokenizer.list.getSourceFilePath(); if (func.filename.empty() || func.filename == "+" || func.filename != called_from_file) @@ -305,22 +305,22 @@ bool CheckUnusedFunctions::check(ErrorLogger * const errorLogger, const Settings filename = func.filename; unusedFunctionError(errorLogger, filename, func.lineNumber, it->first); errors = true; - } else if (! func.usedOtherFile) { + } else if (!func.usedOtherFile) { /** @todo add error message "function is only used in it can be static" */ /* - std::ostringstream errmsg; - errmsg << "The function '" << it->first << "' is only used in the file it was declared in so it should have local linkage."; - mErrorLogger->reportErr( errmsg.str() ); - errors = true; - */ + std::ostringstream errmsg; + errmsg << "The function '" << it->first << "' is only used in the file it was declared in so it should have local linkage."; + mErrorLogger->reportErr( errmsg.str() ); + errors = true; + */ } } return errors; } void CheckUnusedFunctions::unusedFunctionError(ErrorLogger * const errorLogger, - const std::string &filename, unsigned int lineNumber, - const std::string &funcname) + const std::string &filename, unsigned int lineNumber, + const std::string &funcname) { std::list locationList; if (!filename.empty()) { @@ -355,8 +355,7 @@ bool CheckUnusedFunctions::analyseWholeProgram(const CTU::FileInfo *ctu, const s CheckUnusedFunctions::FunctionDecl::FunctionDecl(const Function *f) : functionName(f->name()), lineNumber(f->token->linenr()) -{ -} +{} std::string CheckUnusedFunctions::analyzerInfo() const { diff --git a/lib/checkunusedfunctions.h b/lib/checkunusedfunctions.h index 1816f6a44..7ca418925 100644 --- a/lib/checkunusedfunctions.h +++ b/lib/checkunusedfunctions.h @@ -42,13 +42,11 @@ class Tokenizer; class CPPCHECKLIB CheckUnusedFunctions : public Check { public: /** @brief This constructor is used when registering the CheckUnusedFunctions */ - CheckUnusedFunctions() : Check(myName()) { - } + CheckUnusedFunctions() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckUnusedFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} static void clear() { instance.mFunctions.clear(); @@ -101,13 +99,12 @@ private: class CPPCHECKLIB FunctionUsage { public: - FunctionUsage() : lineNumber(0), usedSameFile(false), usedOtherFile(false) { - } + FunctionUsage() : lineNumber(0), usedSameFile(false), usedOtherFile(false) {} std::string filename; unsigned int lineNumber; - bool usedSameFile; - bool usedOtherFile; + bool usedSameFile; + bool usedOtherFile; }; std::map mFunctions; diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 0e3f3feb8..4c34b2569 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -115,8 +115,7 @@ public: _read(read), _write(write), _modified(modified), - _allocateMemory(allocateMemory) { - } + _allocateMemory(allocateMemory) {} /** variable is used.. set both read+write */ void use() { @@ -1479,7 +1478,7 @@ bool CheckUnusedVar::isRecordTypeWithoutSideEffects(const Type* type) // a type that has no side effects (no constructors and no members with constructors) /** @todo false negative: check constructors for side effects */ const std::pair::iterator,bool> found=mIsRecordTypeWithoutSideEffectsMap.insert( - std::pair(type,false)); //Initialize with side effects for possible recursions + std::pair(type,false)); //Initialize with side effects for possible recursions bool & withoutSideEffects = found.first->second; if (!found.second) return withoutSideEffects; @@ -1521,7 +1520,7 @@ bool CheckUnusedVar::isRecordTypeWithoutSideEffects(const Type* type) } const Function* initValueFunc = valueToken->function(); if (initValueFunc && !isFunctionWithoutSideEffects(*initValueFunc, valueToken, - std::list {})) { + std::list {})) { return withoutSideEffects = false; } } @@ -1575,7 +1574,7 @@ bool CheckUnusedVar::isEmptyType(const Type* type) // a type that has no variables and no constructor const std::pair::iterator,bool> found=mIsEmptyTypeMap.insert( - std::pair(type,false)); + std::pair(type,false)); bool & emptyType=found.first->second; if (!found.second) return emptyType; @@ -1597,7 +1596,7 @@ bool CheckUnusedVar::isEmptyType(const Type* type) } bool CheckUnusedVar::isFunctionWithoutSideEffects(const Function& func, const Token* functionUsageToken, - std::list checkedFuncs) + std::list checkedFuncs) { // no body to analyze if (!func.hasBody()) { diff --git a/lib/checkunusedvar.h b/lib/checkunusedvar.h index e44efef78..90c4b5db2 100644 --- a/lib/checkunusedvar.h +++ b/lib/checkunusedvar.h @@ -46,13 +46,11 @@ class Function; class CPPCHECKLIB CheckUnusedVar : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckUnusedVar() : Check(myName()) { - } + CheckUnusedVar() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckUnusedVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { diff --git a/lib/checkvaarg.cpp b/lib/checkvaarg.cpp index ec2fc037e..9b1388ec2 100644 --- a/lib/checkvaarg.cpp +++ b/lib/checkvaarg.cpp @@ -108,7 +108,7 @@ void CheckVaarg::va_list_usage() bool exitOnEndOfStatement = false; const Token* tok = var->nameToken()->next(); - for (; tok && tok != var->scope()->bodyEnd; tok = tok->next()) { + for (; tok && tok != var->scope()->bodyEnd; tok = tok->next()) { // Skip lambdas const Token* tok2 = findLambdaEndToken(tok); if (tok2) diff --git a/lib/checkvaarg.h b/lib/checkvaarg.h index 55021e145..393b34f3c 100644 --- a/lib/checkvaarg.h +++ b/lib/checkvaarg.h @@ -41,12 +41,10 @@ class Tokenizer; class CPPCHECKLIB CheckVaarg : public Check { public: - CheckVaarg() : Check(myName()) { - } + CheckVaarg() : Check(myName()) {} CheckVaarg(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) - : Check(myName(), tokenizer, settings, errorLogger) { - } + : Check(myName(), tokenizer, settings, errorLogger) {} void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { CheckVaarg check(tokenizer, settings, errorLogger); diff --git a/lib/config.h b/lib/config.h index a0b63990f..3c4a4ccb3 100644 --- a/lib/config.h +++ b/lib/config.h @@ -21,8 +21,8 @@ // C++11 override #if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ >= 5)) \ - || (defined(__clang__) && (defined (__cplusplus)) && (__cplusplus >= 201103L)) \ - || defined(__CPPCHECK__) + || (defined(__clang__) && (defined (__cplusplus)) && (__cplusplus >= 201103L)) \ + || defined(__CPPCHECK__) # define OVERRIDE override # define FINAL final #else @@ -32,8 +32,8 @@ // C++11 noexcept #if (defined(__GNUC__) && (__GNUC__ >= 5)) \ - || (defined(__clang__) && (defined (__cplusplus)) && (__cplusplus >= 201103L)) \ - || defined(__CPPCHECK__) + || (defined(__clang__) && (defined (__cplusplus)) && (__cplusplus >= 201103L)) \ + || defined(__CPPCHECK__) # define NOEXCEPT noexcept #else # define NOEXCEPT @@ -41,8 +41,8 @@ // C++11 noreturn #if (defined(__GNUC__) && (__GNUC__ >= 5)) \ - || (defined(__clang__) && (defined (__cplusplus)) && (__cplusplus >= 201103L)) \ - || defined(__CPPCHECK__) + || (defined(__clang__) && (defined (__cplusplus)) && (__cplusplus >= 201103L)) \ + || defined(__CPPCHECK__) # define NORETURN [[noreturn]] #else # define NORETURN diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index c5acc46ca..2e8b8e543 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -329,8 +329,7 @@ CppCheck::CppCheck(ErrorLogger &errorLogger, , mTooManyConfigs(false) , mSimplify(true) , mExecuteCommand(executeCommand) -{ -} +{} CppCheck::~CppCheck() { @@ -1093,9 +1092,9 @@ static const char * pcreErrorCodeToString(const int pcreExecRet) return "An unexpected internal error has occurred. This error could be caused by a bug " "in PCRE or by overwriting of the compiled pattern (PCRE_ERROR_INTERNAL)"; case PCRE_ERROR_BADCOUNT: - return"This error is given if the value of the ovecsize argument is negative " - "(PCRE_ERROR_BADCOUNT)"; - case PCRE_ERROR_RECURSIONLIMIT : + return "This error is given if the value of the ovecsize argument is negative " + "(PCRE_ERROR_BADCOUNT)"; + case PCRE_ERROR_RECURSIONLIMIT: return "The internal recursion limit, as specified by the match_limit_recursion " "field in a pcre_extra structure (or defaulted) was reached. " "See the description above (PCRE_ERROR_RECURSIONLIMIT)"; @@ -1512,9 +1511,7 @@ void CppCheck::reportInfo(const ErrorMessage &msg) } void CppCheck::reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, std::size_t /*sizedone*/, std::size_t /*sizetotal*/) -{ - -} +{} void CppCheck::bughuntingReport(const std::string &str) { diff --git a/lib/cppcheck.h b/lib/cppcheck.h index 03e31c3e2..3dd755a10 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -67,27 +67,27 @@ public: */ /** - * @brief Check the file. - * This function checks one given file for errors. - * @param path Path to the file to check. - * @return amount of errors found or 0 if none were found. - * @note You must set settings before calling this function (by calling - * settings()). - */ + * @brief Check the file. + * This function checks one given file for errors. + * @param path Path to the file to check. + * @return amount of errors found or 0 if none were found. + * @note You must set settings before calling this function (by calling + * settings()). + */ unsigned int check(const std::string &path); unsigned int check(const ImportProject::FileSettings &fs); /** - * @brief Check the file. - * This function checks one "virtual" file. The file is not read from - * the disk but the content is given in @p content. In errors the @p path - * is used as a filename. - * @param path Path to the file to check. - * @param content File content as a string. - * @return amount of errors found or 0 if none were found. - * @note You must set settings before calling this function (by calling - * settings()). - */ + * @brief Check the file. + * This function checks one "virtual" file. The file is not read from + * the disk but the content is given in @p content. In errors the @p path + * is used as a filename. + * @param path Path to the file to check. + * @param content File content as a string. + * @return amount of errors found or 0 if none were found. + * @note You must set settings before calling this function (by calling + * settings()). + */ unsigned int check(const std::string &path, const std::string &content); /** diff --git a/lib/ctu.cpp b/lib/ctu.cpp index de856d348..07573f458 100644 --- a/lib/ctu.cpp +++ b/lib/ctu.cpp @@ -55,8 +55,7 @@ CTU::FileInfo::Location::Location(const Tokenizer *tokenizer, const Token *tok) : fileName(tokenizer->list.file(tok)) , lineNumber(tok->linenr()) , column(tok->column()) -{ -} +{} std::string CTU::FileInfo::toString() const { @@ -151,15 +150,13 @@ CTU::FileInfo::CallBase::CallBase(const Tokenizer *tokenizer, const Token *callT , callArgNr(0) , callFunctionName(callToken->next()->astOperand1()->expressionString()) , location(CTU::FileInfo::Location(tokenizer, callToken)) -{ -} +{} CTU::FileInfo::NestedCall::NestedCall(const Tokenizer *tokenizer, const Function *myFunction, const Token *callToken) : CallBase(tokenizer, callToken) , myId(getFunctionId(tokenizer, myFunction)) , myArgNr(0) -{ -} +{} static std::string readAttrString(const tinyxml2::XMLElement *e, const char *attr, bool *error) { @@ -529,11 +526,11 @@ static bool findPath(const std::string &callId, } std::list CTU::FileInfo::getErrorPath(InvalidValueType invalidValue, - const CTU::FileInfo::UnsafeUsage &unsafeUsage, - const std::map> &callsMap, - const char info[], - const FunctionCall * * const functionCallPtr, - bool warning) + const CTU::FileInfo::UnsafeUsage &unsafeUsage, + const std::map> &callsMap, + const char info[], + const FunctionCall ** const functionCallPtr, + bool warning) { std::list locationList; diff --git a/lib/ctu.h b/lib/ctu.h index 5066030b5..f77650c68 100644 --- a/lib/ctu.h +++ b/lib/ctu.h @@ -97,9 +97,8 @@ namespace CTU { NestedCall(const std::string &myId, nonneg int myArgNr, const std::string &callId, nonneg int callArgnr, const std::string &callFunctionName, const Location &location) : CallBase(callId, callArgnr, callFunctionName, location), - myId(myId), - myArgNr(myArgNr) { - } + myId(myId), + myArgNr(myArgNr) {} NestedCall(const Tokenizer *tokenizer, const Function *myFunction, const Token *callToken); @@ -117,11 +116,11 @@ namespace CTU { std::map> getCallsMap() const; static std::list getErrorPath(InvalidValueType invalidValue, - const UnsafeUsage &unsafeUsage, - const std::map> &callsMap, - const char info[], - const FunctionCall * * const functionCallPtr, - bool warning); + const UnsafeUsage &unsafeUsage, + const std::map> &callsMap, + const char info[], + const FunctionCall ** const functionCallPtr, + bool warning); }; extern int maxCtuDepth; diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index 512878028..9cc1b10ad 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -69,8 +69,7 @@ static std::size_t calculateWarningHash(const TokenList *tokenList, const std::s ErrorMessage::ErrorMessage() : incomplete(false), severity(Severity::none), cwe(0U), certainty(Certainty::normal), hash(0) -{ -} +{} ErrorMessage::ErrorMessage(const std::list &callStack, const std::string& file1, Severity::SeverityType severity, const std::string &msg, const std::string &id, Certainty::CertaintyLevel certainty) : callStack(callStack), // locations for this error message @@ -180,9 +179,9 @@ ErrorMessage::ErrorMessage(const ErrorPath &errorPath, const TokenList *tokenLis ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errmsg) : incomplete(false), - severity(Severity::none), - cwe(0U), - certainty(Certainty::normal) + severity(Severity::none), + cwe(0U), + certainty(Certainty::normal) { const char * const unknown = ""; @@ -660,13 +659,11 @@ std::string ErrorLogger::callStackToString(const std::listfileIndex()), line(tok->linenr()), column(tok->column()), mOrigFileName(tokenList->getOrigFile(tok)), mFileName(tokenList->file(tok)) -{ -} +{} ErrorMessage::FileLocation::FileLocation(const Token* tok, const std::string &info, const TokenList* tokenList) : fileIndex(tok->fileIndex()), line(tok->linenr()), column(tok->column()), mOrigFileName(tokenList->getOrigFile(tok)), mFileName(tokenList->file(tok)), mInfo(info) -{ -} +{} std::string ErrorMessage::FileLocation::getfile(bool convert) const { @@ -749,9 +746,9 @@ std::string ErrorLogger::plistHeader(const std::string &version, const std::vect << " \r\n"; for (const std::string & file : files) ostr << " " << ErrorLogger::toxml(file) << "\r\n"; - ostr << " \r\n" - << " diagnostics\r\n" - << " \r\n"; + ostr << " \r\n" + << " diagnostics\r\n" + << " \r\n"; return ostr.str(); } diff --git a/lib/errorlogger.h b/lib/errorlogger.h index d5d52ac5c..aac73195b 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -55,8 +55,8 @@ namespace tinyxml2 { /// @{ /** - * Wrapper for error messages, provided by reportErr() - */ + * Wrapper for error messages, provided by reportErr() + */ class CPPCHECKLIB ErrorMessage { public: /** @@ -67,16 +67,13 @@ public: class CPPCHECKLIB FileLocation { public: FileLocation() - : fileIndex(0), line(0), column(0) { - } + : fileIndex(0), line(0), column(0) {} FileLocation(const std::string &file, int line, unsigned int column) - : fileIndex(0), line(line), column(column), mOrigFileName(file), mFileName(file) { - } + : fileIndex(0), line(line), column(column), mOrigFileName(file), mFileName(file) {} FileLocation(const std::string &file, const std::string &info, int line, unsigned int column) - : fileIndex(0), line(line), column(column), mOrigFileName(file), mFileName(file), mInfo(info) { - } + : fileIndex(0), line(line), column(column), mOrigFileName(file), mFileName(file), mInfo(info) {} FileLocation(const Token* tok, const TokenList* tokenList); FileLocation(const Token* tok, const std::string &info, const TokenList* tokenList); @@ -175,7 +172,7 @@ public: * or template to be used. E.g. "{file}:{line},{severity},{id},{message}" * @param templateLocation Format Empty string to use default output format * or template to be used. E.g. "{file}:{line},{info}" - * @return formatted string + * @return formatted string */ std::string toString(bool verbose, const std::string &templateFormat = emptyString, @@ -242,7 +239,7 @@ class CPPCHECKLIB ErrorLogger { protected: std::ofstream plistFile; public: - ErrorLogger() { } + ErrorLogger() {} virtual ~ErrorLogger() { if (plistFile.is_open()) { plistFile << ErrorLogger::plistFooter(); diff --git a/lib/exprengine.cpp b/lib/exprengine.cpp index 11abb0c86..2e5a95882 100644 --- a/lib/exprengine.cpp +++ b/lib/exprengine.cpp @@ -412,7 +412,7 @@ namespace { return tokenizer->isCPP(); } - ExprEngine::ValuePtr executeContract(const Function *function, ExprEngine::ValuePtr(*executeExpression)(const Token*, Data&)) { + ExprEngine::ValuePtr executeContract(const Function *function, ExprEngine::ValuePtr (*executeExpression)(const Token*, Data&)) { const auto it = settings->functionContracts.find(function->fullName()); if (it == settings->functionContracts.end()) return ExprEngine::ValuePtr(); @@ -434,7 +434,7 @@ namespace { return executeExpression(tokenList.front()->astTop(), *this); } - void contractConstraints(const Function *function, ExprEngine::ValuePtr(*executeExpression)(const Token*, Data&)) { + void contractConstraints(const Function *function, ExprEngine::ValuePtr (*executeExpression)(const Token*, Data&)) { auto value = executeContract(function, executeExpression); if (value) constraints.push_back(value); @@ -916,8 +916,7 @@ ExprEngine::ArrayValue::ArrayValue(const std::string &name, const ExprEngine::Ar : Value(name, ExprEngine::ValueType::ArrayValue) , pointer(arrayValue.pointer), nullPointer(arrayValue.nullPointer), uninitPointer(arrayValue.uninitPointer) , data(arrayValue.data), size(arrayValue.size) -{ -} +{} std::string ExprEngine::ArrayValue::getRange() const @@ -1112,7 +1111,7 @@ public: using ValueExpr = std::map; using AssertionList = std::vector; - class BailoutValueException: public ExprEngineException { + class BailoutValueException : public ExprEngineException { public: BailoutValueException() : ExprEngineException(nullptr, "Incomplete analysis") {} }; @@ -1130,8 +1129,7 @@ public: for (auto constraint : data->constraints) { try { solver.add(getConstraintExpr(constraint)); - } catch (const BailoutValueException &) { - } + } catch (const BailoutValueException &) {} } } diff --git a/lib/exprengine.h b/lib/exprengine.h index a01ea157f..600d3ef52 100644 --- a/lib/exprengine.h +++ b/lib/exprengine.h @@ -38,9 +38,9 @@ class Token; class Variable; #if defined(__GNUC__) && defined (__SIZEOF_INT128__) -typedef __int128_t int128_t; +typedef __int128_t int128_t; #else -typedef long long int128_t; +typedef long long int128_t; #ifdef _MSC_VER #pragma message(__FILE__ "(" _CRT_STRINGIZE(__LINE__) ")" ": warning: TODO No 128-bit integer type is available => Limited analysis of large integers...") #else @@ -74,8 +74,7 @@ namespace ExprEngine { public: explicit DataBase(const std::string ¤tFunction, const Settings *settings) : currentFunction(currentFunction) - , settings(settings) { - } + , settings(settings) {} virtual std::string getNewSymbolName() = 0; const std::string currentFunction; const Settings * const settings; @@ -125,7 +124,7 @@ namespace ExprEngine { ValueType type; }; - class UninitValue: public Value { + class UninitValue : public Value { public: UninitValue() : Value("?", ValueType::UninitValue) {} bool isEqual(const DataBase *dataBase, int value) const OVERRIDE { @@ -144,8 +143,7 @@ namespace ExprEngine { : Value(name, ValueType::IntRange) , minValue(minValue) , maxValue(maxValue) - , loopScope(nullptr) { - } + , loopScope(nullptr) {} std::string getRange() const OVERRIDE { if (minValue == maxValue) return str(minValue); @@ -165,8 +163,7 @@ namespace ExprEngine { FloatRange(const std::string &name, long double minValue, long double maxValue) : Value(name, ValueType::FloatRange) , minValue(minValue) - , maxValue(maxValue) { - } + , maxValue(maxValue) {} std::string getRange() const OVERRIDE { return std::to_string(minValue) + ":" + std::to_string(maxValue); @@ -192,7 +189,7 @@ namespace ExprEngine { }; // Array or pointer - class ArrayValue: public Value { + class ArrayValue : public Value { public: enum { MAXSIZE = 0x7fffffff }; @@ -219,7 +216,7 @@ namespace ExprEngine { std::vector size; }; - class StringLiteralValue: public Value { + class StringLiteralValue : public Value { public: StringLiteralValue(const std::string &name, const std::string &s) : Value(name, ValueType::StringLiteralValue), string(s) {} @@ -233,7 +230,7 @@ namespace ExprEngine { const std::string string; }; - class StructValue: public Value { + class StructValue : public Value { public: explicit StructValue(const std::string &name) : Value(name, ValueType::StructValue) {} @@ -259,7 +256,7 @@ namespace ExprEngine { std::map member; }; - class AddressOfValue: public Value { + class AddressOfValue : public Value { public: AddressOfValue(const std::string &name, int varId) : Value(name, ValueType::AddressOfValue) @@ -279,8 +276,7 @@ namespace ExprEngine { : Value(getName(binop, op1, op2), ValueType::BinOpResult) , binop(binop) , op1(op1) - , op2(op2) { - } + , op2(op2) {} bool isEqual(const DataBase *dataBase, int value) const OVERRIDE; bool isGreaterThan(const DataBase *dataBase, int value) const OVERRIDE; @@ -306,8 +302,7 @@ namespace ExprEngine { : Value(name, ValueType::IntegerTruncation) , inputValue(inputValue) , bits(bits) - , sign(sign) { - } + , sign(sign) {} std::string getSymbolicExpression() const OVERRIDE; @@ -316,7 +311,7 @@ namespace ExprEngine { char sign; }; - class FunctionCallArgumentValues: public Value { + class FunctionCallArgumentValues : public Value { public: explicit FunctionCallArgumentValues(const std::vector &argValues) : Value("argValues", ValueType::FunctionCallArgumentValues) @@ -337,7 +332,7 @@ namespace ExprEngine { } }; - typedef std::function Callback; + typedef std::function Callback; /** Execute all functions */ void CPPCHECKLIB executeAllFunctions(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings, const std::vector &callbacks, std::ostream &report); diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index fdf324e7e..4180d20d6 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -82,7 +82,7 @@ struct ForwardTraversal { return evalCond(tok, ctx).second; } - template)> + template )> Progress traverseTok(T* tok, std::function f, bool traverseUnknown, T** out = nullptr) { if (Token::Match(tok, "asm|goto|continue|setjmp|longjmp")) return Break(); @@ -117,7 +117,7 @@ struct ForwardTraversal { return Progress::Continue; } - template)> + template )> Progress traverseRecursive(T* tok, std::function f, bool traverseUnknown, unsigned int recursion=0) { if (!tok) return Progress::Continue; @@ -142,7 +142,7 @@ struct ForwardTraversal { return Progress::Continue; } - template)> + template )> Progress traverseConditional(T* tok, F f, bool traverseUnknown) { if (Token::Match(tok, "?|&&|%oror%") && tok->astOperand1() && tok->astOperand2()) { T* condTok = tok->astOperand1(); @@ -204,7 +204,7 @@ struct ForwardTraversal { return traverseRecursive(tok, f, false); } - template + template T* findRange(T* start, const Token* end, std::function pred) { for (T* tok = start; tok && tok != end; tok = tok->next()) { Analyzer::Action action = analyzer->analyze(tok, Analyzer::Direction::Forward); @@ -349,7 +349,7 @@ struct ForwardTraversal { changed |= isExpressionChanged(condTok, endBlock->link(), endBlock, settings, true); // Check for mutation in the condition changed |= nullptr != - findAstNode(condTok, [&](const Token* tok) { + findAstNode(condTok, [&](const Token* tok) { return isVariableChanged(tok, 0, settings, true); }); if (!changed) diff --git a/lib/forwardanalyzer.h b/lib/forwardanalyzer.h index e08f40f9b..a23c8a638 100644 --- a/lib/forwardanalyzer.h +++ b/lib/forwardanalyzer.h @@ -23,12 +23,12 @@ class Settings; class Token; -template class ValuePtr; +template class ValuePtr; Analyzer::Result valueFlowGenericForward(Token* start, - const Token* end, - const ValuePtr& a, - const Settings* settings); + const Token* end, + const ValuePtr& a, + const Settings* settings); Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const Settings* settings); diff --git a/lib/importproject.cpp b/lib/importproject.cpp index c4cd7f3ce..a1d0f28bb 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -315,7 +315,7 @@ void ImportProject::FileSettings::parseCommand(std::string command) std::string stddef; if (standard == "c++98" || standard == "gnu++98" || standard == "c++03" || standard == "gnu++03") { stddef = "199711L"; - } else if (standard == "c++11" || standard == "gnu++11"|| standard == "c++0x" || standard == "gnu++0x") { + } else if (standard == "c++11" || standard == "gnu++11" || standard == "c++0x" || standard == "gnu++0x") { stddef = "201103L"; } else if (standard == "c++14" || standard == "gnu++14" || standard == "c++1y" || standard == "gnu++1y") { stddef = "201402L"; @@ -404,18 +404,18 @@ void ImportProject::importCompileCommands(std::istream &istr) std::ostringstream comm; if (obj.find("arguments") != obj.end()) { - if (obj[ "arguments" ].is< picojson::array >()) { - for (const picojson::value& arg : obj[ "arguments" ].get< picojson::array >()) { - if (arg.is< std::string >()) { - comm << arg.get< std::string >() << " "; + if (obj["arguments"].is()) { + for (const picojson::value& arg : obj["arguments"].get()) { + if (arg.is()) { + comm << arg.get() << " "; } } } else { return; } } else if (obj.find("command") != obj.end()) { - if (obj[ "command" ].is< std::string >()) { - comm << obj[ "command" ].get< std::string >(); + if (obj["command"].is()) { + comm << obj["command"].get(); } } else { return; @@ -1244,7 +1244,7 @@ void ImportProject::selectOneVsConfig(Settings::PlatformType platform) std::list ImportProject::getVSConfigs() { - return std::list (mAllVSConfigs.begin(), mAllVSConfigs.end()); + return std::list(mAllVSConfigs.begin(), mAllVSConfigs.end()); } void ImportProject::setRelativePaths(const std::string &filename) diff --git a/lib/library.cpp b/lib/library.cpp index 05423828f..a41c1d5be 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -57,8 +57,7 @@ static void gettokenlistfromvalid(const std::string& valid, TokenList& tokenList } Library::Library() : bugHunting(false), mAllocId(0) -{ -} +{} Library::Error Library::load(const char exename[], const char path[]) { @@ -1228,7 +1227,7 @@ bool Library::isCompliantValidationExpression(const char* p) range = true; has_dot = false; has_E = false; - } else if ((*p == '-')|| (*p == '+')) + } else if ((*p == '-') || (*p == '+')) error |= (!std::isdigit(*(p + 1))); else if (*p == ',') { range = false; @@ -1387,7 +1386,7 @@ bool Library::isUse(const std::string& functionName) const } bool Library::isLeakIgnore(const std::string& functionName) const { - const std::unordered_map::const_iterator it = functions.find(functionName); + const std::unordered_map::const_iterator it = functions.find(functionName); if (it != functions.cend()) return it->second.leakignore; return false; @@ -1496,14 +1495,14 @@ const std::string& Library::blockend(const std::string &file) const bool Library::iskeyword(const std::string &file, const std::string &keyword) const { - const std::map >::const_iterator it = + const std::map>::const_iterator it = mKeywords.find(Path::getFilenameExtensionInLowerCase(file)); return (it != mKeywords.end() && it->second.count(keyword)); } bool Library::isimporter(const std::string& file, const std::string &importer) const { - const std::map >::const_iterator it = + const std::map>::const_iterator it = mImporters.find(Path::getFilenameExtensionInLowerCase(file)); return (it != mImporters.end() && it->second.count(importer) > 0); } diff --git a/lib/library.h b/lib/library.h index dd2e20e66..105e45edf 100644 --- a/lib/library.h +++ b/lib/library.h @@ -62,11 +62,11 @@ public: explicit Error(ErrorCode e) : errorcode(e) {} template Error(ErrorCode e, T&& r) : errorcode(e), reason(r) {} - ErrorCode errorcode; - std::string reason; + ErrorCode errorcode; + std::string reason; }; - Error load(const char exename [], const char path []); + Error load(const char exename[], const char path[]); Error load(const tinyxml2::XMLDocument &doc); /** this is primarily meant for unit tests. it only returns true/false */ @@ -213,8 +213,7 @@ public: opLessAllowed(true), hasInitializerListConstructor(false), unstableErase(false), - unstableInsert(false) { - } + unstableInsert(false) {} enum class Action { RESIZE, CLEAR, PUSH, POP, FIND, INSERT, ERASE, CHANGE_CONTENT, CHANGE, CHANGE_INTERNAL, @@ -268,23 +267,22 @@ public: optional(false), variadic(false), iteratorInfo(), - direction(Direction::DIR_UNKNOWN) { - } + direction(Direction::DIR_UNKNOWN) {} - bool notbool; - bool notnull; - int notuninit; - bool formatstr; - bool strz; - bool optional; - bool variadic; - std::string valid; + bool notbool; + bool notnull; + int notuninit; + bool formatstr; + bool strz; + bool optional; + bool variadic; + std::string valid; class IteratorInfo { public: IteratorInfo() : container(0), it(false), first(false), last(false) {} - int container; + int container; bool it; bool first; bool last; @@ -441,8 +439,8 @@ public: const SmartPointer* detectSmartPointer(const Token* tok) const; struct PodType { - unsigned int size; - char sign; + unsigned int size; + char sign; enum class Type { NO, BOOL, CHAR, SHORT, INT, LONG, LONGLONG } stdtype; }; const struct PodType *podtype(const std::string &name) const { @@ -457,8 +455,7 @@ public: , mLong(false) , mPointer(false) , mPtrPtr(false) - , mConstPtr(false) { - } + , mConstPtr(false) {} bool operator == (const PlatformType & type) const { return (mSigned == type.mSigned && mUnsigned == type.mUnsigned && @@ -585,10 +582,10 @@ private: std::map mReportErrors; std::map mProcessAfterCode; std::set mMarkupExtensions; // file extensions of markup files - std::map > mKeywords; // keywords for code in the library + std::map> mKeywords; // keywords for code in the library std::map mExecutableBlocks; // keywords for blocks of executable code std::map mExporters; // keywords that export variables/functions to libraries (meta-code/macros) - std::map > mImporters; // keywords that import variables/functions + std::map> mImporters; // keywords that import variables/functions std::map mReflection; // invocation of reflection std::unordered_map mPodTypes; // pod types std::map mPlatformTypes; // platform independent typedefs diff --git a/lib/matchcompiler.h b/lib/matchcompiler.h index 4ffb1f07d..ed9034000 100644 --- a/lib/matchcompiler.h +++ b/lib/matchcompiler.h @@ -24,13 +24,12 @@ namespace MatchCompiler { - template + template class ConstString { public: typedef const char(&StringRef)[n]; explicit ConstString(StringRef s) - :_s(s) { - } + : _s(s) {} operator StringRef() const { return _s; @@ -40,32 +39,32 @@ namespace MatchCompiler { StringRef _s; }; - template + template inline bool equalN(const char s1[], const char s2[]) { return (*s1 == *s2) && equalN(s1+1, s2+1); } - template <> - inline bool equalN<0>(const char [], const char []) + template<> + inline bool equalN<0>(const char[], const char[]) { return true; } - template + template inline bool operator==(const std::string & s1, ConstString const & s2) { return equalN(s1.c_str(), s2); } - template + template inline bool operator!=(const std::string & s1, ConstString const & s2) { return !operator==(s1,s2); } - template - inline ConstString makeConstString(const char(&s)[n]) + template + inline ConstString makeConstString(const char (&s)[n]) { return ConstString(s); } diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 6f98e4473..1b6cb1550 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -361,7 +361,7 @@ std::string MathLib::normalizeCharacterLiteral(const std::string& iLiteral) { std::string normalizedLiteral; const std::string::size_type iLiteralLen = iLiteral.size(); - for (std::string::size_type idx = 0; idx < iLiteralLen ; ++idx) { + for (std::string::size_type idx = 0; idx < iLiteralLen; ++idx) { if (iLiteral[idx] != '\\') { normalizedLiteral.push_back(iLiteral[idx]); continue; @@ -533,7 +533,7 @@ static double myStod(const std::string& str, std::string::const_iterator from, s int distance; if (std::string::npos == decimalsep) { distance = to - it; - } else if (decimalsep > (to - str.begin())) + } else if (decimalsep > (to - str.begin())) return 0.; // error handling?? else distance = int(decimalsep)-(from - str.begin()); @@ -1130,7 +1130,7 @@ std::string MathLib::subtract(const std::string &first, const std::string &secon } if (first == second) - return "0.0" ; + return "0.0"; double d1 = toDoubleNumber(first); double d2 = toDoubleNumber(second); diff --git a/lib/path.h b/lib/path.h index 8217d63b3..734e3ecdc 100644 --- a/lib/path.h +++ b/lib/path.h @@ -47,10 +47,10 @@ public: static std::string toNativeSeparators(std::string path); /** - * Convert path to use internal path separators. - * @param path Path string to convert. - * @return converted path. - */ + * Convert path to use internal path separators. + * @param path Path string to convert. + * @return converted path. + */ static std::string fromNativeSeparators(std::string path); /** @@ -84,17 +84,17 @@ public: static std::string removeQuotationMarks(std::string path); /** - * @brief Get an extension of the filename. - * @param path Path containing filename. - * @return Filename extension (containing the dot, e.g. ".h" or ".CPP"). - */ + * @brief Get an extension of the filename. + * @param path Path containing filename. + * @return Filename extension (containing the dot, e.g. ".h" or ".CPP"). + */ static std::string getFilenameExtension(const std::string &path); /** - * @brief Get an extension of the filename in lower case. - * @param path Path containing filename. - * @return Filename extension (containing the dot, e.g. ".h"). - */ + * @brief Get an extension of the filename in lower case. + * @param path Path containing filename. + * @return Filename extension (containing the dot, e.g. ".h"). + */ static std::string getFilenameExtensionInLowerCase(const std::string &path); /** @@ -111,18 +111,18 @@ public: static bool isAbsolute(const std::string& path); /** - * @brief Create a relative path from an absolute one, if absolute path is inside the basePaths. - * @param absolutePath Path to be made relative. - * @param basePaths Paths to which it may be made relative. - * @return relative path, if possible. Otherwise absolutePath is returned unchanged - */ + * @brief Create a relative path from an absolute one, if absolute path is inside the basePaths. + * @param absolutePath Path to be made relative. + * @param basePaths Paths to which it may be made relative. + * @return relative path, if possible. Otherwise absolutePath is returned unchanged + */ static std::string getRelativePath(const std::string& absolutePath, const std::vector& basePaths); /** - * @brief Get an absolute file path from a relative one. - * @param filePath File path to be made absolute. - * @return absolute path, if possible. Otherwise an empty path is returned - */ + * @brief Get an absolute file path from a relative one. + * @param filePath File path to be made absolute. + * @return absolute path, if possible. Otherwise an empty path is returned + */ static std::string getAbsoluteFilePath(const std::string& filePath); /** @@ -174,10 +174,10 @@ public: static std::string stripDirectoryPart(const std::string &file); /** - * @brief Checks if a File exists - * @param file Path to be checked if it is a File - * @return true if given path is a File - */ + * @brief Checks if a File exists + * @param file Path to be checked if it is a File + * @return true if given path is a File + */ static bool fileExists(const std::string &file); }; diff --git a/lib/pathanalysis.cpp b/lib/pathanalysis.cpp index 7cb7edd4b..04b8bface 100644 --- a/lib/pathanalysis.cpp +++ b/lib/pathanalysis.cpp @@ -35,7 +35,7 @@ std::pair PathAnalysis::checkCond(const Token * tok, bool& known) }); // If all possible values are the same, then assume all paths have the same value if (it != tok->values().end() && std::all_of(it, tok->values().end(), [&](const ValueFlow::Value& v) { - if (v.isIntValue()) + if (v.isIntValue()) return v.intvalue == it->intvalue; return true; })) { @@ -161,7 +161,7 @@ void PathAnalysis::forward(const std::function& f) const bool reaches(const Token * start, const Token * dest, const Library& library, ErrorPath* errorPath) { - PathAnalysis::Info info = PathAnalysis{start, library} .forwardFind([&](const PathAnalysis::Info& i) { + PathAnalysis::Info info = PathAnalysis{start, library}.forwardFind([&](const PathAnalysis::Info& i) { return (i.tok == dest); }); if (!info.tok) diff --git a/lib/platform.cpp b/lib/platform.cpp index efd142efe..8ebc83b11 100644 --- a/lib/platform.cpp +++ b/lib/platform.cpp @@ -1,20 +1,20 @@ /* -* Cppcheck - A tool for static C/C++ code analysis -* Copyright (C) 2007-2021 Cppcheck team. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2021 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "platform.h" #include "path.h" diff --git a/lib/platform.h b/lib/platform.h index 999a72787..c2c0a078a 100644 --- a/lib/platform.h +++ b/lib/platform.h @@ -1,20 +1,20 @@ /* -* Cppcheck - A tool for static C/C++ code analysis -* Copyright (C) 2007-2020 Cppcheck team. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2020 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ //--------------------------------------------------------------------------- #ifndef platformH @@ -37,8 +37,8 @@ namespace tinyxml2 { namespace cppcheck { /** - * @brief Platform settings - */ + * @brief Platform settings + */ class CPPCHECKLIB Platform { private: static long long min_value(int bit) { @@ -129,9 +129,9 @@ namespace cppcheck { bool loadFromXmlDocument(const tinyxml2::XMLDocument *doc); /** - * @brief Returns true if platform type is Windows - * @return true if Windows platform type. - */ + * @brief Returns true if platform type is Windows + * @return true if Windows platform type. + */ bool isWindowsPlatform() const { return platformType == Win32A || platformType == Win32W || diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index c6be44a0f..9b735f8f0 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -50,12 +50,11 @@ static std::string trim(const std::string& s) return s.substr(beg, end - beg + 1); } -Directive::Directive(const std::string &_file, const int _linenr, const std::string &_str): +Directive::Directive(const std::string &_file, const int _linenr, const std::string &_str) : file(_file), linenr(_linenr), str(trim(_str)) -{ -} +{} std::atomic Preprocessor::missingIncludeFlag; std::atomic Preprocessor::missingSystemIncludeFlag; @@ -63,8 +62,7 @@ std::atomic Preprocessor::missingSystemIncludeFlag; char Preprocessor::macroChar = char(1); Preprocessor::Preprocessor(Settings& settings, ErrorLogger *errorLogger) : mSettings(settings), mErrorLogger(errorLogger) -{ -} +{} Preprocessor::~Preprocessor() { @@ -360,7 +358,7 @@ static bool isUndefined(const std::string &cfg, const std::set &und static bool getConfigsElseIsFalse(const std::vector &configs_if, const std::string &userDefines) { return std::any_of(configs_if.cbegin(), configs_if.cend(), - [=](const std::string &cfg) { + [=](const std::string &cfg) { return hasDefine(userDefines, cfg); }); } @@ -571,7 +569,7 @@ std::string Preprocessor::removeSpaceNearNL(const std::string &str) i + 1 >= str.size() || // treat end of file as newline str[i+1] == '\n' ) - ) { + ) { // Ignore space that has new line in either side of it } else { tmp.append(1, str[i]); @@ -912,7 +910,7 @@ bool Preprocessor::validateCfg(const std::string &cfg, const std::liststr() == "%") *result = result1 % result2; - else if (expr->str() == "<<") { - if (result2 < 0 || result1 < 0 || result2 >= MathLib::bigint_bits) { // don't perform UB + else if (expr->str() == "<<") { + if (result2 < 0 || result1 < 0 || result2 >= MathLib::bigint_bits) { // don't perform UB *error= true; } else { *result = result1 << result2; diff --git a/lib/programmemory.h b/lib/programmemory.h index 5d18c59f1..b4456cb65 100644 --- a/lib/programmemory.h +++ b/lib/programmemory.h @@ -59,7 +59,7 @@ struct ProgramMemoryState { }; using PMEvaluateFunction = - std::function; + std::function; void execute(const Token* expr, ProgramMemory* const programMemory, diff --git a/lib/reverseanalyzer.cpp b/lib/reverseanalyzer.cpp index 4481df841..1ecedc8e4 100644 --- a/lib/reverseanalyzer.cpp +++ b/lib/reverseanalyzer.cpp @@ -126,7 +126,7 @@ struct ReverseTraversal { throw InternalError(tok, "Cyclic reverse analysis."); i = tok->index(); if (tok == start || (tok->str() == "{" && (tok->scope()->type == Scope::ScopeType::eFunction || - tok->scope()->type == Scope::ScopeType::eLambda))) { + tok->scope()->type == Scope::ScopeType::eLambda))) { break; } if (Token::Match(tok, "return|break|continue")) diff --git a/lib/reverseanalyzer.h b/lib/reverseanalyzer.h index 32dfe6bf2..f8e075bd6 100644 --- a/lib/reverseanalyzer.h +++ b/lib/reverseanalyzer.h @@ -22,7 +22,7 @@ struct Analyzer; class Settings; class Token; -template +template class ValuePtr; void valueFlowGenericReverse(Token* start, const ValuePtr& a, const Settings* settings); diff --git a/lib/settings.cpp b/lib/settings.cpp index f4e16ce5a..7d68200cf 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -30,41 +30,41 @@ const char Settings::SafeChecks::XmlExternalVariables[] = "external-variables"; Settings::Settings() : bugHunting(false), - bugHuntingCheckFunctionMaxTime(60), - checkAllConfigurations(true), - checkConfiguration(false), - checkHeaders(true), - checkLibrary(false), - checkUnusedTemplates(true), - clang(false), - clangExecutable("clang"), - clangTidy(false), - daca(false), - debugBugHunting(false), - debugnormal(false), - debugSimplified(false), - debugtemplate(false), - debugwarnings(false), - dump(false), - enforcedLang(None), - exceptionHandling(false), - exitCode(0), - force(false), - inlineSuppressions(false), - jobs(1), - jointSuppressionReport(false), - loadAverage(0), - maxConfigs(12), - maxCtuDepth(2), - maxTemplateRecursion(100), - preprocessOnly(false), - quiet(false), - relativePaths(false), - reportProgress(false), - showtime(SHOWTIME_MODES::SHOWTIME_NONE), - verbose(false), - xml(false), - xml_version(2) + bugHuntingCheckFunctionMaxTime(60), + checkAllConfigurations(true), + checkConfiguration(false), + checkHeaders(true), + checkLibrary(false), + checkUnusedTemplates(true), + clang(false), + clangExecutable("clang"), + clangTidy(false), + daca(false), + debugBugHunting(false), + debugnormal(false), + debugSimplified(false), + debugtemplate(false), + debugwarnings(false), + dump(false), + enforcedLang(None), + exceptionHandling(false), + exitCode(0), + force(false), + inlineSuppressions(false), + jobs(1), + jointSuppressionReport(false), + loadAverage(0), + maxConfigs(12), + maxCtuDepth(2), + maxTemplateRecursion(100), + preprocessOnly(false), + quiet(false), + relativePaths(false), + reportProgress(false), + showtime(SHOWTIME_MODES::SHOWTIME_NONE), + verbose(false), + xml(false), + xml_version(2) { severity.setEnabled(Severity::error, true); certainty.setEnabled(Certainty::normal, true); diff --git a/lib/settings.h b/lib/settings.h index 2cfc2d60f..9c080a91a 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -217,8 +217,8 @@ public: unsigned int jobs; /** @brief Collect unmatched suppressions in one run. - * This delays the reporting until all files are checked. - * It is needed by checks that analyse the whole code base. */ + * This delays the reporting until all files are checked. + * It is needed by checks that analyse the whole code base. */ bool jointSuppressionReport; /** @brief --library= */ @@ -390,9 +390,9 @@ public: std::string addEnabled(const std::string &str); /** - * @brief Returns true if given value can be shown - * @return true if the value can be shown - */ + * @brief Returns true if given value can be shown + * @return true if the value can be shown + */ bool isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck=false) const; /** Is posix library specified? */ diff --git a/lib/summaries.h b/lib/summaries.h index a7c61dfce..0d9bd1da8 100644 --- a/lib/summaries.h +++ b/lib/summaries.h @@ -1,20 +1,20 @@ /* -* Cppcheck - A tool for static C/C++ code analysis -* Copyright (C) 2007-2021 Cppcheck team. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2021 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ //--------------------------------------------------------------------------- #ifndef summariesH diff --git a/lib/suppressions.h b/lib/suppressions.h index 0310ebf60..e066b63a3 100644 --- a/lib/suppressions.h +++ b/lib/suppressions.h @@ -182,7 +182,7 @@ public: /** * @brief Create an xml dump of suppressions * @param out stream to write XML to - */ + */ void dump(std::ostream &out) const; /** diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index af89f1acb..7cda6eef9 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1832,14 +1832,14 @@ Variable::Variable(const Token *name_, const std::string &clangType, const Token const Token *typeEnd, nonneg int index_, AccessControl access_, const Type *type_, const Scope *scope_) : mNameToken(name_), - mTypeStartToken(typeStart), - mTypeEndToken(typeEnd), - mIndex(index_), - mAccess(access_), - mFlags(0), - mType(type_), - mScope(scope_), - mValueType(nullptr) + mTypeStartToken(typeStart), + mTypeEndToken(typeEnd), + mIndex(index_), + mAccess(access_), + mFlags(0), + mType(type_), + mScope(scope_), + mValueType(nullptr) { if (!mTypeStartToken && mTypeEndToken) { mTypeStartToken = mTypeEndToken; @@ -2118,21 +2118,21 @@ Function::Function(const Tokenizer *mTokenizer, const Token *tokDef, const Token *tokArgDef) : tokenDef(tokDef), - argDef(tokArgDef), - token(nullptr), - arg(nullptr), - retDef(nullptr), - retType(nullptr), - functionScope(nullptr), - nestedIn(scope), - initArgCount(0), - type(eFunction), - access(AccessControl::Public), - noexceptArg(nullptr), - throwArg(nullptr), - templateDef(nullptr), - functionPointerUsage(nullptr), - mFlags(0) + argDef(tokArgDef), + token(nullptr), + arg(nullptr), + retDef(nullptr), + retType(nullptr), + functionScope(nullptr), + nestedIn(scope), + initArgCount(0), + type(eFunction), + access(AccessControl::Public), + noexceptArg(nullptr), + throwArg(nullptr), + templateDef(nullptr), + functionPointerUsage(nullptr), + mFlags(0) { // operator function if (::isOperator(tokenDef)) { @@ -2238,21 +2238,21 @@ Function::Function(const Tokenizer *mTokenizer, Function::Function(const Token *tokenDef, const std::string &clangType) : tokenDef(tokenDef), - argDef(nullptr), - token(nullptr), - arg(nullptr), - retDef(nullptr), - retType(nullptr), - functionScope(nullptr), - nestedIn(nullptr), - initArgCount(0), - type(eFunction), - access(AccessControl::Public), - noexceptArg(nullptr), - throwArg(nullptr), - templateDef(nullptr), - functionPointerUsage(nullptr), - mFlags(0) + argDef(nullptr), + token(nullptr), + arg(nullptr), + retDef(nullptr), + retType(nullptr), + functionScope(nullptr), + nestedIn(nullptr), + initArgCount(0), + type(eFunction), + access(AccessControl::Public), + noexceptArg(nullptr), + throwArg(nullptr), + templateDef(nullptr), + functionPointerUsage(nullptr), + mFlags(0) { // operator function if (::isOperator(tokenDef)) { @@ -3633,9 +3633,9 @@ void SymbolDatabase::printOut(const char *title) const } std::cout << std::endl; std::cout << " needInitialization: " << (type->needInitialization == Type::NeedInitialization::Unknown ? "Unknown" : - type->needInitialization == Type::NeedInitialization::True ? "True" : - type->needInitialization == Type::NeedInitialization::False ? "False" : - "Invalid") << std::endl; + type->needInitialization == Type::NeedInitialization::True ? "True" : + type->needInitialization == Type::NeedInitialization::False ? "False" : + "Invalid") << std::endl; std::cout << " derivedFrom[" << type->derivedFrom.size() << "] = ("; std::size_t count = type->derivedFrom.size(); @@ -4047,7 +4047,7 @@ const Function * Function::getOverriddenFunctionRecursive(const ::Type* baseType // avoid endless recursion, see #5289 Crash: Stack overflow in isImplicitlyVirtual_rec when checking SVN and // #5590 with a loop within the class hierarchy. const Function *func = getOverriddenFunctionRecursive(derivedFromType, foundAllBaseClasses); - if (func) { + if (func) { return func; } } @@ -4083,8 +4083,7 @@ Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope * function(nullptr), enumType(nullptr), enumClass(false) -{ -} +{} Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_) : check(check_), @@ -4386,7 +4385,7 @@ const Variable *Scope::getVariable(const std::string &varname) const static const Token* skipPointers(const Token* tok) { - while (Token::Match(tok, "*|&|&&") || (Token::Match(tok, "( [*&]") && Token::Match(tok->link()->next(), "(|["))) { + while (Token::Match(tok, "*|&|&&") || (Token::Match(tok, "( [*&]") && Token::Match(tok->link()->next(), "(|["))) { tok = tok->next(); if (tok->strAt(-1) == "(" && Token::Match(tok, "%type% ::")) tok = tok->tokAt(2); @@ -4628,7 +4627,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const const std::vector & derivedFrom = scope->definedType->derivedFrom; for (const Type::BaseInfo & i : derivedFrom) { const Type *derivedFromType = i.type; - if (derivedFromType && derivedFromType ->classScope) { + if (derivedFromType && derivedFromType->classScope) { enumerator = derivedFromType->classScope->findEnumerator(tokStr); if (enumerator) @@ -5598,7 +5597,7 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n namespace { -#define C_KEYWORDS\ +#define C_KEYWORDS \ "_Alignas", "_Alignof", "_Atomic", "_Bool", "_Complex", "_Generic", "_Imaginary", "_Noreturn", \ "_Static_assert", "_Thread_local", "auto", "break", "case", "char", "const", "continue", "default", \ "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "inline", "int", "long", \ diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index c4545411b..32b21f428 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -57,7 +57,7 @@ enum class AccessControl { Public, Protected, Private, Global, Namespace, Argume * @brief Array dimension information. */ struct Dimension { - Dimension() : tok(nullptr), num(0), known(true) { } + Dimension() : tok(nullptr), num(0), known(true) {} const Token *tok; ///< size token MathLib::bigint num; ///< (assumed) dimension length when size is a number, 0 if not known @@ -77,8 +77,7 @@ public: class BaseInfo { public: BaseInfo() : - type(nullptr), nameTok(nullptr), access(AccessControl::Public), isVirtual(false) { - } + type(nullptr), nameTok(nullptr), access(AccessControl::Public), isVirtual(false) {} std::string name; const Type* type; @@ -93,8 +92,7 @@ public: struct FriendInfo { FriendInfo() : - nameStart(nullptr), nameEnd(nullptr), type(nullptr) { - } + nameStart(nullptr), nameEnd(nullptr), type(nullptr) {} const Token* nameStart; const Token* nameEnd; @@ -146,17 +144,17 @@ public: const Function* getFunction(const std::string& funcName) const; /** - * Check for circulare dependencies, i.e. loops within the class hierarchy - * @param ancestors list of ancestors. For internal usage only, clients should not supply this argument. - * @return true if there is a circular dependency - */ + * Check for circulare dependencies, i.e. loops within the class hierarchy + * @param ancestors list of ancestors. For internal usage only, clients should not supply this argument. + * @return true if there is a circular dependency + */ bool hasCircularDependencies(std::set* ancestors = nullptr) const; /** - * Check for dependency - * @param ancestor potential ancestor - * @return true if there is a dependency - */ + * Check for dependency + * @param ancestor potential ancestor + * @return true if there is a dependency + */ bool findDependency(const Type* ancestor) const; bool isDerivedFrom(const std::string & ancestor) const; @@ -164,7 +162,7 @@ public: class CPPCHECKLIB Enumerator { public: - explicit Enumerator(const Scope * scope_) : scope(scope_), name(nullptr), value(0), start(nullptr), end(nullptr), value_known(false) { } + explicit Enumerator(const Scope * scope_) : scope(scope_), name(nullptr), value(0), start(nullptr), end(nullptr), value_known(false) {} const Scope * scope; const Token * name; MathLib::bigint value; @@ -226,14 +224,14 @@ public: nonneg int index_, AccessControl access_, const Type *type_, const Scope *scope_, const Settings* settings) : mNameToken(name_), - mTypeStartToken(start_), - mTypeEndToken(end_), - mIndex(index_), - mAccess(access_), - mFlags(0), - mType(type_), - mScope(scope_), - mValueType(nullptr) { + mTypeStartToken(start_), + mTypeEndToken(end_), + mIndex(index_), + mAccess(access_), + mFlags(0), + mType(type_), + mScope(scope_), + mValueType(nullptr) { evaluate(settings); } @@ -559,13 +557,13 @@ public: } /** - * Checks if the variable is an STL type ('std::') - * E.g.: - * std::string s; - * ... - * sVar->isStlType() == true - * @return true if it is an stl type and its type matches any of the types in 'stlTypes' - */ + * Checks if the variable is an STL type ('std::') + * E.g.: + * std::string s; + * ... + * sVar->isStlType() == true + * @return true if it is an stl type and its type matches any of the types in 'stlTypes' + */ bool isStlType() const { return getFlag(fIsStlType); } @@ -617,17 +615,17 @@ public: } /** - * Determine whether it's a floating number type - * @return true if the type is known and it's a floating type (float, double and long double) or a pointer/array to it - */ + * Determine whether it's a floating number type + * @return true if the type is known and it's a floating type (float, double and long double) or a pointer/array to it + */ bool isFloatingType() const { return getFlag(fIsFloatType); } /** - * Determine whether it's an enumeration type - * @return true if the type is known and it's an enumeration type - */ + * Determine whether it's an enumeration type + * @return true if the type is known and it's an enumeration type + */ bool isEnumType() const { return type() && type()->isEnumType(); } @@ -1227,56 +1225,56 @@ public: ValueType() : sign(UNKNOWN_SIGN), - type(UNKNOWN_TYPE), - bits(0), - pointer(0U), - constness(0U), - typeScope(nullptr), - smartPointerType(nullptr), - smartPointerTypeToken(nullptr), - smartPointer(nullptr), - container(nullptr), - containerTypeToken(nullptr) + type(UNKNOWN_TYPE), + bits(0), + pointer(0U), + constness(0U), + typeScope(nullptr), + smartPointerType(nullptr), + smartPointerTypeToken(nullptr), + smartPointer(nullptr), + container(nullptr), + containerTypeToken(nullptr) {} ValueType(enum Sign s, enum Type t, nonneg int p) : sign(s), - type(t), - bits(0), - pointer(p), - constness(0U), - typeScope(nullptr), - smartPointerType(nullptr), - smartPointerTypeToken(nullptr), - smartPointer(nullptr), - container(nullptr), - containerTypeToken(nullptr) + type(t), + bits(0), + pointer(p), + constness(0U), + typeScope(nullptr), + smartPointerType(nullptr), + smartPointerTypeToken(nullptr), + smartPointer(nullptr), + container(nullptr), + containerTypeToken(nullptr) {} ValueType(enum Sign s, enum Type t, nonneg int p, nonneg int c) : sign(s), - type(t), - bits(0), - pointer(p), - constness(c), - typeScope(nullptr), - smartPointerType(nullptr), - smartPointerTypeToken(nullptr), - smartPointer(nullptr), - container(nullptr), - containerTypeToken(nullptr) + type(t), + bits(0), + pointer(p), + constness(c), + typeScope(nullptr), + smartPointerType(nullptr), + smartPointerTypeToken(nullptr), + smartPointer(nullptr), + container(nullptr), + containerTypeToken(nullptr) {} ValueType(enum Sign s, enum Type t, nonneg int p, nonneg int c, const std::string& otn) : sign(s), - type(t), - bits(0), - pointer(p), - constness(c), - typeScope(nullptr), - smartPointerType(nullptr), - smartPointerTypeToken(nullptr), - smartPointer(nullptr), - container(nullptr), - containerTypeToken(nullptr), - originalTypeName(otn) + type(t), + bits(0), + pointer(p), + constness(c), + typeScope(nullptr), + smartPointerType(nullptr), + smartPointerTypeToken(nullptr), + smartPointer(nullptr), + container(nullptr), + containerTypeToken(nullptr), + originalTypeName(otn) {} static ValueType parseDecl(const Token *type, const Settings *settings); diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 1869b446c..770dd259d 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -263,13 +263,11 @@ bool TemplateSimplifier::TokenAndName::isAliasToken(const Token *tok) const TemplateSimplifier::TemplateSimplifier(Tokenizer *tokenizer) : mTokenizer(tokenizer), mTokenList(tokenizer->list), mSettings(tokenizer->mSettings), - mErrorLogger(tokenizer->mErrorLogger), mChanged(false) -{ -} + mErrorLogger(tokenizer->mErrorLogger), mChanged(false) +{} TemplateSimplifier::~TemplateSimplifier() -{ -} +{} void TemplateSimplifier::checkComplicatedSyntaxErrorsInTemplates() { @@ -687,8 +685,8 @@ void TemplateSimplifier::addInstantiation(Token *token, const std::string &scope // check if instantiation already exists before adding it std::list::iterator it = std::find(mTemplateInstantiations.begin(), - mTemplateInstantiations.end(), - instantiation); + mTemplateInstantiations.end(), + instantiation); if (it == mTemplateInstantiations.end()) mTemplateInstantiations.emplace_back(instantiation); @@ -1193,8 +1191,8 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration) tok2 = tok2->link(); else if (Token::Match(tok2, "%type% <") && (tok2->strAt(2) == ">" || templateParameters(tok2->next()))) { std::list::iterator ti = std::find_if(mTemplateInstantiations.begin(), - mTemplateInstantiations.end(), - FindToken(tok2)); + mTemplateInstantiations.end(), + FindToken(tok2)); if (ti != mTemplateInstantiations.end()) mTemplateInstantiations.erase(ti); ++indentlevel; @@ -1212,8 +1210,8 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration) // don't strip args from uninstantiated templates std::list::iterator ti2 = std::find_if(mTemplateInstantiations.begin(), - mTemplateInstantiations.end(), - FindName(declaration.name())); + mTemplateInstantiations.end(), + FindName(declaration.name())); if (ti2 == mTemplateInstantiations.end()) continue; @@ -1318,8 +1316,8 @@ void TemplateSimplifier::simplifyTemplateAliases() // Create template instance.. if (Token::Match(tok1, "%name% <")) { const std::list::iterator it = std::find_if(mTemplateInstantiations.begin(), - mTemplateInstantiations.end(), - FindToken(tok1)); + mTemplateInstantiations.end(), + FindToken(tok1)); if (it != mTemplateInstantiations.end()) addInstantiation(tok2, it->scope()); } @@ -1583,7 +1581,7 @@ void TemplateSimplifier::expandTemplate( const bool isSpecialization = templateDeclaration.isSpecialization(); const bool isVariable = templateDeclaration.isVariable(); struct newInstantiation { - newInstantiation(Token *t, const std::string &s) : token(t), scope(s) { } + newInstantiation(Token *t, const std::string &s) : token(t), scope(s) {} Token *token; std::string scope; }; @@ -1614,8 +1612,8 @@ void TemplateSimplifier::expandTemplate( } else { if (it != mTemplateForwardDeclarationsMap.end()) { std::list::iterator it1 = std::find_if(mTemplateForwardDeclarations.begin(), - mTemplateForwardDeclarations.end(), - FindToken(it->second)); + mTemplateForwardDeclarations.end(), + FindToken(it->second)); if (it1 != mTemplateForwardDeclarations.end()) mMemberFunctionsToDelete.push_back(*it1); } @@ -2011,8 +2009,8 @@ void TemplateSimplifier::expandTemplate( tok3 = tok3->next(); std::list::iterator it = std::find_if(mTemplateDeclarations.begin(), - mTemplateDeclarations.end(), - FindToken(startOfTemplateDeclaration)); + mTemplateDeclarations.end(), + FindToken(startOfTemplateDeclaration)); if (it != mTemplateDeclarations.end()) mMemberFunctionsToDelete.push_back(*it); } @@ -3283,7 +3281,7 @@ void TemplateSimplifier::replaceTemplateUsage( const std::list &typeStringsUsedInTemplateInstantiation, const std::string &newName) { - std::list< std::pair > removeTokens; + std::list> removeTokens; for (Token *nameTok = mTokenList.front(); nameTok; nameTok = nameTok->next()) { if (!Token::Match(nameTok, "%name% <") || Token::Match(nameTok, "template|const_cast|dynamic_cast|reinterpret_cast|static_cast")) @@ -3793,10 +3791,10 @@ void TemplateSimplifier::simplifyTemplates( } const bool instantiated = simplifyTemplateInstantiations( - *iter1, - specializations, - maxtime, - expandedtemplates); + *iter1, + specializations, + maxtime, + expandedtemplates); if (instantiated) mInstantiatedTemplates.push_back(*iter1); } @@ -3827,16 +3825,16 @@ void TemplateSimplifier::simplifyTemplates( // remove out of line member functions while (!mMemberFunctionsToDelete.empty()) { const std::list::iterator it = std::find_if(mTemplateDeclarations.begin(), - mTemplateDeclarations.end(), - FindToken(mMemberFunctionsToDelete.begin()->token())); + mTemplateDeclarations.end(), + FindToken(mMemberFunctionsToDelete.begin()->token())); // multiple functions can share the same declaration so make sure it hasn't already been deleted if (it != mTemplateDeclarations.end()) { removeTemplate(it->token()); mTemplateDeclarations.erase(it); } else { const std::list::iterator it1 = std::find_if(mTemplateForwardDeclarations.begin(), - mTemplateForwardDeclarations.end(), - FindToken(mMemberFunctionsToDelete.begin()->token())); + mTemplateForwardDeclarations.end(), + FindToken(mMemberFunctionsToDelete.begin()->token())); // multiple functions can share the same declaration so make sure it hasn't already been deleted if (it1 != mTemplateForwardDeclarations.end()) { removeTemplate(it1->token()); diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index fe1343ee5..727f5f81b 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -170,7 +170,7 @@ public: const std::string & fullName() const { return mFullName; } - const Token * nameToken() const { + const Token * nameToken() const { return mNameToken; } const Token * paramEnd() const { diff --git a/lib/timer.cpp b/lib/timer.cpp index 10f63c519..a403d3a14 100644 --- a/lib/timer.cpp +++ b/lib/timer.cpp @@ -29,7 +29,7 @@ - add unit tests - for --showtime (needs input file) - for Timer* classes -*/ + */ namespace { using dataElementType = std::pair; @@ -51,7 +51,7 @@ void TimerResults::showResults(SHOWTIME_MODES mode) const std::sort(data.begin(), data.end(), more_second_sec); size_t ordinal = 1; // maybe it would be nice to have an ordinal in output later! - for (std::vector::const_iterator iter=data.begin() ; iter!=data.end(); ++iter) { + for (std::vector::const_iterator iter=data.begin(); iter!=data.end(); ++iter) { const double sec = iter->second.seconds(); const double secAverage = sec / (double)(iter->second.mNumberOfResults); overallData.mClocks += iter->second.mClocks; diff --git a/lib/timer.h b/lib/timer.h index a3206100a..a26f8d14f 100644 --- a/lib/timer.h +++ b/lib/timer.h @@ -35,7 +35,7 @@ enum class SHOWTIME_MODES { class CPPCHECKLIB TimerResultsIntf { public: - virtual ~TimerResultsIntf() { } + virtual ~TimerResultsIntf() {} virtual void addResults(const std::string& str, std::clock_t clocks) = 0; }; @@ -46,8 +46,7 @@ struct TimerResultsData { TimerResultsData() : mClocks(0) - , mNumberOfResults(0) { - } + , mNumberOfResults(0) {} double seconds() const { const double ret = (double)((unsigned long)mClocks) / (double)CLOCKS_PER_SEC; @@ -57,8 +56,7 @@ struct TimerResultsData { class CPPCHECKLIB TimerResults : public TimerResultsIntf { public: - TimerResults() { - } + TimerResults() {} void showResults(SHOWTIME_MODES mode) const; void addResults(const std::string& str, std::clock_t clocks) OVERRIDE; diff --git a/lib/token.cpp b/lib/token.cpp index fef9899e0..f5b3bd5e7 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -57,10 +57,10 @@ Token::~Token() } /* -* Get a TokenRange which starts at this token and contains every token following it in order up to but not including 't' -* e.g. for the sequence of tokens A B C D E, C.until(E) would yield the Range C D -* note t can be nullptr to iterate all the way to the end. -*/ + * Get a TokenRange which starts at this token and contains every token following it in order up to but not including 't' + * e.g. for the sequence of tokens A B C D E, C.until(E) would yield the Range C D + * note t can be nullptr to iterate all the way to the end. + */ ConstTokenRange Token::until(const Token* t) const { return ConstTokenRange(this, t); @@ -117,9 +117,9 @@ void Token::update_property_info() else if (mStr.size() <= 2 && !mLink && (mStr == "==" || mStr == "!=" || - mStr == "<" || + mStr == "<" || mStr == "<=" || - mStr == ">" || + mStr == ">" || mStr == ">=")) tokType(eComparisonOp); else if (mStr == "<=>") @@ -153,7 +153,7 @@ static const std::unordered_set stdTypes = { "bool" , "size_t" , "void" , "wchar_t" - }; +}; void Token::update_property_isStandardType() { @@ -2023,7 +2023,7 @@ static bool removeContradiction(std::list& values) using ValueIterator = std::list::iterator; -template +template static ValueIterator removeAdjacentValues(std::list& values, ValueIterator x, Iterator start, Iterator last) { if (!isAdjacent(*x, **start)) @@ -2209,7 +2209,7 @@ void Token::assignProgressValues(Token *tok) ++total_count; int count = 0; for (Token *tok2 = tok; tok2; tok2 = tok2->next()) - tok2->mImpl->mProgressValue = count++ * 100 / total_count; + tok2->mImpl->mProgressValue = count++ *100 / total_count; } void Token::assignIndexes() @@ -2284,10 +2284,10 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok) if (vars.empty()) return nullptr; if (std::all_of( - vars.begin(), vars.end(), [&](const Variable* var) { - return var->type() == vars.front()->type(); + vars.begin(), vars.end(), [&](const Variable* var) { + return var->type() == vars.front()->type(); })) - return vars.front()->type(); + return vars.front()->type(); } return nullptr; @@ -2380,7 +2380,7 @@ bool Token::hasKnownValue() const bool Token::hasKnownValue(ValueFlow::Value::ValueType t) const { return mImpl->mValues && - std::any_of(mImpl->mValues->begin(), mImpl->mValues->end(), [&](const ValueFlow::Value& value) { + std::any_of(mImpl->mValues->begin(), mImpl->mValues->end(), [&](const ValueFlow::Value& value) { return value.isKnown() && value.valueType == t; }); } @@ -2443,7 +2443,7 @@ const ValueFlow::Value* Token::getMovedValue() const return nullptr; const auto it = std::find_if(mImpl->mValues->begin(), mImpl->mValues->end(), [](const ValueFlow::Value& value) { return value.isMovedValue() && !value.isImpossible() && - value.moveKind != ValueFlow::Value::MoveKind::NonMovedVariable; + value.moveKind != ValueFlow::Value::MoveKind::NonMovedVariable; }); return it == mImpl->mValues->end() ? nullptr : &*it; } diff --git a/lib/token.h b/lib/token.h index a160c2688..daa176d02 100644 --- a/lib/token.h +++ b/lib/token.h @@ -215,8 +215,8 @@ public: void deleteNext(nonneg int count = 1); /** - * Unlink and delete the previous 'count' tokens. - */ + * Unlink and delete the previous 'count' tokens. + */ void deletePrevious(nonneg int count = 1); /** @@ -1010,14 +1010,14 @@ public: } /** - * Associate this token with given type - * @param t Type to be associated - */ + * Associate this token with given type + * @param t Type to be associated + */ void type(const ::Type *t); /** - * @return a pointer to the type associated with this token. - */ + * @return a pointer to the type associated with this token. + */ const ::Type *type() const { return mTokType == eType ? mImpl->mType : nullptr; } @@ -1029,8 +1029,8 @@ public: static std::string typeStr(const Token* tok); /** - * @return a pointer to the Enumerator associated with this token. - */ + * @return a pointer to the Enumerator associated with this token. + */ const Enumerator *enumerator() const { return mTokType == eEnumerator ? mImpl->mEnumerator : nullptr; } @@ -1092,10 +1092,10 @@ public: Token* nextArgumentBeforeCreateLinks2() const; /** - * @return the first token of the next template argument. Does only work on template argument - * lists. Requires that Tokenizer::createLinks2() has been called before. - * Returns 0, if there is no next argument. - */ + * @return the first token of the next template argument. Does only work on template argument + * lists. Requires that Tokenizer::createLinks2() has been called before. + * Returns 0, if there is no next argument. + */ Token* nextTemplateArgument() const; /** diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 954a0e804..5dc6a4d8d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -52,11 +52,9 @@ namespace { // in order to store information about the scope struct VarIdScopeInfo { VarIdScopeInfo() - :isExecutable(false), isStructInit(false), isEnum(false), startVarid(0) { - } + : isExecutable(false), isStructInit(false), isEnum(false), startVarid(0) {} VarIdScopeInfo(bool isExecutable, bool isStructInit, bool isEnum, nonneg int startVarid) - :isExecutable(isExecutable), isStructInit(isStructInit), isEnum(isEnum), startVarid(startVarid) { - } + : isExecutable(isExecutable), isStructInit(isStructInit), isEnum(isEnum), startVarid(startVarid) {} const bool isExecutable; const bool isStructInit; @@ -161,8 +159,7 @@ Tokenizer::Tokenizer() : , mMaxTime(std::time(0) + MAXTIME) #endif , mPreprocessor(nullptr) -{ -} +{} Tokenizer::Tokenizer(const Settings *settings, ErrorLogger *errorLogger) : list(settings), @@ -410,7 +407,7 @@ Token * Tokenizer::deleteInvalidTypedef(Token *typeDef) namespace { struct Space { - Space() : bodyEnd(nullptr), bodyEnd2(nullptr), isNamespace(false) { } + Space() : bodyEnd(nullptr), bodyEnd2(nullptr), isNamespace(false) {} std::string className; const Token * bodyEnd; // for body contains typedef define const Token * bodyEnd2; // for body contains typedef using @@ -2225,7 +2222,7 @@ bool Tokenizer::simplifyUsing() ScopeInfo3 scopeInfo; ScopeInfo3 *currentScope = &scopeInfo; struct Using { - Using(Token *start, Token *end) : startTok(start), endTok(end) { } + Using(Token *start, Token *end) : startTok(start), endTok(end) {} Token *startTok; Token *endTok; }; @@ -3533,7 +3530,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map >& structMembers, + std::map>& structMembers, nonneg int *varId) const { Token *tok = *tok1; @@ -3599,9 +3596,9 @@ void Tokenizer::setVarIdStructMembers(Token **tok1, void Tokenizer::setVarIdClassDeclaration(const Token * const startToken, - const VariableMap &variableMap, - const nonneg int scopeStartVarId, - std::map >& structMembers) + const VariableMap &variableMap, + const nonneg int scopeStartVarId, + std::map>& structMembers) { // end of scope const Token * const endToken = startToken->link(); @@ -3680,7 +3677,7 @@ void Tokenizer::setVarIdClassFunction(const std::string &classname, Token * const startToken, const Token * const endToken, const std::map &varlist, - std::map >& structMembers, + std::map>& structMembers, nonneg int *varId_) { for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) { @@ -3724,7 +3721,7 @@ void Tokenizer::setVarId() static const std::unordered_set notstart_c = { NOTSTART_C }; static const std::unordered_set notstart_cpp = { NOTSTART_C, "delete", "friend", "new", "throw", "using", "virtual", "explicit", "const_cast", "dynamic_cast", "reinterpret_cast", "static_cast", "template" - }; +}; void Tokenizer::setVarIdPass1() { @@ -3732,7 +3729,7 @@ void Tokenizer::setVarIdPass1() const std::unordered_set& notstart = (isC()) ? notstart_c : notstart_cpp; VariableMap variableMap; - std::map > structMembers; + std::map> structMembers; std::stack scopeStack; @@ -3753,7 +3750,7 @@ void Tokenizer::setVarIdPass1() if (!variableMap.leaveScope()) cppcheckError(tok); } else if (tok->str() == "{") { - scopeStack.push(VarIdScopeInfo(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", /*isEnum=*/false, *variableMap.getVarId())); + scopeStack.push(VarIdScopeInfo(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", /*isEnum=*/ false, *variableMap.getVarId())); // check if this '{' is a start of an "if" body const Token * ifToken = tok->previous(); @@ -4041,7 +4038,7 @@ void Tokenizer::setVarIdPass1() continue; } - if (!scopeStack.top().isEnum || !(Token::Match(tok->previous(), "{|,") && Token::Match(tok->next(), ",|=|}"))) { + if (!scopeStack.top().isEnum || !(Token::Match(tok->previous(), "{|,") && Token::Match(tok->next(), ",|=|}"))) { const std::map::const_iterator it = variableMap.find(tok->str()); if (it != variableMap.end()) { tok->varId(it->second); @@ -4161,7 +4158,7 @@ static Token * matchMemberFunctionName(const Member &func, const std::list > structMembers; + std::map> structMembers; // Member functions and variables in this source std::list allMemberFunctions; @@ -4223,7 +4220,7 @@ void Tokenizer::setVarIdPass2() std::list scopeInfo; // class members.. - std::map > varsByClass; + std::map> varsByClass; for (Token *tok = list.front(); tok; tok = tok->next()) { while (tok->str() == "}" && !scopeInfo.empty() && tok == scopeInfo.back().bodyEnd) scopeInfo.pop_back(); @@ -5741,7 +5738,7 @@ void Tokenizer::removeMacrosInGlobalScope() Token::eraseTokens(tok, tok2); tok->str(typeName); } - */ + */ // remove unknown macros before foo::foo( if (Token::Match(tok2, "%type% :: %type%")) { const Token *tok3 = tok2; @@ -6639,7 +6636,7 @@ bool Tokenizer::simplifyConditions() cmp.clear(); } - if (! cmp.empty()) { + if (!cmp.empty()) { tok = tok->next(); tok->deleteNext(2); @@ -7616,7 +7613,7 @@ void Tokenizer::simplifyIfAndWhileAssign() tok2->insertToken(tok->next()->str()); tok2->next()->varId(tok->next()->varId()); - while (! braces.empty()) { + while (!braces.empty()) { tok2->insertToken("("); Token::createMutualLinks(tok2->next(), braces.top()); braces.pop(); @@ -9112,7 +9109,7 @@ void Tokenizer::simplifyOffsetPointerReference() void Tokenizer::simplifyNestedStrcat() { for (Token *tok = list.front(); tok; tok = tok->next()) { - if (! Token::Match(tok, "[;{}] strcat ( strcat (")) { + if (!Token::Match(tok, "[;{}] strcat ( strcat (")) { continue; } @@ -9467,7 +9464,7 @@ void Tokenizer::eraseDeadCode(Token *begin, const Token *end) } else { tok = const_cast(tok2); } - } else if (Token::Match(tok, "[{};] default : ;")) { + } else if (Token::Match(tok, "[{};] default : ;")) { if (indentlevel == 1) break; //it seems like the function was called inside a case-default block. if (indentlevel == indentcase) @@ -10202,15 +10199,15 @@ void Tokenizer::findGarbageCode() const const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11; static const std::unordered_set nonConsecutiveKeywords{ "break", - "continue", - "for", - "goto", - "if", - "return", - "switch", - "throw", - "typedef", - "while" }; + "continue", + "for", + "goto", + "if", + "return", + "switch", + "throw", + "typedef", + "while" }; for (const Token *tok = tokens(); tok; tok = tok->next()) { // initialization: = { @@ -10299,15 +10296,15 @@ void Tokenizer::findGarbageCode() const // Keywords in global scope static const std::unordered_set nonGlobalKeywords{"break", - "continue", - "for", - "goto", - "if", - "return", - "switch", - "while", - "try", - "catch"}; + "continue", + "for", + "goto", + "if", + "return", + "switch", + "while", + "try", + "catch"}; for (const Token *tok = tokens(); tok; tok = tok->next()) { if (tok->str() == "{") tok = tok->link(); @@ -10327,7 +10324,7 @@ void Tokenizer::findGarbageCode() const if (!tok) syntaxError(switchToken); // Look for the end of the switch statement, i.e. the first semi-colon or '}' - for (; tok ; tok = tok->next()) { + for (; tok; tok = tok->next()) { if (tok->str() == "{") { tok = tok->link(); } @@ -10347,7 +10344,7 @@ void Tokenizer::findGarbageCode() const } } - for (const Token *tok = tokens(); tok ; tok = tok->next()) { + for (const Token *tok = tokens(); tok; tok = tok->next()) { if (!Token::simpleMatch(tok, "for (")) // find for loops continue; // count number of semicolons diff --git a/lib/tokenize.h b/lib/tokenize.h index 929b347d2..b9f02abce 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -61,7 +61,7 @@ class CPPCHECKLIB Tokenizer { class VariableMap { private: std::map mVariableId; - std::stack > > mScopeInfo; + std::stack>> mScopeInfo; mutable nonneg int mVarId; public: VariableMap(); @@ -146,22 +146,22 @@ public: void setVarIdPass2(); /** - * Basic simplification of tokenlist - * - * @param FileName The filename to run; used to do - * markup checks. - * - * @return false if there is an error that requires aborting - * the checking of this file. - */ + * Basic simplification of tokenlist + * + * @param FileName The filename to run; used to do + * markup checks. + * + * @return false if there is an error that requires aborting + * the checking of this file. + */ bool simplifyTokenList1(const char FileName[]); /** - * Most aggressive simplification of tokenlist - * - * @return false if there is an error that requires aborting - * the checking of this file. - */ + * Most aggressive simplification of tokenlist + * + * @return false if there is an error that requires aborting + * the checking of this file. + */ bool simplifyTokenList2(); /** @@ -243,20 +243,20 @@ public: void simplifyOffsetPointerDereference(); /** - * Simplify referencing a pointer offset: - * "Replace "&str[num]" => "(str + num)" - */ + * Simplify referencing a pointer offset: + * "Replace "&str[num]" => "(str + num)" + */ void simplifyOffsetPointerReference(); /** Insert array size where it isn't given */ void arraySize(); /** Simplify labels and 'case|default' syntaxes. - */ + */ void simplifyLabelsCaseDefault(); /** simplify case ranges (gcc extension) - */ + */ void simplifyCaseRange(); /** Remove macros in global scope */ @@ -268,9 +268,9 @@ public: void removePragma(); /** Remove undefined macro in class definition: - * class DLLEXPORT Fred { }; - * class Fred FINAL : Base { }; - */ + * class DLLEXPORT Fred { }; + * class Fred FINAL : Base { }; + */ void removeMacroInClassDef(); /** Remove unknown macro in variable declarations: PROGMEM char x; */ @@ -280,9 +280,9 @@ public: void removeRedundantAssignment(); /** Simplifies some realloc usage like - * 'x = realloc (0, n);' => 'x = malloc(n);' - * 'x = realloc (y, 0);' => 'x = 0; free(y);' - */ + * 'x = realloc (0, n);' => 'x = malloc(n);' + * 'x = realloc (y, 0);' => 'x = 0; free(y);' + */ void simplifyRealloc(); /** Add parentheses for sizeof: sizeof x => sizeof(x) */ @@ -745,23 +745,23 @@ private: void simplifyNamespaceStd(); /** - * Convert Microsoft memory functions - * CopyMemory(dst, src, len) -> memcpy(dst, src, len) - * FillMemory(dst, len, val) -> memset(dst, val, len) - * MoveMemory(dst, src, len) -> memmove(dst, src, len) - * ZeroMemory(dst, len) -> memset(dst, 0, len) - */ + * Convert Microsoft memory functions + * CopyMemory(dst, src, len) -> memcpy(dst, src, len) + * FillMemory(dst, len, val) -> memset(dst, val, len) + * MoveMemory(dst, src, len) -> memmove(dst, src, len) + * ZeroMemory(dst, len) -> memset(dst, 0, len) + */ void simplifyMicrosoftMemoryFunctions(); /** - * Convert Microsoft string functions - * _tcscpy -> strcpy - */ + * Convert Microsoft string functions + * _tcscpy -> strcpy + */ void simplifyMicrosoftStringFunctions(); /** - * Remove Borland code - */ + * Remove Borland code + */ void simplifyBorland(); /** @@ -779,8 +779,8 @@ private: void simplifyOverloadedOperators(); /** - * Remove [[attribute]] (C++11 and later) from TokenList - */ + * Remove [[attribute]] (C++11 and later) from TokenList + */ void simplifyCPPAttribute(); /** @@ -807,8 +807,8 @@ private: void simplifyCoroutines(); /** - * Prepare ternary operators with parentheses so that the AST can be created - * */ + * Prepare ternary operators with parentheses so that the AST can be created + * */ void prepareTernaryOpForAST(); /** @@ -829,17 +829,17 @@ private: void setVarIdClassDeclaration(const Token * const startToken, const VariableMap &variableMap, const nonneg int scopeStartVarId, - std::map >& structMembers); + std::map>& structMembers); void setVarIdStructMembers(Token **tok1, - std::map >& structMembers, + std::map>& structMembers, nonneg int *varId) const; void setVarIdClassFunction(const std::string &classname, Token * const startToken, const Token * const endToken, const std::map &varlist, - std::map >& structMembers, + std::map>& structMembers, nonneg int *varId_); /** @@ -906,32 +906,32 @@ public: } /** - * Helper function to check whether number is zero (0 or 0.0 or 0E+0) or not? - * @param s the string to check - * @return true in case is is zero and false otherwise. - */ + * Helper function to check whether number is zero (0 or 0.0 or 0E+0) or not? + * @param s the string to check + * @return true in case is is zero and false otherwise. + */ static bool isZeroNumber(const std::string &s); /** - * Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not? - * @param s the string to check - * @return true in case is is one and false otherwise. - */ + * Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not? + * @param s the string to check + * @return true in case is is one and false otherwise. + */ static bool isOneNumber(const std::string &s); /** - * Helper function to check whether number is two (2 or 0.2E+1 or 2E+0) or not? - * @param s the string to check - * @return true in case is is two and false otherwise. - */ + * Helper function to check whether number is two (2 or 0.2E+1 or 2E+0) or not? + * @param s the string to check + * @return true in case is is two and false otherwise. + */ static bool isTwoNumber(const std::string &s); /** - * Helper function to check for start of function execution scope. - * Do not use this in checks. Use the symbol database. - * @param tok pointer to end parentheses of parameter list - * @return pointer to start brace of function scope or nullptr if not start. - */ + * Helper function to check for start of function execution scope. + * Do not use this in checks. Use the symbol database. + * @param tok pointer to end parentheses of parameter list + * @return pointer to start brace of function scope or nullptr if not start. + */ static const Token * startOfExecutableScope(const Token * tok); #ifdef MAXTIME @@ -959,9 +959,9 @@ private: Token *processFunc(Token *tok2, bool inOperator) const; /** - * Get new variable id. - * @return new variable id - */ + * Get new variable id. + * @return new variable id + */ nonneg int newVarId() { return ++mVarId; } diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 74c80f5d6..20bd63a3b 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -703,7 +703,7 @@ static bool isQualifier(const Token* tok) return true; } -static void compileUnaryOp(Token *&tok, AST_state& state, void(*f)(Token *&tok, AST_state& state)) +static void compileUnaryOp(Token *&tok, AST_state& state, void (*f)(Token *&tok, AST_state& state)) { Token *unaryop = tok; if (f) { @@ -723,7 +723,7 @@ static void compileUnaryOp(Token *&tok, AST_state& state, void(*f)(Token *&tok, state.op.push(unaryop); } -static void compileBinOp(Token *&tok, AST_state& state, void(*f)(Token *&tok, AST_state& state)) +static void compileBinOp(Token *&tok, AST_state& state, void (*f)(Token *&tok, AST_state& state)) { Token *binop = tok; if (f) { @@ -791,7 +791,7 @@ static void compileTerm(Token *&tok, AST_state& state) } else if (Token::Match(tok, "sizeof !!(")) { compileUnaryOp(tok, state, compileExpression); state.op.pop(); - } else if (state.cpp && findCppTypeInitPar(tok)) { // int(0), int*(123), .. + } else if (state.cpp && findCppTypeInitPar(tok)) { // int(0), int*(123), .. tok = findCppTypeInitPar(tok); state.op.push(tok); tok = tok->tokAt(2); @@ -1646,7 +1646,7 @@ void TokenList::validateAst() const mTokensFrontBack.front->printOut(); }}; // Check for some known issues in AST to avoid crash/hang later on - std::set < const Token* > safeAstTokens; // list of "safe" AST tokens without endless recursion + std::set safeAstTokens; // list of "safe" AST tokens without endless recursion for (const Token *tok = mTokensFrontBack.front; tok; tok = tok->next()) { // Syntax error if binary operator only has 1 operand if ((tok->isAssignmentOp() || tok->isComparisonOp() || Token::Match(tok,"[|^/%]")) && tok->astOperand1() && !tok->astOperand2()) @@ -1663,7 +1663,7 @@ void TokenList::validateAst() const // Check for endless recursion const Token* parent = tok->astParent(); if (parent) { - std::set < const Token* > astTokens; // list of ancestors + std::set astTokens; // list of ancestors astTokens.insert(tok); do { if (safeAstTokens.find(parent) != safeAstTokens.end()) diff --git a/lib/tokenlist.h b/lib/tokenlist.h index 7b644f935..6a5cbd57d 100644 --- a/lib/tokenlist.h +++ b/lib/tokenlist.h @@ -149,9 +149,9 @@ public: std::string fileLine(const Token *tok) const; /** - * Calculates a 64-bit checksum of the token list used to compare - * multiple token lists with each other as quickly as possible. - */ + * Calculates a 64-bit checksum of the token list used to compare + * multiple token lists with each other as quickly as possible. + */ unsigned long long calculateChecksum() const; /** diff --git a/lib/tokenrange.h b/lib/tokenrange.h index 45934c43f..b1405821d 100644 --- a/lib/tokenrange.h +++ b/lib/tokenrange.h @@ -23,7 +23,7 @@ #include "config.h" -template)> +template )> class TokenRangeBase { T* mFront; T* mBack; diff --git a/lib/utils.cpp b/lib/utils.cpp index 4e65406f5..cb0de92c7 100644 --- a/lib/utils.cpp +++ b/lib/utils.cpp @@ -53,7 +53,7 @@ bool matchglob(const std::string& pattern, const std::string& name) { const char* p = pattern.c_str(); const char* n = name.c_str(); - std::stack > backtrack; + std::stack> backtrack; for (;;) { bool matching = true; diff --git a/lib/utils.h b/lib/utils.h index 8b697f505..c4f2a4925 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -28,14 +28,14 @@ #include struct SelectMapKeys { - template + template typename Pair::first_type operator()(const Pair& p) const { return p.first; } }; struct SelectMapValues { - template + template typename Pair::second_type operator()(const Pair& p) const { return p.second; } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 211fd59ab..753f3e4e3 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -379,7 +379,7 @@ static bool isZero(T x) return isEqual(x, T(0)); } -template +template static R calculate(const std::string& s, const T& x, const T& y) { auto wrap = [](T z) { @@ -430,7 +430,7 @@ static R calculate(const std::string& s, const T& x, const T& y) throw InternalError(nullptr, "Unknown operator: " + s); } -template +template static T calculate(const std::string& s, const T& x, const T& y) { return calculate(s, x, y); @@ -636,7 +636,7 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se nonneg int varId = 0; bool ret = false; visitAstNodes(parent->astOperand1(), - [&](const Token *t) { + [&](const Token *t) { if (t->varId()) { if (varId > 0 || value.varId != 0) ret = true; @@ -979,7 +979,7 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b if (!tok->isTemplateArg()) value.setKnown(); setTokenValue(tok, value, settings); - } catch (const std::exception &/*e*/) { + } catch (const std::exception & /*e*/) { // Bad character literal } } else if (tok->isNumber() && MathLib::isFloat(tok->str())) { @@ -1684,11 +1684,11 @@ static void valueFlowGlobalStaticVar(TokenList *tokenList, const Settings *setti } static Analyzer::Result valueFlowForward(Token* startToken, - const Token* endToken, - const Token* exprTok, - std::list values, - TokenList* const tokenlist, - const Settings* settings); + const Token* endToken, + const Token* exprTok, + std::list values, + TokenList* const tokenlist, + const Settings* settings); static void valueFlowReverse(TokenList* tokenlist, Token* tok, @@ -1803,8 +1803,7 @@ class SelectValueFromVarIdMapRange { using reference = value_type &; explicit Iterator(const M::const_iterator &it) - : mIt(it) { - } + : mIt(it) {} reference operator*() const { return mIt->second; @@ -1834,8 +1833,7 @@ class SelectValueFromVarIdMapRange { public: explicit SelectValueFromVarIdMapRange(const M *m) - : mMap(m) { - } + : mMap(m) {} Iterator begin() const { return Iterator(mMap->begin()); @@ -1902,7 +1900,7 @@ static bool bifurcateVariableChanged(const Variable* var, bool result = false; const Token* tok = start; while ((tok = findVariableChanged( - tok->next(), end, var->isPointer(), var->declarationId(), var->isGlobal(), settings, true))) { + tok->next(), end, var->isPointer(), var->declarationId(), var->isGlobal(), settings, true))) { if (Token::Match(tok->astParent(), "%assign%")) { if (!bifurcate(tok->astParent()->astOperand2(), varids, settings, depth - 1)) return true; @@ -2107,7 +2105,9 @@ struct ValueFlowAnalyzer : Analyzer { } } - virtual bool useSymbolicValues() const { return true; } + virtual bool useSymbolicValues() const { + return true; + } bool isSameSymbolicValue(const Token* tok, ErrorPath* errorPath = nullptr) const { @@ -2365,7 +2365,7 @@ struct SingleValueFlowAnalyzer : ValueFlowAnalyzer { if (value.isLifetimeValue()) return false; for (const auto& m: { - std::ref(getVars()), std::ref(getAliasedVars()) + std::ref(getVars()), std::ref(getAliasedVars()) }) { for (const auto& p:m.get()) { nonneg int varid = p.first; @@ -2540,11 +2540,11 @@ struct OppositeExpressionAnalyzer : ExpressionAnalyzer { }; static Analyzer::Result valueFlowForwardExpression(Token* startToken, - const Token* endToken, - const Token* exprTok, - const std::list& values, - const TokenList* const tokenlist, - const Settings* settings) + const Token* endToken, + const Token* exprTok, + const std::list& values, + const TokenList* const tokenlist, + const Settings* settings) { Analyzer::Result result{}; for (const ValueFlow::Value& v : values) { @@ -2578,7 +2578,7 @@ static const Token* parseBinaryIntOp(const Token* expr, MathLib::bigint& known) return varTok; } -template +template void transformIntValues(std::list& values, F f) { std::transform(values.begin(), values.end(), values.begin(), [&](ValueFlow::Value x) { @@ -2596,22 +2596,22 @@ static const Token* solveExprValues(const Token* expr, std::liststr()[0]) { case '+': { transformIntValues(values, [&](MathLib::bigint x) { - return x - intval; - }); + return x - intval; + }); return solveExprValues(binaryTok, values); } case '*': { if (intval == 0) break; transformIntValues(values, [&](MathLib::bigint x) { - return x / intval; - }); + return x / intval; + }); return solveExprValues(binaryTok, values); } case '^': { transformIntValues(values, [&](MathLib::bigint x) { - return x ^ intval; - }); + return x ^ intval; + }); return solveExprValues(binaryTok, values); } } @@ -2627,11 +2627,11 @@ ValuePtr makeAnalyzer(const Token* exprTok, const ValueFlow::Value& va } static Analyzer::Result valueFlowForward(Token* startToken, - const Token* endToken, - const Token* exprTok, - std::list values, - TokenList* const tokenlist, - const Settings* settings) + const Token* endToken, + const Token* exprTok, + std::list values, + TokenList* const tokenlist, + const Settings* settings) { const Token* expr = solveExprValues(exprTok, values); return valueFlowForwardExpression(startToken, endToken, expr, values, tokenlist, settings); @@ -2770,12 +2770,12 @@ ValueFlow::Value getLifetimeObjValue(const Token *tok, bool inconclusive) return values.front(); } -template +template static std::vector getLifetimeTokens(const Token* tok, - bool escape, - ValueFlow::Value::ErrorPath errorPath, - Predicate pred, - int depth = 20) + bool escape, + ValueFlow::Value::ErrorPath errorPath, + Predicate pred, + int depth = 20) { if (!tok) return std::vector {}; @@ -2842,8 +2842,8 @@ static std::vector getLifetimeTokens(const Token* tok, lt.errorPath.emplace_back(returnTok, "Return reference."); lt.errorPath.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'."); std::vector arglts = LifetimeToken::setInconclusive( - getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, depth - returns.size()), - returns.size() > 1); + getLifetimeTokens(argTok, escape, std::move(lt.errorPath), pred, depth - returns.size()), + returns.size() > 1); result.insert(result.end(), arglts.begin(), arglts.end()); } } @@ -2855,8 +2855,8 @@ static std::vector getLifetimeTokens(const Token* tok, if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) { errorPath.emplace_back(tok->previous(), "Accessing container."); return LifetimeToken::setAddressOf( - getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, depth - 1), - false); + getLifetimeTokens(tok->tokAt(-2)->astOperand1(), escape, std::move(errorPath), pred, depth - 1), + false); } } } else if (Token::Match(tok, ".|::|[") || tok->isUnaryOp("*")) { @@ -3100,9 +3100,9 @@ bool isLifetimeBorrowed(const Token *tok, const Settings *settings) static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings); static void valueFlowLifetimeConstructor(Token *tok, - TokenList *tokenlist, - ErrorLogger *errorLogger, - const Settings *settings); + TokenList *tokenlist, + ErrorLogger *errorLogger, + const Settings *settings); static const Token* getEndOfVarScope(const Token* tok, const std::vector& vars) { @@ -3227,15 +3227,15 @@ struct LifetimeStore { ValueFlow::Value::LifetimeKind type = ValueFlow::Value::LifetimeKind::Object, bool inconclusive = false) : argtok(argtok), - message(message), - type(type), - errorPath(), - inconclusive(inconclusive), - forward(true), - mContext(nullptr) + message(message), + type(type), + errorPath(), + inconclusive(inconclusive), + forward(true), + mContext(nullptr) {} - template + template static void forEach(const std::vector& argtoks, const std::string& message, ValueFlow::Value::LifetimeKind type, @@ -3279,7 +3279,7 @@ struct LifetimeStore { return LifetimeStore{argtok2, "Passed to '" + tok->expressionString() + "'.", ValueFlow::Value::LifetimeKind::Object}; } - template + template bool byRef(Token* tok, TokenList* tokenlist, ErrorLogger* errorLogger, const Settings* settings, Predicate pred) const { if (!argtok) return false; @@ -3319,7 +3319,7 @@ struct LifetimeStore { }); } - template + template bool byVal(Token* tok, TokenList* tokenlist, ErrorLogger* errorLogger, const Settings* settings, Predicate pred) const { if (!argtok) return false; @@ -3385,7 +3385,7 @@ struct LifetimeStore { }); } - template + template void byDerefCopy(Token *tok, TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings, Predicate pred) const { if (!settings->certainty.isEnabled(Certainty::inconclusive) && inconclusive) return; @@ -3402,7 +3402,7 @@ struct LifetimeStore { continue; for (const Token *tok3 = tok; tok3 && tok3 != var->declEndToken(); tok3 = tok3->previous()) { if (tok3->varId() == var->declarationId()) { - LifetimeStore{tok3, message, type, inconclusive} .byVal(tok, tokenlist, errorLogger, settings, pred); + LifetimeStore{tok3, message, type, inconclusive}.byVal(tok, tokenlist, errorLogger, settings, pred); break; } } @@ -3445,19 +3445,19 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog // Check if lifetime is available to avoid adding the lifetime twice ValueFlow::Value val = getLifetimeObjValue(argTok); if (val.tokvalue) { - LifetimeStore{argTok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Iterator} .byVal( + LifetimeStore{argTok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Iterator}.byVal( tok->next(), tokenlist, errorLogger, settings); break; } } } else if (Token::Match(tok->tokAt(-2), "std :: ref|cref|tie|front_inserter|back_inserter")) { for (const Token *argtok : getArguments(tok)) { - LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object} .byRef( + LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byRef( tok->next(), tokenlist, errorLogger, settings); } } else if (Token::Match(tok->tokAt(-2), "std :: make_tuple|tuple_cat|make_pair|make_reverse_iterator|next|prev|move|bind")) { for (const Token *argtok : getArguments(tok)) { - LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object} .byVal( + LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byVal( tok->next(), tokenlist, errorLogger, settings); } } else if (Token::Match(tok->tokAt(-2), "%var% . push_back|push_front|insert|push|assign") && @@ -3468,10 +3468,10 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog if (n > 1 && Token::typeStr(args[n - 2]) == Token::typeStr(args[n - 1]) && (((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) || (astIsPointer(args[n - 2]) && astIsPointer(args[n - 1]))))) { - LifetimeStore{args.back(), "Added to container '" + vartok->str() + "'.", ValueFlow::Value::LifetimeKind::Object} .byDerefCopy( + LifetimeStore{args.back(), "Added to container '" + vartok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byDerefCopy( vartok, tokenlist, errorLogger, settings); } else if (!args.empty() && isLifetimeBorrowed(args.back(), settings)) { - LifetimeStore{args.back(), "Added to container '" + vartok->str() + "'.", ValueFlow::Value::LifetimeKind::Object} .byVal( + LifetimeStore{args.back(), "Added to container '" + vartok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byVal( vartok, tokenlist, errorLogger, settings); } } else if (tok->function()) { @@ -3517,10 +3517,10 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog } static void valueFlowLifetimeConstructor(Token* tok, - const Type* t, - TokenList* tokenlist, - ErrorLogger* errorLogger, - const Settings* settings) + const Type* t, + TokenList* tokenlist, + ErrorLogger* errorLogger, + const Settings* settings) { if (!Token::Match(tok, "(|{")) return; @@ -3531,7 +3531,7 @@ static void valueFlowLifetimeConstructor(Token* tok, // constructor, but make each lifetime inconclusive std::vector args = getArguments(tok); LifetimeStore::forEach( - args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, [&](LifetimeStore& ls) { + args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, [&](LifetimeStore& ls) { ls.inconclusive = true; ls.byVal(tok, tokenlist, errorLogger, settings); }); @@ -3547,7 +3547,7 @@ static void valueFlowLifetimeConstructor(Token* tok, LifetimeStore::forEach(args, "Passed to constructor of '" + t->name() + "'.", ValueFlow::Value::LifetimeKind::SubObject, - [&](const LifetimeStore& ls) { + [&](const LifetimeStore& ls) { if (it == scope->varlist.end()) return; const Variable& var = *it; @@ -3588,14 +3588,14 @@ static void valueFlowLifetimeConstructor(Token* tok, TokenList* tokenlist, Error // Assume range constructor if passed a pair of iterators if (astIsContainer(parent) && args.size() == 2 && astIsIterator(args[0]) && astIsIterator(args[1])) { LifetimeStore::forEach( - args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, [&](const LifetimeStore& ls) { + args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, [&](const LifetimeStore& ls) { ls.byDerefCopy(tok, tokenlist, errorLogger, settings); }); } else { LifetimeStore::forEach(args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, - [&](const LifetimeStore& ls) { + [&](const LifetimeStore& ls) { ls.byVal(tok, tokenlist, errorLogger, settings); }); } @@ -4206,14 +4206,14 @@ static void valueFlowSymbolicInfer(TokenList* tokenlist, SymbolDatabase* symbold MathLib::bigint rhsvalue = 0; const ValueFlow::Value* rhs = - ValueFlow::findValue(tok->astOperand2()->values(), nullptr, [&](const ValueFlow::Value& v) { + ValueFlow::findValue(tok->astOperand2()->values(), nullptr, [&](const ValueFlow::Value& v) { return v.isSymbolicValue() && v.tokvalue && v.tokvalue->exprId() == tok->astOperand1()->exprId(); }); if (rhs) rhsvalue = rhs->intvalue; MathLib::bigint lhsvalue = 0; const ValueFlow::Value* lhs = - ValueFlow::findValue(tok->astOperand1()->values(), nullptr, [&](const ValueFlow::Value& v) { + ValueFlow::findValue(tok->astOperand1()->values(), nullptr, [&](const ValueFlow::Value& v) { return v.isSymbolicValue() && v.tokvalue && v.tokvalue->exprId() == tok->astOperand2()->exprId(); }); if (lhs) @@ -4257,10 +4257,10 @@ static void valueFlowForwardAssign(Token* const tok, values.remove_if(std::mem_fn(&ValueFlow::Value::isLifetimeValue)); } if (std::all_of( - vars.begin(), vars.end(), [&](const Variable* var) { - return !var->isPointer() && !var->isSmartPointer(); + vars.begin(), vars.end(), [&](const Variable* var) { + return !var->isPointer() && !var->isSmartPointer(); })) - values.remove_if(std::mem_fn(&ValueFlow::Value::isTokValue)); + values.remove_if(std::mem_fn(&ValueFlow::Value::isTokValue)); if (tok->astParent()) { for (ValueFlow::Value& value : values) { std::string valueKind; @@ -4283,7 +4283,7 @@ static void valueFlowForwardAssign(Token* const tok, if (it->isIntValue()) it->intvalue = (it->intvalue != 0); if (it->isTokValue()) - it ->intvalue = (it->tokvalue != nullptr); + it->intvalue = (it->tokvalue != nullptr); } } @@ -4317,9 +4317,9 @@ static void valueFlowForwardAssign(Token* const tok, } static std::list truncateValues(std::list values, - const ValueType* dst, - const ValueType* src, - const Settings* settings) + const ValueType* dst, + const ValueType* src, + const Settings* settings) { if (!dst || !dst->isIntegral()) return values; @@ -4404,7 +4404,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat continue; std::list values = truncateValues( - tok->astOperand2()->values(), tok->astOperand1()->valueType(), tok->astOperand2()->valueType(), settings); + tok->astOperand2()->values(), tok->astOperand1()->valueType(), tok->astOperand2()->valueType(), settings); // Remove known values std::set types; if (tok->astOperand1()->hasKnownValue()) { @@ -4419,8 +4419,8 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat // Remove container size if its not a container if (!astIsContainer(tok->astOperand2())) values.remove_if([&](const ValueFlow::Value& value) { - return value.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE; - }); + return value.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE; + }); // Remove symbolic values that are the same as the LHS values.remove_if([&](const ValueFlow::Value& value) { if (value.isSymbolicValue() && value.tokvalue) @@ -4431,8 +4431,8 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat if ((tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->pointer == 0) || (tok->astOperand1()->variable() && tok->astOperand1()->variable()->isReference() && tok->astOperand1()->variable()->nameToken() == tok->astOperand1())) values.remove_if([&](const ValueFlow::Value& value) { - return value.isUninitValue(); - }); + return value.isUninitValue(); + }); if (values.empty()) continue; const bool init = vars.size() == 1 && vars.front()->nameToken() == tok->astOperand1(); @@ -4487,9 +4487,9 @@ static void insertNegateKnown(std::list& values, const std::li } static std::vector getExprVariables(const Token* expr, - const TokenList* tokenlist, - const SymbolDatabase* symboldatabase, - const Settings* settings) + const TokenList* tokenlist, + const SymbolDatabase* symboldatabase, + const Settings* settings) { std::vector result; FwdAnalysis fwdAnalysis(tokenlist->isCPP(), settings->library); @@ -4538,7 +4538,7 @@ struct ConditionHandler { ErrorLogger* errorLogger, const Settings* settings, const std::function< - void(const Condition& cond, Token* tok, const Scope* scope, const std::vector& vars)>& f) const { + void(const Condition& cond, Token* tok, const Scope* scope, const std::vector& vars)>& f) const { for (const Scope *scope : symboldatabase->functionScopes) { std::set aliased; for (Token *tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { @@ -4597,7 +4597,7 @@ struct ConditionHandler { symboldatabase, errorLogger, settings, - [&](const Condition& cond, Token* tok, const Scope*, const std::vector&) { + [&](const Condition& cond, Token* tok, const Scope*, const std::vector&) { if (cond.vartok->exprId() == 0) return; @@ -4673,8 +4673,8 @@ struct ConditionHandler { if (isExpressionChanged(cond.vartok, start, end, settings, tokenlist->isCPP())) { // If its reassigned in loop then analyze from the end if (!Token::Match(tok, "%assign%|++|--") && - findExpression(cond.vartok->exprId(), start, end, [&](const Token* tok2) { - return Token::Match(tok2->astParent(), "%assign%") && astIsLHS(tok2); + findExpression(cond.vartok->exprId(), start, end, [&](const Token* tok2) { + return Token::Match(tok2->astParent(), "%assign%") && astIsLHS(tok2); })) { // Start at the end of the loop body Token* bodyTok = top->link()->next(); @@ -4710,7 +4710,7 @@ struct ConditionHandler { symboldatabase, errorLogger, settings, - [&](const Condition& cond, Token* tok, const Scope* scope, const std::vector& vars) { + [&](const Condition& cond, Token* tok, const Scope* scope, const std::vector& vars) { if (Token::simpleMatch(tok->astParent(), "?")) return; const Token* top = tok->astTop(); @@ -5034,8 +5034,8 @@ static const ValueFlow::Value* getCompareIntValue(const std::listhasKnownIntValue()) return ValueFlow::Value{}; if (std::none_of(varTok->values().begin(), varTok->values().end(), [](const ValueFlow::Value& v) { - return v.isImpossible() && v.valueType == ValueFlow::Value::ValueType::INT; + return v.isImpossible() && v.valueType == ValueFlow::Value::ValueType::INT; })) { return ValueFlow::Value{}; } @@ -5204,7 +5204,7 @@ static bool valueFlowForLoop2(const Token *tok, // If a variable is reassigned in second expression, return false bool reassign = false; visitAstNodes(secondExpression, - [&](const Token *t) { + [&](const Token *t) { if (t->str() == "=" && t->astOperand1() && programMemory.hasValue(t->astOperand1()->varId())) // TODO: investigate what variable is assigned. reassign = true; @@ -5323,10 +5323,10 @@ static void valueFlowForLoopSimplify(Token * const bodyStart, const nonneg int v } static void valueFlowForLoopSimplifyAfter(Token* fortok, - nonneg int varid, - const MathLib::bigint num, - TokenList* tokenlist, - const Settings* settings) + nonneg int varid, + const MathLib::bigint num, + TokenList* tokenlist, + const Settings* settings) { const Token *vartok = nullptr; for (const Token *tok = fortok; tok; tok = tok->next()) { @@ -5710,7 +5710,7 @@ static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symbol // FIXME We must check if there is a return. See #9276 /* - valueFlowForwardVariable(tok->tokAt(3), + valueFlowForwardVariable(tok->tokAt(3), vartok->variable()->scope()->bodyEnd, vartok->variable(), vartok->varId(), @@ -5720,7 +5720,7 @@ static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symbol tokenlist, errorLogger, settings); - */ + */ } } } @@ -6253,9 +6253,9 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer { return Action::Read | Action::Write | Action::Incremental; if (rhs->valueType() && rhs->valueType()->container && rhs->valueType()->container->stdStringLike) { if (std::any_of(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value &rhsval) { - return rhsval.isKnown() && rhsval.isContainerSizeValue(); + return rhsval.isKnown() && rhsval.isContainerSizeValue(); })) - return Action::Read | Action::Write | Action::Incremental; + return Action::Read | Action::Write | Action::Incremental; } } else if (Token::Match(tok, "%name% . %name% (")) { Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2)); @@ -6315,10 +6315,10 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer { }; static Analyzer::Result valueFlowContainerForward(Token* startToken, - const Token* endToken, - const Token* exprTok, - const ValueFlow::Value& value, - TokenList* tokenlist) + const Token* endToken, + const Token* exprTok, + const ValueFlow::Value& value, + TokenList* tokenlist) { ContainerExpressionAnalyzer a(exprTok, value, tokenlist); return valueFlowGenericForward(startToken, endToken, a, tokenlist->getSettings()); @@ -6336,9 +6336,9 @@ static Analyzer::Result valueFlowContainerForwardRecursive(Token* top, } static Analyzer::Result valueFlowContainerForward(Token* startToken, - const Token* exprTok, - const ValueFlow::Value& value, - TokenList* tokenlist) + const Token* exprTok, + const ValueFlow::Value& value, + TokenList* tokenlist) { const Token* endToken = nullptr; const Function* f = Scope::nestedInFunction(startToken->scope()); @@ -6598,8 +6598,8 @@ static std::vector makeContainerSizeValue(const Token* tok, bo } static std::vector getInitListSize(const Token* tok, - const Library::Container* container, - bool known = true) + const Library::Container* container, + bool known = true) { std::vector args = getArguments(tok); // Strings don't use an init list @@ -7057,23 +7057,23 @@ static void valueFlowUnknownFunctionReturn(TokenList *tokenlist, const Settings ValueFlow::Value::Value(const Token* c, long long val) : valueType(ValueType::INT), - bound(Bound::Point), - intvalue(val), - tokvalue(nullptr), - floatValue(0.0), - moveKind(MoveKind::NonMovedVariable), - varvalue(val), - condition(c), - varId(0), - safe(false), - conditional(false), - defaultArg(false), - indirect(0), - path(0), - wideintvalue(0), - lifetimeKind(LifetimeKind::Object), - lifetimeScope(LifetimeScope::Local), - valueKind(ValueKind::Possible) + bound(Bound::Point), + intvalue(val), + tokvalue(nullptr), + floatValue(0.0), + moveKind(MoveKind::NonMovedVariable), + varvalue(val), + condition(c), + varId(0), + safe(false), + conditional(false), + defaultArg(false), + indirect(0), + path(0), + wideintvalue(0), + lifetimeKind(LifetimeKind::Object), + lifetimeScope(LifetimeScope::Local), + valueKind(ValueKind::Possible) { errorPath.emplace_back(c, "Assuming that condition '" + c->expressionString() + "' is not redundant"); } @@ -7240,8 +7240,8 @@ std::string ValueFlow::eitherTheConditionIsRedundant(const Token *condition) } const ValueFlow::Value* ValueFlow::findValue(const std::list& values, - const Settings* settings, - std::function pred) + const Settings* settings, + std::function pred) { const ValueFlow::Value* ret = nullptr; for (const ValueFlow::Value& v : values) { diff --git a/lib/valueflow.h b/lib/valueflow.h index 29a47d4ec..297795bcb 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -44,34 +44,34 @@ class Variable; namespace ValueFlow { struct increment { - template + template void operator()(T& x) const { x++; } }; struct decrement { - template + template void operator()(T& x) const { x--; } }; struct less { - template + template bool operator()(const T& x, const U& y) const { return x < y; } }; struct adjacent { - template + template bool operator()(const T& x, const U& y) const { return std::abs(x - y) == 1; } }; struct equalVisitor { - template + template void operator()(bool& result, T x, U y) const { result = !(x > y || x < y); } @@ -83,23 +83,23 @@ namespace ValueFlow { explicit Value(long long val = 0) : valueType(ValueType::INT), - bound(Bound::Point), - intvalue(val), - tokvalue(nullptr), - floatValue(0.0), - moveKind(MoveKind::NonMovedVariable), - varvalue(val), - condition(nullptr), - varId(0U), - safe(false), - conditional(false), - defaultArg(false), - indirect(0), - path(0), - wideintvalue(val), - lifetimeKind(LifetimeKind::Object), - lifetimeScope(LifetimeScope::Local), - valueKind(ValueKind::Possible) + bound(Bound::Point), + intvalue(val), + tokvalue(nullptr), + floatValue(0.0), + moveKind(MoveKind::NonMovedVariable), + varvalue(val), + condition(nullptr), + varId(0U), + safe(false), + conditional(false), + defaultArg(false), + indirect(0), + path(0), + wideintvalue(val), + lifetimeKind(LifetimeKind::Object), + lifetimeScope(LifetimeScope::Local), + valueKind(ValueKind::Possible) {} Value(const Token *c, long long val); @@ -144,7 +144,7 @@ namespace ValueFlow { return true; } - template + template static void visitValue(T& self, F f) { switch (self.valueType) { case ValueType::INT: @@ -170,19 +170,19 @@ namespace ValueFlow { struct compareVisitor { struct innerVisitor { - template + template void operator()(bool& result, Compare compare, T x, U y) const { result = compare(x, y); } }; - template + template void operator()(bool& result, const Value& rhs, Compare compare, T x) const { visitValue(rhs, std::bind(innerVisitor{}, std::ref(result), std::move(compare), x, std::placeholders::_1)); } }; - template + template bool compareValue(const Value& rhs, Compare compare) const { assert((!this->isSymbolicValue() && !rhs.isSymbolicValue()) || (this->valueType == rhs.valueType && this->tokvalue == rhs.tokvalue)); @@ -210,7 +210,7 @@ namespace ValueFlow { return !(*this == rhs); } - template )> + template )> bool equalTo(const T& x) const { bool result = false; visitValue(*this, std::bind(equalVisitor{}, std::ref(result), x, std::placeholders::_1)); @@ -473,8 +473,8 @@ ValueFlow::Value inferCondition(std::string op, MathLib::bigint val, const Token ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val); std::vector getLifetimeTokens(const Token* tok, - bool escape = false, - ValueFlow::Value::ErrorPath errorPath = ValueFlow::Value::ErrorPath{}); + bool escape = false, + ValueFlow::Value::ErrorPath errorPath = ValueFlow::Value::ErrorPath{}); bool hasLifetimeToken(const Token* tok, const Token* lifetime); diff --git a/lib/valueptr.h b/lib/valueptr.h index 466fd663e..9de8c2631 100644 --- a/lib/valueptr.h +++ b/lib/valueptr.h @@ -25,9 +25,9 @@ #include #include -template +template class CPPCHECKLIB ValuePtr { - template + template struct cloner { static T* apply(const T* x) { return new U(*static_cast(x)); @@ -41,7 +41,7 @@ public: ValuePtr() : mPtr(nullptr), mClone() {} - template + template // cppcheck-suppress noExplicitConstructor ValuePtr(const U& value) : mPtr(cloner::apply(&value)), mClone(&cloner::apply) {} @@ -57,7 +57,9 @@ public: return mPtr.release(); } - T* get() NOEXCEPT { return mPtr.get(); } + T* get() NOEXCEPT { + return mPtr.get(); + } const T* get() const NOEXCEPT { return mPtr.get(); } @@ -69,7 +71,9 @@ public: return *get(); } - T* operator->() NOEXCEPT { return get(); } + T* operator->() NOEXCEPT { + return get(); + } const T* operator->() const NOEXCEPT { return get(); } diff --git a/oss-fuzz/type2.cpp b/oss-fuzz/type2.cpp index 1daf59f36..61fbe8ded 100644 --- a/oss-fuzz/type2.cpp +++ b/oss-fuzz/type2.cpp @@ -109,9 +109,9 @@ static std::string functionStart() } static std::string generateExpression2_conditionalCode(const std::string &indent, - const uint8_t *data, - size_t dataSize, - uint8_t numberOfGlobalConstants) + const uint8_t *data, + size_t dataSize, + uint8_t numberOfGlobalConstants) { std::ostringstream code; @@ -168,18 +168,18 @@ std::string generateCode2(const uint8_t *data, size_t dataSize) // create global constants constexpr uint8_t numberOfGlobalConstants = 0; /* - const int numberOfGlobalConstants = getValue(data, dataSize, 5); - for (int nr = 1; nr <= numberOfGlobalConstants; nr++) { + const int numberOfGlobalConstants = getValue(data, dataSize, 5); + for (int nr = 1; nr <= numberOfGlobalConstants; nr++) { const char *types[4] = {"char", "int", "long long", "float"}; code << "const " << types[getValue(data, dataSize, 4)] << " globalconstant" << nr << " = " << generateExpression2_Expr(data, dataSize, nr - 1) << ";\n"; - } - */ + } + */ code << "int var1 = 1;\n" - "int var2 = 0;\n" - "int var3 = 1;\n" - "int var4 = 0;\n" - "int var5 = -1;\n\n"; + "int var2 = 0;\n" + "int var3 = 1;\n" + "int var4 = 0;\n" + "int var5 = -1;\n\n"; code << generateExpression2_conditionalCode("", data, dataSize, numberOfGlobalConstants); diff --git a/runformat b/runformat new file mode 100755 index 000000000..4f44597e8 --- /dev/null +++ b/runformat @@ -0,0 +1,42 @@ +#!/bin/bash +UNCRUSTIFY_VERSION="0.72.0" +UNCRUSTIFY="${UNCRUSTIFY-uncrustify}" + +DETECTED_VERSION=$("$UNCRUSTIFY" --version 2>&1 | grep -o -E '[0-9.]+') +if [ "$DETECTED_VERSION" != "${UNCRUSTIFY_VERSION}" ]; then + echo "You should use version: ${UNCRUSTIFY_VERSION}" + echo "Detected version: ${DETECTED_VERSION}" + exit 1 +fi + +# OS variables +[ $(uname -s) = "Darwin" ] && export OSX=1 && export UNIX=1 +[ $(uname -s) = "Linux" ] && export LINUX=1 && export UNIX=1 +uname -s | grep -q "_NT-" && export WINDOWS=1 + +if [ $OSX ] +then + export CPUCOUNT=$(sysctl -n hw.ncpu) +elif [ $LINUX ] +then + export CPUCOUNT=$(nproc) +else + export CPUCOUNT="1" +fi + +function formatCplusplus { + find $1 -iname '*.h' \ + -o -iname '*.c' \ + -o -iname '*.cpp' \ + | xargs -n 1 -P $CPUCOUNT -I{} -t $UNCRUSTIFY -c .uncrustify.cfg --no-backup {} + +} + +formatCplusplus cli/ +formatCplusplus democlient/ +formatCplusplus gui/ +formatCplusplus lib/ +formatCplusplus oss-fuzz/ +formatCplusplus test/ +formatCplusplus tools/ +formatCplusplus samples/ diff --git a/test/bug-hunting/cve/CVE-2018-19872/qppmhandler.cpp b/test/bug-hunting/cve/CVE-2018-19872/qppmhandler.cpp index e9f5a905f..b80ebcf9c 100644 --- a/test/bug-hunting/cve/CVE-2018-19872/qppmhandler.cpp +++ b/test/bug-hunting/cve/CVE-2018-19872/qppmhandler.cpp @@ -50,8 +50,8 @@ QT_BEGIN_NAMESPACE /***************************************************************************** - PBM/PGM/PPM (ASCII and RAW) image read/write functions - *****************************************************************************/ + PBM/PGM/PPM (ASCII and RAW) image read/write functions +*****************************************************************************/ static void discard_pbm_line(QIODevice *d) { @@ -66,8 +66,8 @@ static void discard_pbm_line(QIODevice *d) static int read_pbm_int(QIODevice *d) { char c; - int val = -1; - bool digit; + int val = -1; + bool digit; for (;;) { if (!d->getChar(&c)) // end of file break; @@ -134,23 +134,23 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q QImage::Format format; switch (type) { - case '1': // ascii PBM - case '4': // raw PBM - nbits = 1; - format = QImage::Format_Mono; - break; - case '2': // ascii PGM - case '5': // raw PGM - nbits = 8; - format = QImage::Format_Grayscale8; - break; - case '3': // ascii PPM - case '6': // raw PPM - nbits = 32; - format = QImage::Format_RGB32; - break; - default: - return false; + case '1': // ascii PBM + case '4': // raw PBM + nbits = 1; + format = QImage::Format_Mono; + break; + case '2': // ascii PGM + case '5': // raw PGM + nbits = 8; + format = QImage::Format_Grayscale8; + break; + case '3': // ascii PPM + case '6': // raw PPM + nbits = 32; + format = QImage::Format_RGB32; + break; + default: + return false; } raw = type >= '4'; @@ -343,95 +343,95 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy str += '\n'; switch (image.depth()) { - case 1: { - str.insert(1, '4'); - if (out->write(str, str.length()) != str.length()) + case 1: { + str.insert(1, '4'); + if (out->write(str, str.length()) != str.length()) + return false; + w = (w+7)/8; + for (uint y=0; ywrite((char*)line, w)) return false; - w = (w+7)/8; - for (uint y=0; ywrite((char*)line, w)) - return false; - } - } - break; - - case 8: { - str.insert(1, gray ? '5' : '6'); - str.append("255\n"); - if (out->write(str, str.length()) != str.length()) - return false; - uint bpl = w * (gray ? 1 : 3); - uchar *buf = new uchar[bpl]; - if (image.format() == QImage::Format_Indexed8) { - QVector color = image.colorTable(); - for (uint y=0; ywrite((char*)buf, bpl)) - return false; - } - } else { - for (uint y=0; ywrite((char*)buf, bpl)) - return false; - } - } - delete [] buf; - break; } + } + break; - case 32: { - str.insert(1, '6'); - str.append("255\n"); - if (out->write(str, str.length()) != str.length()) - return false; - uint bpl = w * 3; - uchar *buf = new uchar[bpl]; + case 8: { + str.insert(1, gray ? '5' : '6'); + str.append("255\n"); + if (out->write(str, str.length()) != str.length()) + return false; + uint bpl = w * (gray ? 1 : 3); + uchar *buf = new uchar[bpl]; + if (image.format() == QImage::Format_Indexed8) { + QVector color = image.colorTable(); for (uint y=0; y(image.constScanLine(y)); + const uchar *b = image.constScanLine(y); uchar *p = buf; uchar *end = buf+bpl; - while (p < end) { - QRgb rgb = *b++; - *p++ = qRed(rgb); - *p++ = qGreen(rgb); - *p++ = qBlue(rgb); + if (gray) { + while (p < end) { + uchar g = (uchar)qGray(color[*b++]); + *p++ = g; + } + } else { + while (p < end) { + QRgb rgb = color[*b++]; + *p++ = qRed(rgb); + *p++ = qGreen(rgb); + *p++ = qBlue(rgb); + } + } + if (bpl != (uint)out->write((char*)buf, bpl)) + return false; + } + } else { + for (uint y=0; ywrite((char*)buf, bpl)) return false; } - delete [] buf; - break; } + delete[] buf; + break; + } + + case 32: { + str.insert(1, '6'); + str.append("255\n"); + if (out->write(str, str.length()) != str.length()) + return false; + uint bpl = w * 3; + uchar *buf = new uchar[bpl]; + for (uint y=0; y(image.constScanLine(y)); + uchar *p = buf; + uchar *end = buf+bpl; + while (p < end) { + QRgb rgb = *b++; + *p++ = qRed(rgb); + *p++ = qGreen(rgb); + *p++ = qBlue(rgb); + } + if (bpl != (uint)out->write((char*)buf, bpl)) + return false; + } + delete[] buf; + break; + } default: return false; @@ -442,8 +442,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy QPpmHandler::QPpmHandler() : state(Ready) -{ -} +{} bool QPpmHandler::readHeader() { @@ -523,8 +522,8 @@ bool QPpmHandler::write(const QImage &image) bool QPpmHandler::supportsOption(ImageOption option) const { return option == SubType - || option == Size - || option == ImageFormat; + || option == Size + || option == ImageFormat; } QVariant QPpmHandler::option(ImageOption option) const @@ -544,20 +543,20 @@ QVariant QPpmHandler::option(ImageOption option) const return QVariant(); QImage::Format format = QImage::Format_Invalid; switch (type) { - case '1': // ascii PBM - case '4': // raw PBM - format = QImage::Format_Mono; - break; - case '2': // ascii PGM - case '5': // raw PGM - format = QImage::Format_Grayscale8; - break; - case '3': // ascii PPM - case '6': // raw PPM - format = QImage::Format_RGB32; - break; - default: - break; + case '1': // ascii PBM + case '4': // raw PBM + format = QImage::Format_Mono; + break; + case '2': // ascii PGM + case '5': // raw PGM + format = QImage::Format_Grayscale8; + break; + case '3': // ascii PPM + case '6': // raw PPM + format = QImage::Format_RGB32; + break; + default: + break; } return format; } diff --git a/test/bug-hunting/cve/CVE-2018-20845/pi.c b/test/bug-hunting/cve/CVE-2018-20845/pi.c index 9e909f656..5edb2223d 100644 --- a/test/bug-hunting/cve/CVE-2018-20845/pi.c +++ b/test/bug-hunting/cve/CVE-2018-20845/pi.c @@ -45,34 +45,34 @@ /*@{*/ /** -Get next packet in layer-resolution-component-precinct order. -@param pi packet iterator to modify -@return returns false if pi pointed to the last packet or else returns true -*/ + Get next packet in layer-resolution-component-precinct order. + @param pi packet iterator to modify + @return returns false if pi pointed to the last packet or else returns true + */ static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi); /** -Get next packet in resolution-layer-component-precinct order. -@param pi packet iterator to modify -@return returns false if pi pointed to the last packet or else returns true -*/ + Get next packet in resolution-layer-component-precinct order. + @param pi packet iterator to modify + @return returns false if pi pointed to the last packet or else returns true + */ static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi); /** -Get next packet in resolution-precinct-component-layer order. -@param pi packet iterator to modify -@return returns false if pi pointed to the last packet or else returns true -*/ + Get next packet in resolution-precinct-component-layer order. + @param pi packet iterator to modify + @return returns false if pi pointed to the last packet or else returns true + */ static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi); /** -Get next packet in precinct-component-resolution-layer order. -@param pi packet iterator to modify -@return returns false if pi pointed to the last packet or else returns true -*/ + Get next packet in precinct-component-resolution-layer order. + @param pi packet iterator to modify + @return returns false if pi pointed to the last packet or else returns true + */ static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi); /** -Get next packet in component-precinct-resolution-layer order. -@param pi packet iterator to modify -@return returns false if pi pointed to the last packet or else returns true -*/ + Get next packet in component-precinct-resolution-layer order. + @param pi packet iterator to modify + @return returns false if pi pointed to the last packet or else returns true + */ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi); /*@}*/ @@ -80,10 +80,10 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi); /*@}*/ /* -========================================================== + ========================================================== local functions -========================================================== -*/ + ========================================================== + */ static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) { @@ -101,7 +101,7 @@ static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; - pi->resno++) { + pi->resno++) { for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { comp = &pi->comps[pi->compno]; if (pi->resno >= comp->numresolutions) { @@ -203,9 +203,9 @@ static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi) } for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; - pi->y += pi->dy - (pi->y % pi->dy)) { + pi->y += pi->dy - (pi->y % pi->dy)) { for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; - pi->x += pi->dx - (pi->x % pi->dx)) { + pi->x += pi->dx - (pi->x % pi->dx)) { for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { int levelno; int trx0, try0; @@ -227,16 +227,16 @@ static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi) /* To avoid divisions by zero / undefined behaviour on shift */ if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx || - rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { + rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { continue; } if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && - ((try0 << levelno) % (1 << rpy))))) { + ((try0 << levelno) % (1 << rpy))))) { continue; } if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && - ((trx0 << levelno) % (1 << rpx))))) { + ((trx0 << levelno) % (1 << rpx))))) { continue; } @@ -304,13 +304,13 @@ static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi) pi->poc.tx1 = pi->tx1; } for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; - pi->y += pi->dy - (pi->y % pi->dy)) { + pi->y += pi->dy - (pi->y % pi->dy)) { for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; - pi->x += pi->dx - (pi->x % pi->dx)) { + pi->x += pi->dx - (pi->x % pi->dx)) { for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { comp = &pi->comps[pi->compno]; for (pi->resno = pi->poc.resno0; - pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { int levelno; int trx0, try0; int trx1, try1; @@ -327,16 +327,16 @@ static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi) /* To avoid divisions by zero / undefined behaviour on shift */ if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx || - rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { + rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) { continue; } if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && - ((try0 << levelno) % (1 << rpy))))) { + ((try0 << levelno) % (1 << rpy))))) { continue; } if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && - ((trx0 << levelno) % (1 << rpx))))) { + ((trx0 << levelno) % (1 << rpx))))) { continue; } @@ -404,11 +404,11 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi) pi->poc.tx1 = pi->tx1; } for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; - pi->y += pi->dy - (pi->y % pi->dy)) { + pi->y += pi->dy - (pi->y % pi->dy)) { for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; - pi->x += pi->dx - (pi->x % pi->dx)) { + pi->x += pi->dx - (pi->x % pi->dx)) { for (pi->resno = pi->poc.resno0; - pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { int levelno; int trx0, try0; int trx1, try1; @@ -424,11 +424,11 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi) rpy = res->pdy + levelno; if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && - ((try0 << levelno) % (1 << rpy))))) { + ((try0 << levelno) % (1 << rpy))))) { continue; } if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && - ((trx0 << levelno) % (1 << rpx))))) { + ((trx0 << levelno) % (1 << rpx))))) { continue; } @@ -464,10 +464,10 @@ LABEL_SKIP: } /* -========================================================== + ========================================================== Packet iterator interface -========================================================== -*/ + ========================================================== + */ opj_pi_iterator_t *pi_create_decode(opj_image_t *image, opj_cp_t *cp, int tileno) @@ -500,7 +500,7 @@ opj_pi_iterator_t *pi_create_decode(opj_image_t *image, opj_cp_t *cp, pi[pino].numcomps = image->numcomps; pi[pino].comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, - sizeof(opj_pi_comp_t)); + sizeof(opj_pi_comp_t)); if (!pi[pino].comps) { /* TODO: throw an error */ pi_destroy(pi, cp, tileno); @@ -516,7 +516,7 @@ opj_pi_iterator_t *pi_create_decode(opj_image_t *image, opj_cp_t *cp, comp->numresolutions = tccp->numresolutions; comp->resolutions = (opj_pi_resolution_t*) opj_calloc(comp->numresolutions, - sizeof(opj_pi_resolution_t)); + sizeof(opj_pi_resolution_t)); if (!comp->resolutions) { /* TODO: throw an error */ pi_destroy(pi, cp, tileno); @@ -570,7 +570,7 @@ opj_pi_iterator_t *pi_create_decode(opj_image_t *image, opj_cp_t *cp, if (pino == 0) { pi[pino].include = (short int*) opj_calloc(image->numcomps * maxres * - tcp->numlayers * maxprec, sizeof(short int)); + tcp->numlayers * maxprec, sizeof(short int)); if (!pi[pino].include) { /* TODO: throw an error */ pi_destroy(pi, cp, tileno); @@ -627,7 +627,7 @@ opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, } pi->tp_on = cp->tp_on; - for (pino = 0; pino < tcp->numpocs + 1 ; pino ++) { + for (pino = 0; pino < tcp->numpocs + 1; pino++) { p = tileno % cp->tw; q = tileno / cp->tw; @@ -638,7 +638,7 @@ opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, pi[pino].numcomps = image->numcomps; pi[pino].comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, - sizeof(opj_pi_comp_t)); + sizeof(opj_pi_comp_t)); if (!pi[pino].comps) { pi_destroy(pi, cp, tileno); return NULL; @@ -653,7 +653,7 @@ opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, comp->numresolutions = tccp->numresolutions; comp->resolutions = (opj_pi_resolution_t*) opj_malloc(comp->numresolutions * - sizeof(opj_pi_resolution_t)); + sizeof(opj_pi_resolution_t)); if (!comp->resolutions) { pi_destroy(pi, cp, tileno); return NULL; @@ -717,7 +717,7 @@ opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, if (pino == 0) { pi[pino].include = (short int*) opj_calloc(tcp->numlayers * pi[pino].step_l, - sizeof(short int)); + sizeof(short int)); if (!pi[pino].include) { pi_destroy(pi, cp, tileno); return NULL; @@ -1027,14 +1027,14 @@ opj_bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno, pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx); tcp->tx0_t = pi[pino].poc.tx1; pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy); - pi[pino].poc.ty1 = tcp->ty0_t ; + pi[pino].poc.ty1 = tcp->ty0_t; incr_top = 0; } } else { pi[pino].poc.tx0 = tcp->tx0_t - tcp->dx - (tcp->tx0_t % tcp->dx); - pi[pino].poc.tx1 = tcp->tx0_t ; + pi[pino].poc.tx1 = tcp->tx0_t; pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy); - pi[pino].poc.ty1 = tcp->ty0_t ; + pi[pino].poc.ty1 = tcp->ty0_t; } } } diff --git a/test/bug-hunting/cve/CVE-2019-10018/Function.h b/test/bug-hunting/cve/CVE-2019-10018/Function.h index 5cf45169a..615c2abfd 100644 --- a/test/bug-hunting/cve/CVE-2019-10018/Function.h +++ b/test/bug-hunting/cve/CVE-2019-10018/Function.h @@ -34,64 +34,84 @@ struct PSCode; class Function { public: - Function(); + Function(); - virtual ~Function(); + virtual ~Function(); - // Construct a function. Returns NULL if unsuccessful. - static Function *parse(Object *funcObj, int recursion = 0); + // Construct a function. Returns NULL if unsuccessful. + static Function *parse(Object *funcObj, int recursion = 0); - // Initialize the entries common to all function types. - GBool init(Dict *dict); + // Initialize the entries common to all function types. + GBool init(Dict *dict); - virtual Function *copy() = 0; + virtual Function *copy() = 0; - // Return the function type: - // -1 : identity - // 0 : sampled - // 2 : exponential - // 3 : stitching - // 4 : PostScript - virtual int getType() = 0; + // Return the function type: + // -1 : identity + // 0 : sampled + // 2 : exponential + // 3 : stitching + // 4 : PostScript + virtual int getType() = 0; - // Return size of input and output tuples. - int getInputSize() { return m; } - int getOutputSize() { return n; } + // Return size of input and output tuples. + int getInputSize() { + return m; + } + int getOutputSize() { + return n; + } - double getDomainMin(int i) { return domain[i][0]; } - double getDomainMax(int i) { return domain[i][1]; } - double getRangeMin(int i) { return range[i][0]; } - double getRangeMax(int i) { return range[i][1]; } - GBool getHasRange() { return hasRange; } + double getDomainMin(int i) { + return domain[i][0]; + } + double getDomainMax(int i) { + return domain[i][1]; + } + double getRangeMin(int i) { + return range[i][0]; + } + double getRangeMax(int i) { + return range[i][1]; + } + GBool getHasRange() { + return hasRange; + } - // Transform an input tuple into an output tuple. - virtual void transform(double *in, double *out) = 0; + // Transform an input tuple into an output tuple. + virtual void transform(double *in, double *out) = 0; - virtual GBool isOk() = 0; + virtual GBool isOk() = 0; protected: - int m, n; // size of input and output tuples - double // min and max values for function domain - domain[funcMaxInputs][2]; - double // min and max values for function range - range[funcMaxOutputs][2]; - GBool hasRange; // set if range is defined + int m, n; // size of input and output tuples + double // min and max values for function domain + domain[funcMaxInputs][2]; + double // min and max values for function range + range[funcMaxOutputs][2]; + GBool hasRange; // set if range is defined }; //------------------------------------------------------------------------ // IdentityFunction //------------------------------------------------------------------------ -class IdentityFunction: public Function { +class IdentityFunction : public Function { public: - IdentityFunction(); - virtual ~IdentityFunction(); - virtual Function *copy() { return new IdentityFunction(); } - virtual int getType() { return -1; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return gTrue; } + IdentityFunction(); + virtual ~IdentityFunction(); + virtual Function *copy() { + return new IdentityFunction(); + } + virtual int getType() { + return -1; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return gTrue; + } private: }; @@ -100,137 +120,191 @@ private: // SampledFunction //------------------------------------------------------------------------ -class SampledFunction: public Function { +class SampledFunction : public Function { public: - SampledFunction(Object *funcObj, Dict *dict); - virtual ~SampledFunction(); - virtual Function *copy() { return new SampledFunction(this); } - virtual int getType() { return 0; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + SampledFunction(Object *funcObj, Dict *dict); + virtual ~SampledFunction(); + virtual Function *copy() { + return new SampledFunction(this); + } + virtual int getType() { + return 0; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - int getSampleSize(int i) { return sampleSize[i]; } - double getEncodeMin(int i) { return encode[i][0]; } - double getEncodeMax(int i) { return encode[i][1]; } - double getDecodeMin(int i) { return decode[i][0]; } - double getDecodeMax(int i) { return decode[i][1]; } - double *getSamples() { return samples; } + int getSampleSize(int i) { + return sampleSize[i]; + } + double getEncodeMin(int i) { + return encode[i][0]; + } + double getEncodeMax(int i) { + return encode[i][1]; + } + double getDecodeMin(int i) { + return decode[i][0]; + } + double getDecodeMax(int i) { + return decode[i][1]; + } + double *getSamples() { + return samples; + } private: - SampledFunction(SampledFunction *func); + SampledFunction(SampledFunction *func); - int // number of samples for each domain element - sampleSize[funcMaxInputs]; - double // min and max values for domain encoder - encode[funcMaxInputs][2]; - double // min and max values for range decoder - decode[funcMaxOutputs][2]; - double // input multipliers - inputMul[funcMaxInputs]; - int *idxOffset; - double *samples; // the samples - int nSamples; // size of the samples array - double *sBuf; // buffer for the transform function - double cacheIn[funcMaxInputs]; - double cacheOut[funcMaxOutputs]; - GBool ok; + int // number of samples for each domain element + sampleSize[funcMaxInputs]; + double // min and max values for domain encoder + encode[funcMaxInputs][2]; + double // min and max values for range decoder + decode[funcMaxOutputs][2]; + double // input multipliers + inputMul[funcMaxInputs]; + int *idxOffset; + double *samples; // the samples + int nSamples; // size of the samples array + double *sBuf; // buffer for the transform function + double cacheIn[funcMaxInputs]; + double cacheOut[funcMaxOutputs]; + GBool ok; }; //------------------------------------------------------------------------ // ExponentialFunction //------------------------------------------------------------------------ -class ExponentialFunction: public Function { +class ExponentialFunction : public Function { public: - ExponentialFunction(Object *funcObj, Dict *dict); - virtual ~ExponentialFunction(); - virtual Function *copy() { return new ExponentialFunction(this); } - virtual int getType() { return 2; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + ExponentialFunction(Object *funcObj, Dict *dict); + virtual ~ExponentialFunction(); + virtual Function *copy() { + return new ExponentialFunction(this); + } + virtual int getType() { + return 2; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - double *getC0() { return c0; } - double *getC1() { return c1; } - double getE() { return e; } + double *getC0() { + return c0; + } + double *getC1() { + return c1; + } + double getE() { + return e; + } private: - ExponentialFunction(ExponentialFunction *func); + ExponentialFunction(ExponentialFunction *func); - double c0[funcMaxOutputs]; - double c1[funcMaxOutputs]; - double e; - GBool ok; + double c0[funcMaxOutputs]; + double c1[funcMaxOutputs]; + double e; + GBool ok; }; //------------------------------------------------------------------------ // StitchingFunction //------------------------------------------------------------------------ -class StitchingFunction: public Function { +class StitchingFunction : public Function { public: - StitchingFunction(Object *funcObj, Dict *dict, int recursion); - virtual ~StitchingFunction(); - virtual Function *copy() { return new StitchingFunction(this); } - virtual int getType() { return 3; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + StitchingFunction(Object *funcObj, Dict *dict, int recursion); + virtual ~StitchingFunction(); + virtual Function *copy() { + return new StitchingFunction(this); + } + virtual int getType() { + return 3; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - int getNumFuncs() { return k; } - Function *getFunc(int i) { return funcs[i]; } - double *getBounds() { return bounds; } - double *getEncode() { return encode; } - double *getScale() { return scale; } + int getNumFuncs() { + return k; + } + Function *getFunc(int i) { + return funcs[i]; + } + double *getBounds() { + return bounds; + } + double *getEncode() { + return encode; + } + double *getScale() { + return scale; + } private: - StitchingFunction(StitchingFunction *func); + StitchingFunction(StitchingFunction *func); - int k; - Function **funcs; - double *bounds; - double *encode; - double *scale; - GBool ok; + int k; + Function **funcs; + double *bounds; + double *encode; + double *scale; + GBool ok; }; //------------------------------------------------------------------------ // PostScriptFunction //------------------------------------------------------------------------ -class PostScriptFunction: public Function { +class PostScriptFunction : public Function { public: - PostScriptFunction(Object *funcObj, Dict *dict); - virtual ~PostScriptFunction(); - virtual Function *copy() { return new PostScriptFunction(this); } - virtual int getType() { return 4; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + PostScriptFunction(Object *funcObj, Dict *dict); + virtual ~PostScriptFunction(); + virtual Function *copy() { + return new PostScriptFunction(this); + } + virtual int getType() { + return 4; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - GString *getCodeString() { return codeString; } + GString *getCodeString() { + return codeString; + } private: - PostScriptFunction(PostScriptFunction *func); - GBool parseCode(GList *tokens, int *tokPtr, int *codePtr); - void addCode(int *codePtr, int op); - void addCodeI(int *codePtr, int op, int x); - void addCodeD(int *codePtr, int op, double x); - GString *getToken(Stream *str); - int exec(double *stack, int sp0); + PostScriptFunction(PostScriptFunction *func); + GBool parseCode(GList *tokens, int *tokPtr, int *codePtr); + void addCode(int *codePtr, int op); + void addCodeI(int *codePtr, int op, int x); + void addCodeD(int *codePtr, int op, double x); + GString *getToken(Stream *str); + int exec(double *stack, int sp0); - GString *codeString; - PSCode *code; - int codeLen; - int codeSize; - double cacheIn[funcMaxInputs]; - double cacheOut[funcMaxOutputs]; - GBool ok; + GString *codeString; + PSCode *code; + int codeLen; + int codeSize; + double cacheIn[funcMaxInputs]; + double cacheOut[funcMaxOutputs]; + GBool ok; }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-10019/PSOutputDev.h b/test/bug-hunting/cve/CVE-2019-10019/PSOutputDev.h index 66057a7cb..acd4eaf63 100644 --- a/test/bug-hunting/cve/CVE-2019-10019/PSOutputDev.h +++ b/test/bug-hunting/cve/CVE-2019-10019/PSOutputDev.h @@ -48,464 +48,492 @@ class PSFontFileInfo; //------------------------------------------------------------------------ enum PSOutMode { - psModePS, - psModeEPS, - psModeForm + psModePS, + psModeEPS, + psModeForm }; enum PSFileType { - psFile, // write to file - psPipe, // write to pipe - psStdout, // write to stdout - psGeneric // write to a generic stream + psFile, // write to file + psPipe, // write to pipe + psStdout, // write to stdout + psGeneric // write to a generic stream }; enum PSOutCustomCodeLocation { - psOutCustomDocSetup, - psOutCustomPageSetup + psOutCustomDocSetup, + psOutCustomPageSetup }; typedef void (*PSOutputFunc)(void *stream, const char *data, int len); typedef GString *(*PSOutCustomCodeCbk)(PSOutputDev *psOut, - PSOutCustomCodeLocation loc, int n, - void *data); + PSOutCustomCodeLocation loc, int n, + void *data); -class PSOutputDev: public OutputDev { +class PSOutputDev : public OutputDev { public: - // Open a PostScript output file, and write the prolog. - PSOutputDev(char *fileName, PDFDoc *docA, - int firstPageA, int lastPageA, PSOutMode modeA, - int imgLLXA = 0, int imgLLYA = 0, - int imgURXA = 0, int imgURYA = 0, - GBool manualCtrlA = gFalse, - PSOutCustomCodeCbk customCodeCbkA = NULL, - void *customCodeCbkDataA = NULL, - GBool honorUserUnitA = gFalse); + // Open a PostScript output file, and write the prolog. + PSOutputDev(char *fileName, PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA = 0, int imgLLYA = 0, + int imgURXA = 0, int imgURYA = 0, + GBool manualCtrlA = gFalse, + PSOutCustomCodeCbk customCodeCbkA = NULL, + void *customCodeCbkDataA = NULL, + GBool honorUserUnitA = gFalse); - // Open a PSOutputDev that will write to a generic stream. - PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, - PDFDoc *docA, - int firstPageA, int lastPageA, PSOutMode modeA, - int imgLLXA = 0, int imgLLYA = 0, - int imgURXA = 0, int imgURYA = 0, - GBool manualCtrlA = gFalse, - PSOutCustomCodeCbk customCodeCbkA = NULL, - void *customCodeCbkDataA = NULL, - GBool honorUserUnitA = gFalse); + // Open a PSOutputDev that will write to a generic stream. + PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, + PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA = 0, int imgLLYA = 0, + int imgURXA = 0, int imgURYA = 0, + GBool manualCtrlA = gFalse, + PSOutCustomCodeCbk customCodeCbkA = NULL, + void *customCodeCbkDataA = NULL, + GBool honorUserUnitA = gFalse); - // Destructor -- writes the trailer and closes the file. - virtual ~PSOutputDev(); + // Destructor -- writes the trailer and closes the file. + virtual ~PSOutputDev(); - // Check if file was successfully created. - virtual GBool isOk() { return ok; } + // Check if file was successfully created. + virtual GBool isOk() { + return ok; + } - // Returns false if there have been any errors on the output stream. - GBool checkIO(); + // Returns false if there have been any errors on the output stream. + GBool checkIO(); - //---- get info about output device + //---- get info about output device - // Does this device use upside-down coordinates? - // (Upside-down means (0,0) is the top left corner of the page.) - virtual GBool upsideDown() { return gFalse; } + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + virtual GBool upsideDown() { + return gFalse; + } - // Does this device use drawChar() or drawString()? - virtual GBool useDrawChar() { return gFalse; } + // Does this device use drawChar() or drawString()? + virtual GBool useDrawChar() { + return gFalse; + } - // Does this device use tilingPatternFill()? If this returns false, - // tiling pattern fills will be reduced to a series of other drawing - // operations. - virtual GBool useTilingPatternFill() { return gTrue; } + // Does this device use tilingPatternFill()? If this returns false, + // tiling pattern fills will be reduced to a series of other drawing + // operations. + virtual GBool useTilingPatternFill() { + return gTrue; + } - // Does this device use functionShadedFill(), axialShadedFill(), and - // radialShadedFill()? If this returns false, these shaded fills - // will be reduced to a series of other drawing operations. - virtual GBool useShadedFills() - { return level == psLevel2 || level == psLevel2Sep || - level == psLevel3 || level == psLevel3Sep; } + // Does this device use functionShadedFill(), axialShadedFill(), and + // radialShadedFill()? If this returns false, these shaded fills + // will be reduced to a series of other drawing operations. + virtual GBool useShadedFills() + { + return level == psLevel2 || level == psLevel2Sep || + level == psLevel3 || level == psLevel3Sep; + } - // Does this device use drawForm()? If this returns false, - // form-type XObjects will be interpreted (i.e., unrolled). - virtual GBool useDrawForm() { return preload; } + // Does this device use drawForm()? If this returns false, + // form-type XObjects will be interpreted (i.e., unrolled). + virtual GBool useDrawForm() { + return preload; + } - // Does this device use beginType3Char/endType3Char? Otherwise, - // text in Type 3 fonts will be drawn with drawChar/drawString. - virtual GBool interpretType3Chars() { return gFalse; } + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + virtual GBool interpretType3Chars() { + return gFalse; + } - //----- header/trailer (used only if manualCtrl is true) + //----- header/trailer (used only if manualCtrl is true) - // Write the document-level header. - void writeHeader(PDFRectangle *mediaBox, PDFRectangle *cropBox, - int pageRotate); + // Write the document-level header. + void writeHeader(PDFRectangle *mediaBox, PDFRectangle *cropBox, + int pageRotate); - // Write the Xpdf procset. - void writeXpdfProcset(); + // Write the Xpdf procset. + void writeXpdfProcset(); - // Write the document-level setup. - void writeDocSetup(Catalog *catalog); + // Write the document-level setup. + void writeDocSetup(Catalog *catalog); - // Write the trailer for the current page. - void writePageTrailer(); + // Write the trailer for the current page. + void writePageTrailer(); - // Write the document trailer. - void writeTrailer(); + // Write the document trailer. + void writeTrailer(); - //----- initialization and control + //----- initialization and control - // Check to see if a page slice should be displayed. If this - // returns false, the page display is aborted. Typically, an - // OutputDev will use some alternate means to display the page - // before returning false. - virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - int sliceX, int sliceY, int sliceW, int sliceH, - GBool printing, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); + // Check to see if a page slice should be displayed. If this + // returns false, the page display is aborted. Typically, an + // OutputDev will use some alternate means to display the page + // before returning false. + virtual GBool checkPageSlice(Page *page, double hDPI, double vDPI, + int rotate, GBool useMediaBox, GBool crop, + int sliceX, int sliceY, int sliceW, int sliceH, + GBool printing, + GBool (*abortCheckCbk)(void *data) = NULL, + void *abortCheckCbkData = NULL); - // Start a page. - virtual void startPage(int pageNum, GfxState *state); + // Start a page. + virtual void startPage(int pageNum, GfxState *state); - // End a page. - virtual void endPage(); + // End a page. + virtual void endPage(); - //----- save/restore graphics state - virtual void saveState(GfxState *state); - virtual void restoreState(GfxState *state); + //----- save/restore graphics state + virtual void saveState(GfxState *state); + virtual void restoreState(GfxState *state); - //----- update graphics state - virtual void updateCTM(GfxState *state, double m11, double m12, - double m21, double m22, double m31, double m32); - virtual void updateLineDash(GfxState *state); - virtual void updateFlatness(GfxState *state); - virtual void updateLineJoin(GfxState *state); - virtual void updateLineCap(GfxState *state); - virtual void updateMiterLimit(GfxState *state); - virtual void updateLineWidth(GfxState *state); - virtual void updateFillColorSpace(GfxState *state); - virtual void updateStrokeColorSpace(GfxState *state); - virtual void updateFillColor(GfxState *state); - virtual void updateStrokeColor(GfxState *state); - virtual void updateFillOverprint(GfxState *state); - virtual void updateStrokeOverprint(GfxState *state); - virtual void updateOverprintMode(GfxState *state); - virtual void updateTransfer(GfxState *state); + //----- update graphics state + virtual void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32); + virtual void updateLineDash(GfxState *state); + virtual void updateFlatness(GfxState *state); + virtual void updateLineJoin(GfxState *state); + virtual void updateLineCap(GfxState *state); + virtual void updateMiterLimit(GfxState *state); + virtual void updateLineWidth(GfxState *state); + virtual void updateFillColorSpace(GfxState *state); + virtual void updateStrokeColorSpace(GfxState *state); + virtual void updateFillColor(GfxState *state); + virtual void updateStrokeColor(GfxState *state); + virtual void updateFillOverprint(GfxState *state); + virtual void updateStrokeOverprint(GfxState *state); + virtual void updateOverprintMode(GfxState *state); + virtual void updateTransfer(GfxState *state); - //----- update text state - virtual void updateFont(GfxState *state); - virtual void updateTextMat(GfxState *state); - virtual void updateCharSpace(GfxState *state); - virtual void updateRender(GfxState *state); - virtual void updateRise(GfxState *state); - virtual void updateWordSpace(GfxState *state); - virtual void updateHorizScaling(GfxState *state); - virtual void updateTextPos(GfxState *state); - virtual void updateTextShift(GfxState *state, double shift); - virtual void saveTextPos(GfxState *state); - virtual void restoreTextPos(GfxState *state); + //----- update text state + virtual void updateFont(GfxState *state); + virtual void updateTextMat(GfxState *state); + virtual void updateCharSpace(GfxState *state); + virtual void updateRender(GfxState *state); + virtual void updateRise(GfxState *state); + virtual void updateWordSpace(GfxState *state); + virtual void updateHorizScaling(GfxState *state); + virtual void updateTextPos(GfxState *state); + virtual void updateTextShift(GfxState *state, double shift); + virtual void saveTextPos(GfxState *state); + virtual void restoreTextPos(GfxState *state); - //----- path painting - virtual void stroke(GfxState *state); - virtual void fill(GfxState *state); - virtual void eoFill(GfxState *state); - virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, - int paintType, int tilingType, Dict *resDict, - double *mat, double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep); - virtual GBool functionShadedFill(GfxState *state, - GfxFunctionShading *shading); - virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading); - virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading); + //----- path painting + virtual void stroke(GfxState *state); + virtual void fill(GfxState *state); + virtual void eoFill(GfxState *state); + virtual void tilingPatternFill(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + virtual GBool functionShadedFill(GfxState *state, + GfxFunctionShading *shading); + virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading); + virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading); - //----- path clipping - virtual void clip(GfxState *state); - virtual void eoClip(GfxState *state); - virtual void clipToStrokePath(GfxState *state); + //----- path clipping + virtual void clip(GfxState *state); + virtual void eoClip(GfxState *state); + virtual void clipToStrokePath(GfxState *state); - //----- text drawing - virtual void drawString(GfxState *state, GString *s); - virtual void endTextObject(GfxState *state); + //----- text drawing + virtual void drawString(GfxState *state, GString *s); + virtual void endTextObject(GfxState *state); - //----- image drawing - virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, GBool invert, - GBool inlineImg, GBool interpolate); - virtual void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg, GBool interpolate); - virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert, GBool interpolate); + //----- image drawing + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg, GBool interpolate); + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg, GBool interpolate); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert, GBool interpolate); #if OPI_SUPPORT - //----- OPI functions - virtual void opiBegin(GfxState *state, Dict *opiDict); - virtual void opiEnd(GfxState *state, Dict *opiDict); + //----- OPI functions + virtual void opiBegin(GfxState *state, Dict *opiDict); + virtual void opiEnd(GfxState *state, Dict *opiDict); #endif - //----- Type 3 font operators - virtual void type3D0(GfxState *state, double wx, double wy); - virtual void type3D1(GfxState *state, double wx, double wy, - double llx, double lly, double urx, double ury); + //----- Type 3 font operators + virtual void type3D0(GfxState *state, double wx, double wy); + virtual void type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury); - //----- form XObjects - virtual void drawForm(Ref ref); + //----- form XObjects + virtual void drawForm(Ref ref); - //----- PostScript XObjects - virtual void psXObject(Stream *psStream, Stream *level1Stream); + //----- PostScript XObjects + virtual void psXObject(Stream *psStream, Stream *level1Stream); - //----- miscellaneous - void setImageableArea(int imgLLXA, int imgLLYA, int imgURXA, int imgURYA) - { imgLLX = imgLLXA; imgLLY = imgLLYA; imgURX = imgURXA; imgURY = imgURYA; } - void setOffset(double x, double y) - { tx0 = x; ty0 = y; } - void setScale(double x, double y) - { xScale0 = x; yScale0 = y; } - void setRotate(int rotateA) - { rotate0 = rotateA; } - void setClip(double llx, double lly, double urx, double ury) - { clipLLX0 = llx; clipLLY0 = lly; clipURX0 = urx; clipURY0 = ury; } - void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), - void *data) - { underlayCbk = cbk; underlayCbkData = data; } - void setOverlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), - void *data) - { overlayCbk = cbk; overlayCbkData = data; } + //----- miscellaneous + void setImageableArea(int imgLLXA, int imgLLYA, int imgURXA, int imgURYA) + { + imgLLX = imgLLXA; imgLLY = imgLLYA; imgURX = imgURXA; imgURY = imgURYA; + } + void setOffset(double x, double y) + { + tx0 = x; ty0 = y; + } + void setScale(double x, double y) + { + xScale0 = x; yScale0 = y; + } + void setRotate(int rotateA) + { + rotate0 = rotateA; + } + void setClip(double llx, double lly, double urx, double ury) + { + clipLLX0 = llx; clipLLY0 = lly; clipURX0 = urx; clipURY0 = ury; + } + void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), + void *data) + { + underlayCbk = cbk; underlayCbkData = data; + } + void setOverlayCbk(void (*cbk)(PSOutputDev *psOut, void *data), + void *data) + { + overlayCbk = cbk; overlayCbkData = data; + } - void writePSChar(char c); - void writePSBlock(char *s, int len); - void writePS(const char *s); - void writePSFmt(const char *fmt, ...); - void writePSString(GString *s); - void writePSName(const char *s); + void writePSChar(char c); + void writePSBlock(char *s, int len); + void writePS(const char *s); + void writePSFmt(const char *fmt, ...); + void writePSString(GString *s); + void writePSName(const char *s); private: - void init(PSOutputFunc outputFuncA, void *outputStreamA, - PSFileType fileTypeA, PDFDoc *docA, - int firstPageA, int lastPageA, PSOutMode modeA, - int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, - GBool manualCtrlA, GBool honorUserUnitA); - GBool checkIfPageNeedsToBeRasterized(int pg); - void setupResources(Dict *resDict); - void setupFonts(Dict *resDict); - void setupFont(GfxFont *font, Dict *parentResDict); - PSFontFileInfo *setupEmbeddedType1Font(GfxFont *font, Ref *id); - PSFontFileInfo *setupExternalType1Font(GfxFont *font, GString *fileName); - PSFontFileInfo *setupEmbeddedType1CFont(GfxFont *font, Ref *id); - PSFontFileInfo *setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id); - PSFontFileInfo *setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id); - PSFontFileInfo *setupExternalTrueTypeFont(GfxFont *font, GString *fileName, - int fontNum); - PSFontFileInfo *setupEmbeddedCIDType0Font(GfxFont *font, Ref *id); - PSFontFileInfo *setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, - GBool needVerticalMetrics); - PSFontFileInfo *setupExternalCIDTrueTypeFont(GfxFont *font, - GString *fileName, - int fontNum, - GBool needVerticalMetrics); - PSFontFileInfo *setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id); - PSFontFileInfo *setupExternalOpenTypeCFFFont(GfxFont *font, - GString *fileName); - PSFontFileInfo *setupType3Font(GfxFont *font, Dict *parentResDict); - GString *makePSFontName(GfxFont *font, Ref *id); - GString *fixType1Font(GString *font, int length1, int length2); - GBool splitType1PFA(Guchar *font, int fontSize, - int length1, int length2, - GString *textSection, GString *binSection); - GBool splitType1PFB(Guchar *font, int fontSize, - GString *textSection, GString *binSection); - GString *asciiHexDecodeType1EexecSection(GString *in); - GBool fixType1EexecSection(GString *binSection, GString *out); - GString *copyType1PFA(Guchar *font, int fontSize); - GString *copyType1PFB(Guchar *font, int fontSize); - void renameType1Font(GString *font, GString *name); - void setupDefaultFont(); - void setupImages(Dict *resDict); - void setupImage(Ref id, Stream *str, GBool mask, Array *colorKeyMask); - void setupForms(Dict *resDict); - void setupForm(Object *strRef, Object *strObj); - void addProcessColor(double c, double m, double y, double k); - void addCustomColor(GfxState *state, GfxSeparationColorSpace *sepCS); - void addCustomColors(GfxState *state, GfxDeviceNColorSpace *devnCS); - void tilingPatternFillL1(GfxState *state, Gfx *gfx, Object *strRef, - int paintType, int tilingType, Dict *resDict, - double *mat, double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep); - void tilingPatternFillL2(GfxState *state, Gfx *gfx, Object *strRef, - int paintType, int tilingType, Dict *resDict, - double *mat, double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep); - void doPath(GfxPath *path); - void doImageL1(Object *ref, GfxState *state, - GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len); - void doImageL1Sep(GfxState *state, GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len); - void doImageL2(Object *ref, GfxState *state, - GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len, - int *maskColors, Stream *maskStr, - int maskWidth, int maskHeight, GBool maskInvert); - void convertColorKeyMaskToClipRects(GfxImageColorMap *colorMap, - Stream *str, - int width, int height, - int *maskColors); - void convertExplicitMaskToClipRects(Stream *maskStr, - int maskWidth, int maskHeight, - GBool maskInvert); - void doImageL3(Object *ref, GfxState *state, - GfxImageColorMap *colorMap, - GBool invert, GBool inlineImg, - Stream *str, int width, int height, int len, - int *maskColors, Stream *maskStr, - int maskWidth, int maskHeight, GBool maskInvert); - void dumpColorSpaceL2(GfxState *state, GfxColorSpace *colorSpace, - GBool genXform, GBool updateColors, - GBool map01); - void dumpDeviceGrayColorSpace(GfxDeviceGrayColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpCalGrayColorSpace(GfxCalGrayColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpDeviceRGBColorSpace(GfxDeviceRGBColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpCalRGBColorSpace(GfxCalRGBColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpDeviceCMYKColorSpace(GfxDeviceCMYKColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpLabColorSpace(GfxLabColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpICCBasedColorSpace(GfxState *state, GfxICCBasedColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpIndexedColorSpace(GfxState *state, - GfxIndexedColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpSeparationColorSpace(GfxState *state, - GfxSeparationColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpDeviceNColorSpaceL2(GfxState *state, GfxDeviceNColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - void dumpDeviceNColorSpaceL3(GfxState *state, GfxDeviceNColorSpace *cs, - GBool genXform, GBool updateColors, - GBool map01); - GString *createDeviceNTintFunc(GfxDeviceNColorSpace *cs); + void init(PSOutputFunc outputFuncA, void *outputStreamA, + PSFileType fileTypeA, PDFDoc *docA, + int firstPageA, int lastPageA, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA, GBool honorUserUnitA); + GBool checkIfPageNeedsToBeRasterized(int pg); + void setupResources(Dict *resDict); + void setupFonts(Dict *resDict); + void setupFont(GfxFont *font, Dict *parentResDict); + PSFontFileInfo *setupEmbeddedType1Font(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalType1Font(GfxFont *font, GString *fileName); + PSFontFileInfo *setupEmbeddedType1CFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalTrueTypeFont(GfxFont *font, GString *fileName, + int fontNum); + PSFontFileInfo *setupEmbeddedCIDType0Font(GfxFont *font, Ref *id); + PSFontFileInfo *setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, + GBool needVerticalMetrics); + PSFontFileInfo *setupExternalCIDTrueTypeFont(GfxFont *font, + GString *fileName, + int fontNum, + GBool needVerticalMetrics); + PSFontFileInfo *setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id); + PSFontFileInfo *setupExternalOpenTypeCFFFont(GfxFont *font, + GString *fileName); + PSFontFileInfo *setupType3Font(GfxFont *font, Dict *parentResDict); + GString *makePSFontName(GfxFont *font, Ref *id); + GString *fixType1Font(GString *font, int length1, int length2); + GBool splitType1PFA(Guchar *font, int fontSize, + int length1, int length2, + GString *textSection, GString *binSection); + GBool splitType1PFB(Guchar *font, int fontSize, + GString *textSection, GString *binSection); + GString *asciiHexDecodeType1EexecSection(GString *in); + GBool fixType1EexecSection(GString *binSection, GString *out); + GString *copyType1PFA(Guchar *font, int fontSize); + GString *copyType1PFB(Guchar *font, int fontSize); + void renameType1Font(GString *font, GString *name); + void setupDefaultFont(); + void setupImages(Dict *resDict); + void setupImage(Ref id, Stream *str, GBool mask, Array *colorKeyMask); + void setupForms(Dict *resDict); + void setupForm(Object *strRef, Object *strObj); + void addProcessColor(double c, double m, double y, double k); + void addCustomColor(GfxState *state, GfxSeparationColorSpace *sepCS); + void addCustomColors(GfxState *state, GfxDeviceNColorSpace *devnCS); + void tilingPatternFillL1(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + void tilingPatternFillL2(GfxState *state, Gfx *gfx, Object *strRef, + int paintType, int tilingType, Dict *resDict, + double *mat, double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep); + void doPath(GfxPath *path); + void doImageL1(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len); + void doImageL1Sep(GfxState *state, GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len); + void doImageL2(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert); + void convertColorKeyMaskToClipRects(GfxImageColorMap *colorMap, + Stream *str, + int width, int height, + int *maskColors); + void convertExplicitMaskToClipRects(Stream *maskStr, + int maskWidth, int maskHeight, + GBool maskInvert); + void doImageL3(Object *ref, GfxState *state, + GfxImageColorMap *colorMap, + GBool invert, GBool inlineImg, + Stream *str, int width, int height, int len, + int *maskColors, Stream *maskStr, + int maskWidth, int maskHeight, GBool maskInvert); + void dumpColorSpaceL2(GfxState *state, GfxColorSpace *colorSpace, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceGrayColorSpace(GfxDeviceGrayColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpCalGrayColorSpace(GfxCalGrayColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceRGBColorSpace(GfxDeviceRGBColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpCalRGBColorSpace(GfxCalRGBColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceCMYKColorSpace(GfxDeviceCMYKColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpLabColorSpace(GfxLabColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpICCBasedColorSpace(GfxState *state, GfxICCBasedColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpIndexedColorSpace(GfxState *state, + GfxIndexedColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpSeparationColorSpace(GfxState *state, + GfxSeparationColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceNColorSpaceL2(GfxState *state, GfxDeviceNColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + void dumpDeviceNColorSpaceL3(GfxState *state, GfxDeviceNColorSpace *cs, + GBool genXform, GBool updateColors, + GBool map01); + GString *createDeviceNTintFunc(GfxDeviceNColorSpace *cs); #if OPI_SUPPORT - void opiBegin20(GfxState *state, Dict *dict); - void opiBegin13(GfxState *state, Dict *dict); - void opiTransform(GfxState *state, double x0, double y0, - double *x1, double *y1); - GBool getFileSpec(Object *fileSpec, Object *fileName); + void opiBegin20(GfxState *state, Dict *dict); + void opiBegin13(GfxState *state, Dict *dict); + void opiTransform(GfxState *state, double x0, double y0, + double *x1, double *y1); + GBool getFileSpec(Object *fileSpec, Object *fileName); #endif - void cvtFunction(Function *func); - GString *filterPSName(GString *name); - void writePSTextLine(GString *s); + void cvtFunction(Function *func); + GString *filterPSName(GString *name); + void writePSTextLine(GString *s); - PSLevel level; // PostScript level - PSOutMode mode; // PostScript mode (PS, EPS, form) - int paperWidth; // width of paper, in pts - int paperHeight; // height of paper, in pts - GBool paperMatch; // true if paper size is set to match each page - int imgLLX, imgLLY, // imageable area, in pts - imgURX, imgURY; - GBool preload; // load all images into memory, and - // predefine forms + PSLevel level; // PostScript level + PSOutMode mode; // PostScript mode (PS, EPS, form) + int paperWidth; // width of paper, in pts + int paperHeight; // height of paper, in pts + GBool paperMatch; // true if paper size is set to match each page + int imgLLX, imgLLY, // imageable area, in pts + imgURX, imgURY; + GBool preload; // load all images into memory, and + // predefine forms - PSOutputFunc outputFunc; - void *outputStream; - PSFileType fileType; // file / pipe / stdout - GBool manualCtrl; - int seqPage; // current sequential page number - void (*underlayCbk)(PSOutputDev *psOut, void *data); - void *underlayCbkData; - void (*overlayCbk)(PSOutputDev *psOut, void *data); - void *overlayCbkData; - GString *(*customCodeCbk)(PSOutputDev *psOut, - PSOutCustomCodeLocation loc, int n, - void *data); - void *customCodeCbkData; - GBool honorUserUnit; + PSOutputFunc outputFunc; + void *outputStream; + PSFileType fileType; // file / pipe / stdout + GBool manualCtrl; + int seqPage; // current sequential page number + void (*underlayCbk)(PSOutputDev *psOut, void *data); + void *underlayCbkData; + void (*overlayCbk)(PSOutputDev *psOut, void *data); + void *overlayCbkData; + GString *(*customCodeCbk)(PSOutputDev *psOut, + PSOutCustomCodeLocation loc, int n, + void *data); + void *customCodeCbkData; + GBool honorUserUnit; - PDFDoc *doc; - XRef *xref; // the xref table for this PDF file + PDFDoc *doc; + XRef *xref; // the xref table for this PDF file - int firstPage; // first output page - int lastPage; // last output page - char *rasterizePage; // boolean for each page - true if page - // needs to be rasterized + int firstPage; // first output page + int lastPage; // last output page + char *rasterizePage; // boolean for each page - true if page + // needs to be rasterized - GList *fontInfo; // info for each font [PSFontInfo] - GHash *fontFileInfo; // info for each font file [PSFontFileInfo] - Ref *imgIDs; // list of image IDs for in-memory images - int imgIDLen; // number of entries in imgIDs array - int imgIDSize; // size of imgIDs array - Ref *formIDs; // list of IDs for predefined forms - int formIDLen; // number of entries in formIDs array - int formIDSize; // size of formIDs array - char *visitedResources; // vector of resource objects already visited - GBool noStateChanges; // true if there have been no state changes - // since the last save - GList *saveStack; // "no state changes" flag for each - // pending save - int numTilingPatterns; // current number of nested tiling patterns - int nextFunc; // next unique number to use for a function + GList *fontInfo; // info for each font [PSFontInfo] + GHash *fontFileInfo; // info for each font file [PSFontFileInfo] + Ref *imgIDs; // list of image IDs for in-memory images + int imgIDLen; // number of entries in imgIDs array + int imgIDSize; // size of imgIDs array + Ref *formIDs; // list of IDs for predefined forms + int formIDLen; // number of entries in formIDs array + int formIDSize; // size of formIDs array + char *visitedResources; // vector of resource objects already visited + GBool noStateChanges; // true if there have been no state changes + // since the last save + GList *saveStack; // "no state changes" flag for each + // pending save + int numTilingPatterns; // current number of nested tiling patterns + int nextFunc; // next unique number to use for a function - GList *paperSizes; // list of used paper sizes, if paperMatch - // is true [PSOutPaperSize] - double tx0, ty0; // global translation - double xScale0, yScale0; // global scaling - int rotate0; // rotation angle (0, 90, 180, 270) - double clipLLX0, clipLLY0, - clipURX0, clipURY0; - double tx, ty; // global translation for current page - double xScale, yScale; // global scaling for current page - int rotate; // rotation angle for current page - double epsX1, epsY1, // EPS bounding box (unrotated) - epsX2, epsY2; + GList *paperSizes; // list of used paper sizes, if paperMatch + // is true [PSOutPaperSize] + double tx0, ty0; // global translation + double xScale0, yScale0; // global scaling + int rotate0; // rotation angle (0, 90, 180, 270) + double clipLLX0, clipLLY0, + clipURX0, clipURY0; + double tx, ty; // global translation for current page + double xScale, yScale; // global scaling for current page + int rotate; // rotation angle for current page + double epsX1, epsY1, // EPS bounding box (unrotated) + epsX2, epsY2; - GString *embFontList; // resource comments for embedded fonts + GString *embFontList; // resource comments for embedded fonts - int processColors; // used process colors - PSOutCustomColor // used custom colors + int processColors; // used process colors + PSOutCustomColor // used custom colors *customColors; - GBool haveTextClip; // set if text has been drawn with a - // clipping render mode + GBool haveTextClip; // set if text has been drawn with a + // clipping render mode - GBool inType3Char; // inside a Type 3 CharProc - GString *t3String; // Type 3 content string - double t3WX, t3WY, // Type 3 character parameters - t3LLX, t3LLY, t3URX, t3URY; - GBool t3FillColorOnly; // operators should only use the fill color - GBool t3Cacheable; // cleared if char is not cacheable - GBool t3NeedsRestore; // set if a 'q' operator was issued + GBool inType3Char; // inside a Type 3 CharProc + GString *t3String; // Type 3 content string + double t3WX, t3WY, // Type 3 character parameters + t3LLX, t3LLY, t3URX, t3URY; + GBool t3FillColorOnly; // operators should only use the fill color + GBool t3Cacheable; // cleared if char is not cacheable + GBool t3NeedsRestore; // set if a 'q' operator was issued #if OPI_SUPPORT - int opi13Nest; // nesting level of OPI 1.3 objects - int opi20Nest; // nesting level of OPI 2.0 objects + int opi13Nest; // nesting level of OPI 1.3 objects + int opi20Nest; // nesting level of OPI 2.0 objects #endif - GBool ok; // set up ok? + GBool ok; // set up ok? - friend class WinPDFPrinter; + friend class WinPDFPrinter; }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-10020/Splash.h b/test/bug-hunting/cve/CVE-2019-10020/Splash.h index 423ed3605..dc6675121 100644 --- a/test/bug-hunting/cve/CVE-2019-10020/Splash.h +++ b/test/bug-hunting/cve/CVE-2019-10020/Splash.h @@ -40,27 +40,27 @@ typedef GBool (*SplashImageMaskSource)(void *data, Guchar *pixel); // * and returns true. If the image stream is exhausted, // returns false. typedef GBool (*SplashImageSource)(void *data, SplashColorPtr colorLine, - Guchar *alphaLine); + Guchar *alphaLine); //------------------------------------------------------------------------ enum SplashPipeResultColorCtrl { - splashPipeResultColorNoAlphaBlendMono, - splashPipeResultColorNoAlphaBlendRGB, + splashPipeResultColorNoAlphaBlendMono, + splashPipeResultColorNoAlphaBlendRGB, #if SPLASH_CMYK - splashPipeResultColorNoAlphaBlendCMYK, + splashPipeResultColorNoAlphaBlendCMYK, #endif - splashPipeResultColorAlphaNoBlendMono, - splashPipeResultColorAlphaNoBlendRGB, + splashPipeResultColorAlphaNoBlendMono, + splashPipeResultColorAlphaNoBlendRGB, #if SPLASH_CMYK - splashPipeResultColorAlphaNoBlendCMYK, + splashPipeResultColorAlphaNoBlendCMYK, #endif - splashPipeResultColorAlphaBlendMono, - splashPipeResultColorAlphaBlendRGB + splashPipeResultColorAlphaBlendMono, + splashPipeResultColorAlphaBlendRGB #if SPLASH_CMYK - , - splashPipeResultColorAlphaBlendCMYK + , + splashPipeResultColorAlphaBlendCMYK #endif }; @@ -71,367 +71,379 @@ enum SplashPipeResultColorCtrl { class Splash { public: - // Create a new rasterizer object. - Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, - SplashScreenParams *screenParams = NULL); - Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, - SplashScreen *screenA); + // Create a new rasterizer object. + Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, + SplashScreenParams *screenParams = NULL); + Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, + SplashScreen *screenA); - ~Splash(); + ~Splash(); - //----- state read + //----- state read - SplashCoord *getMatrix(); - SplashPattern *getStrokePattern(); - SplashPattern *getFillPattern(); - SplashScreen *getScreen(); - SplashBlendFunc getBlendFunc(); - SplashCoord getStrokeAlpha(); - SplashCoord getFillAlpha(); - SplashCoord getLineWidth(); - int getLineCap(); - int getLineJoin(); - SplashCoord getMiterLimit(); - SplashCoord getFlatness(); - SplashCoord *getLineDash(); - int getLineDashLength(); - SplashCoord getLineDashPhase(); - SplashStrokeAdjustMode getStrokeAdjust(); - SplashClip *getClip(); - SplashBitmap *getSoftMask(); - GBool getInNonIsolatedGroup(); - GBool getInKnockoutGroup(); + SplashCoord *getMatrix(); + SplashPattern *getStrokePattern(); + SplashPattern *getFillPattern(); + SplashScreen *getScreen(); + SplashBlendFunc getBlendFunc(); + SplashCoord getStrokeAlpha(); + SplashCoord getFillAlpha(); + SplashCoord getLineWidth(); + int getLineCap(); + int getLineJoin(); + SplashCoord getMiterLimit(); + SplashCoord getFlatness(); + SplashCoord *getLineDash(); + int getLineDashLength(); + SplashCoord getLineDashPhase(); + SplashStrokeAdjustMode getStrokeAdjust(); + SplashClip *getClip(); + SplashBitmap *getSoftMask(); + GBool getInNonIsolatedGroup(); + GBool getInKnockoutGroup(); - //----- state write + //----- state write - void setMatrix(SplashCoord *matrix); - void setStrokePattern(SplashPattern *strokeColor); - void setFillPattern(SplashPattern *fillColor); - void setScreen(SplashScreen *screen); - void setBlendFunc(SplashBlendFunc func); - void setStrokeAlpha(SplashCoord alpha); - void setFillAlpha(SplashCoord alpha); - void setLineWidth(SplashCoord lineWidth); - void setLineCap(int lineCap); - void setLineJoin(int lineJoin); - void setMiterLimit(SplashCoord miterLimit); - void setFlatness(SplashCoord flatness); - // the array will be copied - void setLineDash(SplashCoord *lineDash, int lineDashLength, - SplashCoord lineDashPhase); - void setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust); - // NB: uses transformed coordinates. - void clipResetToRect(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1); - // NB: uses transformed coordinates. - SplashError clipToRect(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1); - // NB: uses untransformed coordinates. - SplashError clipToPath(SplashPath *path, GBool eo); - void setSoftMask(SplashBitmap *softMask); - void setInTransparencyGroup(SplashBitmap *groupBackBitmapA, - int groupBackXA, int groupBackYA, - GBool nonIsolated, GBool knockout); - void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray); - void setOverprintMask(Guint overprintMask); - void setEnablePathSimplification(GBool en); + void setMatrix(SplashCoord *matrix); + void setStrokePattern(SplashPattern *strokeColor); + void setFillPattern(SplashPattern *fillColor); + void setScreen(SplashScreen *screen); + void setBlendFunc(SplashBlendFunc func); + void setStrokeAlpha(SplashCoord alpha); + void setFillAlpha(SplashCoord alpha); + void setLineWidth(SplashCoord lineWidth); + void setLineCap(int lineCap); + void setLineJoin(int lineJoin); + void setMiterLimit(SplashCoord miterLimit); + void setFlatness(SplashCoord flatness); + // the array will be copied + void setLineDash(SplashCoord *lineDash, int lineDashLength, + SplashCoord lineDashPhase); + void setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust); + // NB: uses transformed coordinates. + void clipResetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + // NB: uses transformed coordinates. + SplashError clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + // NB: uses untransformed coordinates. + SplashError clipToPath(SplashPath *path, GBool eo); + void setSoftMask(SplashBitmap *softMask); + void setInTransparencyGroup(SplashBitmap *groupBackBitmapA, + int groupBackXA, int groupBackYA, + GBool nonIsolated, GBool knockout); + void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray); + void setOverprintMask(Guint overprintMask); + void setEnablePathSimplification(GBool en); - //----- state save/restore + //----- state save/restore - void saveState(); - SplashError restoreState(); + void saveState(); + SplashError restoreState(); - //----- drawing operations + //----- drawing operations - // Fill the bitmap with . This is not subject to clipping. - void clear(SplashColorPtr color, Guchar alpha = 0x00); + // Fill the bitmap with . This is not subject to clipping. + void clear(SplashColorPtr color, Guchar alpha = 0x00); - // Stroke a path using the current stroke pattern. - SplashError stroke(SplashPath *path); + // Stroke a path using the current stroke pattern. + SplashError stroke(SplashPath *path); - // Fill a path using the current fill pattern. - SplashError fill(SplashPath *path, GBool eo); + // Fill a path using the current fill pattern. + SplashError fill(SplashPath *path, GBool eo); - // Draw a character, using the current fill pattern. - SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font); + // Draw a character, using the current fill pattern. + SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font); - // Draw a glyph, using the current fill pattern. This function does - // not free any data, i.e., it ignores glyph->freeData. - SplashError fillGlyph(SplashCoord x, SplashCoord y, - SplashGlyphBitmap *glyph); + // Draw a glyph, using the current fill pattern. This function does + // not free any data, i.e., it ignores glyph->freeData. + SplashError fillGlyph(SplashCoord x, SplashCoord y, + SplashGlyphBitmap *glyph); - // Draws an image mask using the fill color. This will read - // lines of pixels from , starting with the top line. "1" - // pixels will be drawn with the current fill color; "0" pixels are - // transparent. The matrix: - // [ mat[0] mat[1] 0 ] - // [ mat[2] mat[3] 0 ] - // [ mat[4] mat[5] 1 ] - // maps a unit square to the desired destination for the image, in - // PostScript style: - // [x' y' 1] = [x y 1] * mat - // Note that the Splash y axis points downward, and the image source - // is assumed to produce pixels in raster order, starting from the - // top line. - SplashError fillImageMask(SplashImageMaskSource src, void *srcData, - int w, int h, SplashCoord *mat, - GBool glyphMode, GBool interpolate); + // Draws an image mask using the fill color. This will read + // lines of pixels from , starting with the top line. "1" + // pixels will be drawn with the current fill color; "0" pixels are + // transparent. The matrix: + // [ mat[0] mat[1] 0 ] + // [ mat[2] mat[3] 0 ] + // [ mat[4] mat[5] 1 ] + // maps a unit square to the desired destination for the image, in + // PostScript style: + // [x' y' 1] = [x y 1] * mat + // Note that the Splash y axis points downward, and the image source + // is assumed to produce pixels in raster order, starting from the + // top line. + SplashError fillImageMask(SplashImageMaskSource src, void *srcData, + int w, int h, SplashCoord *mat, + GBool glyphMode, GBool interpolate); - // Draw an image. This will read lines of pixels from - // , starting with the top line. These pixels are assumed to - // be in the source mode, . If is true, the - // alpha values returned by are used; otherwise they are - // ignored. The following combinations of source and target modes - // are supported: - // source target - // ------ ------ - // Mono8 Mono1 -- with dithering - // Mono8 Mono8 - // RGB8 RGB8 - // BGR8 RGB8 - // CMYK8 CMYK8 - // The matrix behaves as for fillImageMask. - SplashError drawImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, GBool srcAlpha, - int w, int h, SplashCoord *mat, - GBool interpolate); + // Draw an image. This will read lines of pixels from + // , starting with the top line. These pixels are assumed to + // be in the source mode, . If is true, the + // alpha values returned by are used; otherwise they are + // ignored. The following combinations of source and target modes + // are supported: + // source target + // ------ ------ + // Mono8 Mono1 -- with dithering + // Mono8 Mono8 + // RGB8 RGB8 + // BGR8 RGB8 + // CMYK8 CMYK8 + // The matrix behaves as for fillImageMask. + SplashError drawImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, GBool srcAlpha, + int w, int h, SplashCoord *mat, + GBool interpolate); - // Composite a rectangular region from onto this Splash - // object. - SplashError composite(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h, - GBool noClip, GBool nonIsolated); + // Composite a rectangular region from onto this Splash + // object. + SplashError composite(SplashBitmap *src, int xSrc, int ySrc, + int xDest, int yDest, int w, int h, + GBool noClip, GBool nonIsolated); - // Composite this Splash object onto a background color. The - // background alpha is assumed to be 1. - void compositeBackground(SplashColorPtr color); + // Composite this Splash object onto a background color. The + // background alpha is assumed to be 1. + void compositeBackground(SplashColorPtr color); - // Copy a rectangular region from onto the bitmap belonging to - // this Splash object. The destination alpha values are all set to - // zero. - SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h); + // Copy a rectangular region from onto the bitmap belonging to + // this Splash object. The destination alpha values are all set to + // zero. + SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc, + int xDest, int yDest, int w, int h); - // Copy a rectangular region from the bitmap belonging to this - // Splash object to . The alpha values are corrected for a - // non-isolated group. - SplashError blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc, - int xDest, int yDest, int w, int h); + // Copy a rectangular region from the bitmap belonging to this + // Splash object to . The alpha values are corrected for a + // non-isolated group. + SplashError blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc, + int xDest, int yDest, int w, int h); - //----- misc + //----- misc - // Construct a path for a stroke, given the path to be stroked and - // the line width . All other stroke parameters are taken from - // the current state. If is true, this function will - // first flatten the path and handle the linedash. - SplashPath *makeStrokePath(SplashPath *path, SplashCoord w, - int lineCap, int lineJoin, - GBool flatten = gTrue); + // Construct a path for a stroke, given the path to be stroked and + // the line width . All other stroke parameters are taken from + // the current state. If is true, this function will + // first flatten the path and handle the linedash. + SplashPath *makeStrokePath(SplashPath *path, SplashCoord w, + int lineCap, int lineJoin, + GBool flatten = gTrue); - // Reduce the size of a rectangle as much as possible by moving any - // edges that are completely outside the clip region. Returns the - // clipping status of the resulting rectangle. - SplashClipResult limitRectToClipRect(int *xMin, int *yMin, - int *xMax, int *yMax); + // Reduce the size of a rectangle as much as possible by moving any + // edges that are completely outside the clip region. Returns the + // clipping status of the resulting rectangle. + SplashClipResult limitRectToClipRect(int *xMin, int *yMin, + int *xMax, int *yMax); - // Return the associated bitmap. - SplashBitmap *getBitmap() { return bitmap; } + // Return the associated bitmap. + SplashBitmap *getBitmap() { + return bitmap; + } - // Set the minimum line width. - void setMinLineWidth(SplashCoord w) { minLineWidth = w; } + // Set the minimum line width. + void setMinLineWidth(SplashCoord w) { + minLineWidth = w; + } - // Get a bounding box which includes all modifications since the - // last call to clearModRegion. - void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax) - { *xMin = modXMin; *yMin = modYMin; *xMax = modXMax; *yMax = modYMax; } + // Get a bounding box which includes all modifications since the + // last call to clearModRegion. + void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax) + { + *xMin = modXMin; *yMin = modYMin; *xMax = modXMax; *yMax = modYMax; + } - // Clear the modified region bounding box. - void clearModRegion(); + // Clear the modified region bounding box. + void clearModRegion(); - // Get clipping status for the last drawing operation subject to - // clipping. - SplashClipResult getClipRes() { return opClipRes; } + // Get clipping status for the last drawing operation subject to + // clipping. + SplashClipResult getClipRes() { + return opClipRes; + } - // Toggle debug mode on or off. - void setDebugMode(GBool debugModeA) { debugMode = debugModeA; } + // Toggle debug mode on or off. + void setDebugMode(GBool debugModeA) { + debugMode = debugModeA; + } #if 1 //~tmp: turn off anti-aliasing temporarily - void setInShading(GBool sh) { inShading = sh; } + void setInShading(GBool sh) { + inShading = sh; + } #endif private: - void pipeInit(SplashPipe *pipe, SplashPattern *pattern, - Guchar aInput, GBool usesShape, - GBool nonIsolatedGroup); - void pipeRun(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeInit(SplashPipe *pipe, SplashPattern *pattern, + Guchar aInput, GBool usesShape, + GBool nonIsolatedGroup); + void pipeRun(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #if SPLASH_CMYK - void pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #endif - void pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #if SPLASH_CMYK - void pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #endif - void pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #if SPLASH_CMYK - void pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #endif - void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, - SplashCoord *xo, SplashCoord *yo); - void updateModX(int x); - void updateModY(int y); - void strokeNarrow(SplashPath *path); - void drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip); - void strokeWide(SplashPath *path, SplashCoord w, - int lineCap, int lineJoin); - SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix, - SplashCoord flatness); - void flattenCurve(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1, - SplashCoord x2, SplashCoord y2, - SplashCoord x3, SplashCoord y3, - SplashCoord *matrix, SplashCoord flatness2, - SplashPath *fPath); - SplashPath *makeDashedPath(SplashPath *xPath); - SplashError fillWithPattern(SplashPath *path, GBool eo, - SplashPattern *pattern, SplashCoord alpha); - SplashPath *tweakFillPath(SplashPath *path); - GBool pathAllOutside(SplashPath *path); - SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph); - void getImageBounds(SplashCoord xyMin, SplashCoord xyMax, - int *xyMinI, int *xyMaxI); - void upscaleMask(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - SplashCoord *mat, GBool glyphMode, - GBool interpolate); - void arbitraryTransformMask(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - SplashCoord *mat, GBool glyphMode, - GBool interpolate); - SplashBitmap *scaleMask(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - GBool interpolate); - void scaleMaskYdXd(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleMaskYdXu(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleMaskYuXd(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleMaskYuXu(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleMaskYuXuI(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void blitMask(SplashBitmap *src, int xDest, int yDest, - SplashClipResult clipRes); - void upscaleImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - SplashCoord *mat, GBool interpolate); - void arbitraryTransformImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, - int srcWidth, int srcHeight, - SplashCoord *mat, GBool interpolate); - SplashBitmap *scaleImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - GBool interpolate); - void scaleImageYdXd(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleImageYdXu(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleImageYuXd(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleImageYuXu(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleImageYuXuI(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void vertFlipImage(SplashBitmap *img, int width, int height, - int nComps); - void horizFlipImage(SplashBitmap *img, int width, int height, - int nComps); - void blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest, - SplashClipResult clipRes); - void blitImageClipped(SplashBitmap *src, GBool srcAlpha, - int xSrc, int ySrc, int xDest, int yDest, - int w, int h); - void dumpPath(SplashPath *path); - void dumpXPath(SplashXPath *path); + void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, + SplashCoord *xo, SplashCoord *yo); + void updateModX(int x); + void updateModY(int y); + void strokeNarrow(SplashPath *path); + void drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip); + void strokeWide(SplashPath *path, SplashCoord w, + int lineCap, int lineJoin); + SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness); + void flattenCurve(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord x2, SplashCoord y2, + SplashCoord x3, SplashCoord y3, + SplashCoord *matrix, SplashCoord flatness2, + SplashPath *fPath); + SplashPath *makeDashedPath(SplashPath *xPath); + SplashError fillWithPattern(SplashPath *path, GBool eo, + SplashPattern *pattern, SplashCoord alpha); + SplashPath *tweakFillPath(SplashPath *path); + GBool pathAllOutside(SplashPath *path); + SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph); + void getImageBounds(SplashCoord xyMin, SplashCoord xyMax, + int *xyMinI, int *xyMaxI); + void upscaleMask(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + SplashCoord *mat, GBool glyphMode, + GBool interpolate); + void arbitraryTransformMask(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + SplashCoord *mat, GBool glyphMode, + GBool interpolate); + SplashBitmap *scaleMask(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + GBool interpolate); + void scaleMaskYdXd(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleMaskYdXu(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleMaskYuXd(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleMaskYuXu(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleMaskYuXuI(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void blitMask(SplashBitmap *src, int xDest, int yDest, + SplashClipResult clipRes); + void upscaleImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + SplashCoord *mat, GBool interpolate); + void arbitraryTransformImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, + int srcWidth, int srcHeight, + SplashCoord *mat, GBool interpolate); + SplashBitmap *scaleImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + GBool interpolate); + void scaleImageYdXd(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleImageYdXu(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleImageYuXd(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleImageYuXu(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleImageYuXuI(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void vertFlipImage(SplashBitmap *img, int width, int height, + int nComps); + void horizFlipImage(SplashBitmap *img, int width, int height, + int nComps); + void blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest, + SplashClipResult clipRes); + void blitImageClipped(SplashBitmap *src, GBool srcAlpha, + int xSrc, int ySrc, int xDest, int yDest, + int w, int h); + void dumpPath(SplashPath *path); + void dumpXPath(SplashXPath *path); - static SplashPipeResultColorCtrl pipeResultColorNoAlphaBlend[]; - static SplashPipeResultColorCtrl pipeResultColorAlphaNoBlend[]; - static SplashPipeResultColorCtrl pipeResultColorAlphaBlend[]; - static int pipeNonIsoGroupCorrection[]; + static SplashPipeResultColorCtrl pipeResultColorNoAlphaBlend[]; + static SplashPipeResultColorCtrl pipeResultColorAlphaNoBlend[]; + static SplashPipeResultColorCtrl pipeResultColorAlphaBlend[]; + static int pipeNonIsoGroupCorrection[]; - SplashBitmap *bitmap; - int bitmapComps; - SplashState *state; - Guchar *scanBuf; - Guchar *scanBuf2; - SplashBitmap // for transparency groups, this is the bitmap - *groupBackBitmap; // containing the alpha0/color0 values - int groupBackX, groupBackY; // offset within groupBackBitmap - SplashCoord minLineWidth; - int modXMin, modYMin, modXMax, modYMax; - SplashClipResult opClipRes; - GBool vectorAntialias; - GBool inShading; - GBool debugMode; + SplashBitmap *bitmap; + int bitmapComps; + SplashState *state; + Guchar *scanBuf; + Guchar *scanBuf2; + SplashBitmap // for transparency groups, this is the bitmap + *groupBackBitmap; // containing the alpha0/color0 values + int groupBackX, groupBackY; // offset within groupBackBitmap + SplashCoord minLineWidth; + int modXMin, modYMin, modXMax, modYMax; + SplashClipResult opClipRes; + GBool vectorAntialias; + GBool inShading; + GBool debugMode; }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-10021/Stream.h b/test/bug-hunting/cve/CVE-2019-10021/Stream.h index c25d46b2c..3c036e9c3 100644 --- a/test/bug-hunting/cve/CVE-2019-10021/Stream.h +++ b/test/bug-hunting/cve/CVE-2019-10021/Stream.h @@ -30,24 +30,24 @@ class SharedFile; //------------------------------------------------------------------------ enum StreamKind { - strFile, - strASCIIHex, - strASCII85, - strLZW, - strRunLength, - strCCITTFax, - strDCT, - strFlate, - strJBIG2, - strJPX, - strWeird // internal-use stream types + strFile, + strASCIIHex, + strASCII85, + strLZW, + strRunLength, + strCCITTFax, + strDCT, + strFlate, + strJBIG2, + strJPX, + strWeird // internal-use stream types }; enum StreamColorSpaceMode { - streamCSNone, - streamCSDeviceGray, - streamCSDeviceRGB, - streamCSDeviceCMYK + streamCSNone, + streamCSDeviceGray, + streamCSDeviceRGB, + streamCSDeviceCMYK }; //------------------------------------------------------------------------ @@ -55,9 +55,9 @@ enum StreamColorSpaceMode { // This is in Stream.h instead of Decrypt.h to avoid really annoying // include file dependency loops. enum CryptAlgorithm { - cryptRC4, - cryptAES, - cryptAES256 + cryptRC4, + cryptAES, + cryptAES256 }; //------------------------------------------------------------------------ @@ -67,88 +67,94 @@ enum CryptAlgorithm { class Stream { public: - // Constructor. - Stream(); + // Constructor. + Stream(); - // Destructor. - virtual ~Stream(); + // Destructor. + virtual ~Stream(); - virtual Stream *copy() = 0; + virtual Stream *copy() = 0; - // Get kind of stream. - virtual StreamKind getKind() = 0; + // Get kind of stream. + virtual StreamKind getKind() = 0; - virtual GBool isEmbedStream() { return gFalse; } + virtual GBool isEmbedStream() { + return gFalse; + } - // Reset stream to beginning. - virtual void reset() = 0; + // Reset stream to beginning. + virtual void reset() = 0; - // Close down the stream. - virtual void close(); + // Close down the stream. + virtual void close(); - // Get next char from stream. - virtual int getChar() = 0; + // Get next char from stream. + virtual int getChar() = 0; - // Peek at next char in stream. - virtual int lookChar() = 0; + // Peek at next char in stream. + virtual int lookChar() = 0; - // Get next char from stream without using the predictor. - // This is only used by StreamPredictor. - virtual int getRawChar(); + // Get next char from stream without using the predictor. + // This is only used by StreamPredictor. + virtual int getRawChar(); - // Get exactly bytes from stream. Returns the number of - // bytes read -- the returned count will be less than at EOF. - virtual int getBlock(char *blk, int size); + // Get exactly bytes from stream. Returns the number of + // bytes read -- the returned count will be less than at EOF. + virtual int getBlock(char *blk, int size); - // Get next line from stream. - virtual char *getLine(char *buf, int size); + // Get next line from stream. + virtual char *getLine(char *buf, int size); - // Discard the next bytes from stream. Returns the number of - // bytes discarded, which will be less than only if EOF is - // reached. - virtual Guint discardChars(Guint n); + // Discard the next bytes from stream. Returns the number of + // bytes discarded, which will be less than only if EOF is + // reached. + virtual Guint discardChars(Guint n); - // Get current position in file. - virtual GFileOffset getPos() = 0; + // Get current position in file. + virtual GFileOffset getPos() = 0; - // Go to a position in the stream. If is negative, the - // position is from the end of the file; otherwise the position is - // from the start of the file. - virtual void setPos(GFileOffset pos, int dir = 0) = 0; + // Go to a position in the stream. If is negative, the + // position is from the end of the file; otherwise the position is + // from the start of the file. + virtual void setPos(GFileOffset pos, int dir = 0) = 0; - // Get PostScript command for the filter(s). - virtual GString *getPSFilter(int psLevel, const char *indent); + // Get PostScript command for the filter(s). + virtual GString *getPSFilter(int psLevel, const char *indent); - // Does this stream type potentially contain non-printable chars? - virtual GBool isBinary(GBool last = gTrue) = 0; + // Does this stream type potentially contain non-printable chars? + virtual GBool isBinary(GBool last = gTrue) = 0; - // Get the BaseStream of this stream. - virtual BaseStream *getBaseStream() = 0; + // Get the BaseStream of this stream. + virtual BaseStream *getBaseStream() = 0; - // Get the stream after the last decoder (this may be a BaseStream - // or a DecryptStream). - virtual Stream *getUndecodedStream() = 0; + // Get the stream after the last decoder (this may be a BaseStream + // or a DecryptStream). + virtual Stream *getUndecodedStream() = 0; - // Get the dictionary associated with this stream. - virtual Dict *getDict() = 0; + // Get the dictionary associated with this stream. + virtual Dict *getDict() = 0; - // Is this an encoding filter? - virtual GBool isEncoder() { return gFalse; } + // Is this an encoding filter? + virtual GBool isEncoder() { + return gFalse; + } - // Get image parameters which are defined by the stream contents. - virtual void getImageParams(int *bitsPerComponent, - StreamColorSpaceMode *csMode) {} + // Get image parameters which are defined by the stream contents. + virtual void getImageParams(int *bitsPerComponent, + StreamColorSpaceMode *csMode) {} - // Return the next stream in the "stack". - virtual Stream *getNextStream() { return NULL; } + // Return the next stream in the "stack". + virtual Stream *getNextStream() { + return NULL; + } - // Add filters to this stream according to the parameters in . - // Returns the new stream. - Stream *addFilters(Object *dict, int recursion = 0); + // Add filters to this stream according to the parameters in . + // Returns the new stream. + Stream *addFilters(Object *dict, int recursion = 0); private: - Stream *makeFilter(char *name, Stream *str, Object *params, int recursion); + Stream *makeFilter(char *name, Stream *str, Object *params, int recursion); }; //------------------------------------------------------------------------ @@ -157,27 +163,37 @@ private: // This is the base class for all streams that read directly from a file. //------------------------------------------------------------------------ -class BaseStream: public Stream { +class BaseStream : public Stream { public: - BaseStream(Object *dictA); - virtual ~BaseStream(); - virtual Stream *makeSubStream(GFileOffset start, GBool limited, - GFileOffset length, Object *dict) = 0; - virtual void setPos(GFileOffset pos, int dir = 0) = 0; - virtual GBool isBinary(GBool last = gTrue) { return last; } - virtual BaseStream *getBaseStream() { return this; } - virtual Stream *getUndecodedStream() { return this; } - virtual Dict *getDict() { return dict.getDict(); } - virtual GString *getFileName() { return NULL; } + BaseStream(Object *dictA); + virtual ~BaseStream(); + virtual Stream *makeSubStream(GFileOffset start, GBool limited, + GFileOffset length, Object *dict) = 0; + virtual void setPos(GFileOffset pos, int dir = 0) = 0; + virtual GBool isBinary(GBool last = gTrue) { + return last; + } + virtual BaseStream *getBaseStream() { + return this; + } + virtual Stream *getUndecodedStream() { + return this; + } + virtual Dict *getDict() { + return dict.getDict(); + } + virtual GString *getFileName() { + return NULL; + } - // Get/set position of first byte of stream within the file. - virtual GFileOffset getStart() = 0; - virtual void moveStart(int delta) = 0; + // Get/set position of first byte of stream within the file. + virtual GFileOffset getStart() = 0; + virtual void moveStart(int delta) = 0; protected: - Object dict; + Object dict; }; //------------------------------------------------------------------------ @@ -186,22 +202,32 @@ protected: // This is the base class for all streams that filter another stream. //------------------------------------------------------------------------ -class FilterStream: public Stream { +class FilterStream : public Stream { public: - FilterStream(Stream *strA); - virtual ~FilterStream(); - virtual void close(); - virtual GFileOffset getPos() { return str->getPos(); } - virtual void setPos(GFileOffset pos, int dir = 0); - virtual BaseStream *getBaseStream() { return str->getBaseStream(); } - virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); } - virtual Dict *getDict() { return str->getDict(); } - virtual Stream *getNextStream() { return str; } + FilterStream(Stream *strA); + virtual ~FilterStream(); + virtual void close(); + virtual GFileOffset getPos() { + return str->getPos(); + } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual BaseStream *getBaseStream() { + return str->getBaseStream(); + } + virtual Stream *getUndecodedStream() { + return str->getUndecodedStream(); + } + virtual Dict *getDict() { + return str->getDict(); + } + virtual Stream *getNextStream() { + return str; + } protected: - Stream *str; + Stream *str; }; //------------------------------------------------------------------------ @@ -211,41 +237,41 @@ protected: class ImageStream { public: - // Create an image stream object for an image with the specified - // parameters. Note that these are the actual image parameters, - // which may be different from the predictor parameters. - ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA); + // Create an image stream object for an image with the specified + // parameters. Note that these are the actual image parameters, + // which may be different from the predictor parameters. + ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA); - ~ImageStream(); + ~ImageStream(); - // Reset the stream. - void reset(); + // Reset the stream. + void reset(); - // Close down the stream. - void close(); + // Close down the stream. + void close(); - // Gets the next pixel from the stream. should be able to hold - // at least nComps elements. Returns false at end of file. - GBool getPixel(Guchar *pix); + // Gets the next pixel from the stream. should be able to hold + // at least nComps elements. Returns false at end of file. + GBool getPixel(Guchar *pix); - // Returns a pointer to the next line of pixels. Returns NULL at - // end of file. - Guchar *getLine(); + // Returns a pointer to the next line of pixels. Returns NULL at + // end of file. + Guchar *getLine(); - // Skip an entire line from the image. - void skipLine(); + // Skip an entire line from the image. + void skipLine(); private: - Stream *str; // base stream - int width; // pixels per line - int nComps; // components per pixel - int nBits; // bits per component - int nVals; // components per line - int inputLineSize; // input line buffer size - char *inputLine; // input line buffer - Guchar *imgLine; // line buffer - int imgIdx; // current index in imgLine + Stream *str; // base stream + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + int inputLineSize; // input line buffer size + char *inputLine; // input line buffer + Guchar *imgLine; // line buffer + int imgIdx; // current index in imgLine }; @@ -256,41 +282,51 @@ private: class StreamPredictor { public: - // Create a predictor object. Note that the parameters are for the - // predictor, and may not match the actual image parameters. - StreamPredictor(Stream *strA, int predictorA, - int widthA, int nCompsA, int nBitsA); + // Create a predictor object. Note that the parameters are for the + // predictor, and may not match the actual image parameters. + StreamPredictor(Stream *strA, int predictorA, + int widthA, int nCompsA, int nBitsA); - ~StreamPredictor(); + ~StreamPredictor(); - GBool isOk() { return ok; } + GBool isOk() { + return ok; + } - void reset(); + void reset(); - int lookChar(); - int getChar(); - int getBlock(char *blk, int size); + int lookChar(); + int getChar(); + int getBlock(char *blk, int size); - int getPredictor() { return predictor; } - int getWidth() { return width; } - int getNComps() { return nComps; } - int getNBits() { return nBits; } + int getPredictor() { + return predictor; + } + int getWidth() { + return width; + } + int getNComps() { + return nComps; + } + int getNBits() { + return nBits; + } private: - GBool getNextLine(); + GBool getNextLine(); - Stream *str; // base stream - int predictor; // predictor - int width; // pixels per line - int nComps; // components per pixel - int nBits; // bits per component - int nVals; // components per line - int pixBytes; // bytes per pixel - int rowBytes; // bytes per line - Guchar *predLine; // line buffer - int predIdx; // current index in predLine - GBool ok; + Stream *str; // base stream + int predictor; // predictor + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + int pixBytes; // bytes per pixel + int rowBytes; // bytes per line + Guchar *predLine; // line buffer + int predIdx; // current index in predLine + GBool ok; }; //------------------------------------------------------------------------ @@ -299,76 +335,96 @@ private: #define fileStreamBufSize 256 -class FileStream: public BaseStream { +class FileStream : public BaseStream { public: - FileStream(FILE *fA, GFileOffset startA, GBool limitedA, - GFileOffset lengthA, Object *dictA); - virtual ~FileStream(); - virtual Stream *copy(); - virtual Stream *makeSubStream(GFileOffset startA, GBool limitedA, - GFileOffset lengthA, Object *dictA); - virtual StreamKind getKind() { return strFile; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual int getBlock(char *blk, int size); - virtual GFileOffset getPos() { return bufPos + (int)(bufPtr - buf); } - virtual void setPos(GFileOffset pos, int dir = 0); - virtual GFileOffset getStart() { return start; } - virtual void moveStart(int delta); + FileStream(FILE *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual ~FileStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { + return strFile; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { + return bufPos + (int)(bufPtr - buf); + } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart() { + return start; + } + virtual void moveStart(int delta); private: - FileStream(SharedFile *fA, GFileOffset startA, GBool limitedA, - GFileOffset lengthA, Object *dictA); - GBool fillBuf(); + FileStream(SharedFile *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + GBool fillBuf(); - SharedFile *f; - GFileOffset start; - GBool limited; - GFileOffset length; - char buf[fileStreamBufSize]; - char *bufPtr; - char *bufEnd; - GFileOffset bufPos; + SharedFile *f; + GFileOffset start; + GBool limited; + GFileOffset length; + char buf[fileStreamBufSize]; + char *bufPtr; + char *bufEnd; + GFileOffset bufPos; }; //------------------------------------------------------------------------ // MemStream //------------------------------------------------------------------------ -class MemStream: public BaseStream { +class MemStream : public BaseStream { public: - MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); - virtual ~MemStream(); - virtual Stream *copy(); - virtual Stream *makeSubStream(GFileOffset start, GBool limited, - GFileOffset lengthA, Object *dictA); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual void close(); - virtual int getChar() - { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; } - virtual int lookChar() - { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; } - virtual int getBlock(char *blk, int size); - virtual GFileOffset getPos() { return (GFileOffset)(bufPtr - buf); } - virtual void setPos(GFileOffset pos, int dir = 0); - virtual GFileOffset getStart() { return start; } - virtual void moveStart(int delta); + MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); + virtual ~MemStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset start, GBool limited, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual void close(); + virtual int getChar() + { + return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; + } + virtual int lookChar() + { + return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; + } + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { + return (GFileOffset)(bufPtr - buf); + } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart() { + return start; + } + virtual void moveStart(int delta); private: - char *buf; - Guint start; - Guint length; - char *bufEnd; - char *bufPtr; - GBool needFree; + char *buf; + Guint start; + Guint length; + char *bufEnd; + char *bufPtr; + GBool needFree; }; //------------------------------------------------------------------------ @@ -381,156 +437,178 @@ private: // that creating a new FileStream (using makeSubStream). //------------------------------------------------------------------------ -class EmbedStream: public BaseStream { +class EmbedStream : public BaseStream { public: - EmbedStream(Stream *strA, Object *dictA, GBool limitedA, GFileOffset lengthA); - virtual ~EmbedStream(); - virtual Stream *copy(); - virtual Stream *makeSubStream(GFileOffset start, GBool limitedA, - GFileOffset lengthA, Object *dictA); - virtual StreamKind getKind() { return str->getKind(); } - virtual GBool isEmbedStream() { return gTrue; } - virtual void reset() {} - virtual int getChar(); - virtual int lookChar(); - virtual int getBlock(char *blk, int size); - virtual GFileOffset getPos() { return str->getPos(); } - virtual void setPos(GFileOffset pos, int dir = 0); - virtual GFileOffset getStart(); - virtual void moveStart(int delta); + EmbedStream(Stream *strA, Object *dictA, GBool limitedA, GFileOffset lengthA); + virtual ~EmbedStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset start, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { + return str->getKind(); + } + virtual GBool isEmbedStream() { + return gTrue; + } + virtual void reset() {} + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { + return str->getPos(); + } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart(); + virtual void moveStart(int delta); private: - Stream *str; - GBool limited; - GFileOffset length; + Stream *str; + GBool limited; + GFileOffset length; }; //------------------------------------------------------------------------ // ASCIIHexStream //------------------------------------------------------------------------ -class ASCIIHexStream: public FilterStream { +class ASCIIHexStream : public FilterStream { public: - ASCIIHexStream(Stream *strA); - virtual ~ASCIIHexStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strASCIIHex; } - virtual void reset(); - virtual int getChar() - { int c = lookChar(); buf = EOF; return c; } - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + ASCIIHexStream(Stream *strA); + virtual ~ASCIIHexStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strASCIIHex; + } + virtual void reset(); + virtual int getChar() + { + int c = lookChar(); buf = EOF; return c; + } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - int buf; - GBool eof; + int buf; + GBool eof; }; //------------------------------------------------------------------------ // ASCII85Stream //------------------------------------------------------------------------ -class ASCII85Stream: public FilterStream { +class ASCII85Stream : public FilterStream { public: - ASCII85Stream(Stream *strA); - virtual ~ASCII85Stream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strASCII85; } - virtual void reset(); - virtual int getChar() - { int ch = lookChar(); ++index; return ch; } - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + ASCII85Stream(Stream *strA); + virtual ~ASCII85Stream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strASCII85; + } + virtual void reset(); + virtual int getChar() + { + int ch = lookChar(); ++index; return ch; + } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - int c[5]; - int b[4]; - int index, n; - GBool eof; + int c[5]; + int b[4]; + int index, n; + GBool eof; }; //------------------------------------------------------------------------ // LZWStream //------------------------------------------------------------------------ -class LZWStream: public FilterStream { +class LZWStream : public FilterStream { public: - LZWStream(Stream *strA, int predictor, int columns, int colors, - int bits, int earlyA); - virtual ~LZWStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strLZW; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getRawChar(); - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + LZWStream(Stream *strA, int predictor, int columns, int colors, + int bits, int earlyA); + virtual ~LZWStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strLZW; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - StreamPredictor *pred; // predictor - int early; // early parameter - GBool eof; // true if at eof - int inputBuf; // input buffer - int inputBits; // number of bits in input buffer - struct { // decoding table - int length; - int head; - Guchar tail; - } table[4097]; - int nextCode; // next code to be used - int nextBits; // number of bits in next code word - int prevCode; // previous code used in stream - int newChar; // next char to be added to table - Guchar seqBuf[4097]; // buffer for current sequence - int seqLength; // length of current sequence - int seqIndex; // index into current sequence - GBool first; // first code after a table clear + StreamPredictor *pred; // predictor + int early; // early parameter + GBool eof; // true if at eof + int inputBuf; // input buffer + int inputBits; // number of bits in input buffer + struct { // decoding table + int length; + int head; + Guchar tail; + } table[4097]; + int nextCode; // next code to be used + int nextBits; // number of bits in next code word + int prevCode; // previous code used in stream + int newChar; // next char to be added to table + Guchar seqBuf[4097]; // buffer for current sequence + int seqLength; // length of current sequence + int seqIndex; // index into current sequence + GBool first; // first code after a table clear - GBool processNextCode(); - void clearTable(); - int getCode(); + GBool processNextCode(); + void clearTable(); + int getCode(); }; //------------------------------------------------------------------------ // RunLengthStream //------------------------------------------------------------------------ -class RunLengthStream: public FilterStream { +class RunLengthStream : public FilterStream { public: - RunLengthStream(Stream *strA); - virtual ~RunLengthStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strRunLength; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + RunLengthStream(Stream *strA); + virtual ~RunLengthStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strRunLength; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - char buf[128]; // buffer - char *bufPtr; // next char to read - char *bufEnd; // end of buffer - GBool eof; + char buf[128]; // buffer + char *bufPtr; // next char to read + char *bufEnd; // end of buffer + GBool eof; - GBool fillBuf(); + GBool fillBuf(); }; //------------------------------------------------------------------------ @@ -539,52 +617,56 @@ private: struct CCITTCodeTable; -class CCITTFaxStream: public FilterStream { +class CCITTFaxStream : public FilterStream { public: - CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, - GBool byteAlignA, int columnsA, int rowsA, - GBool endOfBlockA, GBool blackA); - virtual ~CCITTFaxStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strCCITTFax; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, + GBool byteAlignA, int columnsA, int rowsA, + GBool endOfBlockA, GBool blackA); + virtual ~CCITTFaxStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strCCITTFax; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - int encoding; // 'K' parameter - GBool endOfLine; // 'EndOfLine' parameter - GBool byteAlign; // 'EncodedByteAlign' parameter - int columns; // 'Columns' parameter - int rows; // 'Rows' parameter - GBool endOfBlock; // 'EndOfBlock' parameter - GBool black; // 'BlackIs1' parameter - int blackXOR; - GBool eof; // true if at eof - GBool nextLine2D; // true if next line uses 2D encoding - int row; // current row - Guint inputBuf; // input buffer - int inputBits; // number of bits in input buffer - int *codingLine; // coding line changing elements - int *refLine; // reference line changing elements - int nextCol; // next column to read - int a0i; // index into codingLine - GBool err; // error on current line - int nErrors; // number of errors so far in this stream + int encoding; // 'K' parameter + GBool endOfLine; // 'EndOfLine' parameter + GBool byteAlign; // 'EncodedByteAlign' parameter + int columns; // 'Columns' parameter + int rows; // 'Rows' parameter + GBool endOfBlock; // 'EndOfBlock' parameter + GBool black; // 'BlackIs1' parameter + int blackXOR; + GBool eof; // true if at eof + GBool nextLine2D; // true if next line uses 2D encoding + int row; // current row + Guint inputBuf; // input buffer + int inputBits; // number of bits in input buffer + int *codingLine; // coding line changing elements + int *refLine; // reference line changing elements + int nextCol; // next column to read + int a0i; // index into codingLine + GBool err; // error on current line + int nErrors; // number of errors so far in this stream - void addPixels(int a1, int blackPixels); - void addPixelsNeg(int a1, int blackPixels); - GBool readRow(); - short getTwoDimCode(); - short getWhiteCode(); - short getBlackCode(); - short lookBits(int n); - void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; } + void addPixels(int a1, int blackPixels); + void addPixelsNeg(int a1, int blackPixels); + GBool readRow(); + short getTwoDimCode(); + short getWhiteCode(); + short getBlackCode(); + short lookBits(int n); + void eatBits(int n) { + if ((inputBits -= n) < 0) inputBits = 0; + } }; //------------------------------------------------------------------------ @@ -598,148 +680,152 @@ class DCTStream; #define dctStreamBufSize 4096 struct DCTSourceMgr { - jpeg_source_mgr src; - DCTStream *str; - char buf[dctStreamBufSize]; + jpeg_source_mgr src; + DCTStream *str; + char buf[dctStreamBufSize]; }; struct DCTErrorMgr { - struct jpeg_error_mgr err; - jmp_buf setjmpBuf; + struct jpeg_error_mgr err; + jmp_buf setjmpBuf; }; #else // HAVE_JPEGLIB // DCT component info struct DCTCompInfo { - int id; // component ID - int hSample, vSample; // horiz/vert sampling resolutions - int quantTable; // quantization table number - int prevDC; // DC coefficient accumulator + int id; // component ID + int hSample, vSample; // horiz/vert sampling resolutions + int quantTable; // quantization table number + int prevDC; // DC coefficient accumulator }; struct DCTScanInfo { - GBool comp[4]; // comp[i] is set if component i is - // included in this scan - int numComps; // number of components in the scan - int dcHuffTable[4]; // DC Huffman table numbers - int acHuffTable[4]; // AC Huffman table numbers - int firstCoeff, lastCoeff; // first and last DCT coefficient - int ah, al; // successive approximation parameters + GBool comp[4]; // comp[i] is set if component i is + // included in this scan + int numComps; // number of components in the scan + int dcHuffTable[4]; // DC Huffman table numbers + int acHuffTable[4]; // AC Huffman table numbers + int firstCoeff, lastCoeff; // first and last DCT coefficient + int ah, al; // successive approximation parameters }; // DCT Huffman decoding table struct DCTHuffTable { - Guchar firstSym[17]; // first symbol for this bit length - Gushort firstCode[17]; // first code for this bit length - Gushort numCodes[17]; // number of codes of this bit length - Guchar sym[256]; // symbols + Guchar firstSym[17]; // first symbol for this bit length + Gushort firstCode[17]; // first code for this bit length + Gushort numCodes[17]; // number of codes of this bit length + Guchar sym[256]; // symbols }; #endif // HAVE_JPEGLIB -class DCTStream: public FilterStream { +class DCTStream : public FilterStream { public: - DCTStream(Stream *strA, int colorXformA); - virtual ~DCTStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strDCT; } - virtual void reset(); - virtual void close(); - virtual int getChar(); - virtual int lookChar(); - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); - Stream *getRawStream() { return str; } + DCTStream(Stream *strA, int colorXformA); + virtual ~DCTStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strDCT; + } + virtual void reset(); + virtual void close(); + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); + Stream *getRawStream() { + return str; + } private: #if HAVE_JPEGLIB - int colorXform; // color transform: -1 = unspecified - // 0 = none - // 1 = YUV/YUVK -> RGB/CMYK - jpeg_decompress_struct decomp; - DCTErrorMgr errorMgr; - DCTSourceMgr sourceMgr; - GBool error; - char *lineBuf; - int lineBufHeight; - char *lineBufRows[4]; - char *bufPtr; - char *bufEnd; - GBool inlineImage; + int colorXform; // color transform: -1 = unspecified + // 0 = none + // 1 = YUV/YUVK -> RGB/CMYK + jpeg_decompress_struct decomp; + DCTErrorMgr errorMgr; + DCTSourceMgr sourceMgr; + GBool error; + char *lineBuf; + int lineBufHeight; + char *lineBufRows[4]; + char *bufPtr; + char *bufEnd; + GBool inlineImage; - GBool fillBuf(); - static void errorExit(j_common_ptr d); - static void errorMessage(j_common_ptr d); - static void initSourceCbk(j_decompress_ptr d); - static boolean fillInputBufferCbk(j_decompress_ptr d); - static void skipInputDataCbk(j_decompress_ptr d, long numBytes); - static void termSourceCbk(j_decompress_ptr d); + GBool fillBuf(); + static void errorExit(j_common_ptr d); + static void errorMessage(j_common_ptr d); + static void initSourceCbk(j_decompress_ptr d); + static boolean fillInputBufferCbk(j_decompress_ptr d); + static void skipInputDataCbk(j_decompress_ptr d, long numBytes); + static void termSourceCbk(j_decompress_ptr d); #else // HAVE_JPEGLIB - GBool progressive; // set if in progressive mode - GBool interleaved; // set if in interleaved mode - int width, height; // image size - int mcuWidth, mcuHeight; // size of min coding unit, in data units - int bufWidth, bufHeight; // frameBuf size - DCTCompInfo compInfo[4]; // info for each component - DCTScanInfo scanInfo; // info for the current scan - int numComps; // number of components in image - int colorXform; // color transform: -1 = unspecified - // 0 = none - // 1 = YUV/YUVK -> RGB/CMYK - GBool gotJFIFMarker; // set if APP0 JFIF marker was present - GBool gotAdobeMarker; // set if APP14 Adobe marker was present - int restartInterval; // restart interval, in MCUs - Gushort quantTables[4][64]; // quantization tables - int numQuantTables; // number of quantization tables - DCTHuffTable dcHuffTables[4]; // DC Huffman tables - DCTHuffTable acHuffTables[4]; // AC Huffman tables - int numDCHuffTables; // number of DC Huffman tables - int numACHuffTables; // number of AC Huffman tables - Guchar *rowBuf; - Guchar *rowBufPtr; // current position within rowBuf - Guchar *rowBufEnd; // end of valid data in rowBuf - int *frameBuf[4]; // buffer for frame (progressive mode) - int comp, x, y; // current position within image/MCU - int restartCtr; // MCUs left until restart - int restartMarker; // next restart marker - int eobRun; // number of EOBs left in the current run - int inputBuf; // input buffer for variable length codes - int inputBits; // number of valid bits in input buffer + GBool progressive; // set if in progressive mode + GBool interleaved; // set if in interleaved mode + int width, height; // image size + int mcuWidth, mcuHeight; // size of min coding unit, in data units + int bufWidth, bufHeight; // frameBuf size + DCTCompInfo compInfo[4]; // info for each component + DCTScanInfo scanInfo; // info for the current scan + int numComps; // number of components in image + int colorXform; // color transform: -1 = unspecified + // 0 = none + // 1 = YUV/YUVK -> RGB/CMYK + GBool gotJFIFMarker; // set if APP0 JFIF marker was present + GBool gotAdobeMarker; // set if APP14 Adobe marker was present + int restartInterval; // restart interval, in MCUs + Gushort quantTables[4][64]; // quantization tables + int numQuantTables; // number of quantization tables + DCTHuffTable dcHuffTables[4]; // DC Huffman tables + DCTHuffTable acHuffTables[4]; // AC Huffman tables + int numDCHuffTables; // number of DC Huffman tables + int numACHuffTables; // number of AC Huffman tables + Guchar *rowBuf; + Guchar *rowBufPtr; // current position within rowBuf + Guchar *rowBufEnd; // end of valid data in rowBuf + int *frameBuf[4]; // buffer for frame (progressive mode) + int comp, x, y; // current position within image/MCU + int restartCtr; // MCUs left until restart + int restartMarker; // next restart marker + int eobRun; // number of EOBs left in the current run + int inputBuf; // input buffer for variable length codes + int inputBits; // number of valid bits in input buffer - void restart(); - GBool readMCURow(); - void readScan(); - GBool readDataUnit(DCTHuffTable *dcHuffTable, - DCTHuffTable *acHuffTable, - int *prevDC, int data[64]); - GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, - DCTHuffTable *acHuffTable, - int *prevDC, int data[64]); - void decodeImage(); - void transformDataUnit(Gushort *quantTable, - int dataIn[64], Guchar dataOut[64]); - int readHuffSym(DCTHuffTable *table); - int readAmp(int size); - int readBit(); - GBool readHeader(GBool frame); - GBool readBaselineSOF(); - GBool readProgressiveSOF(); - GBool readScanInfo(); - GBool readQuantTables(); - GBool readHuffmanTables(); - GBool readRestartInterval(); - GBool readJFIFMarker(); - GBool readAdobeMarker(); - GBool readTrailer(); - int readMarker(); - int read16(); + void restart(); + GBool readMCURow(); + void readScan(); + GBool readDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]); + GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]); + void decodeImage(); + void transformDataUnit(Gushort *quantTable, + int dataIn[64], Guchar dataOut[64]); + int readHuffSym(DCTHuffTable *table); + int readAmp(int size); + int readBit(); + GBool readHeader(GBool frame); + GBool readBaselineSOF(); + GBool readProgressiveSOF(); + GBool readScanInfo(); + GBool readQuantTables(); + GBool readHuffmanTables(); + GBool readRestartInterval(); + GBool readJFIFMarker(); + GBool readAdobeMarker(); + GBool readTrailer(); + int readMarker(); + int read16(); #endif // HAVE_JPEGLIB }; @@ -757,239 +843,299 @@ private: // Huffman code table entry struct FlateCode { - Gushort len; // code length, in bits - Gushort val; // value represented by this code + Gushort len; // code length, in bits + Gushort val; // value represented by this code }; struct FlateHuffmanTab { - FlateCode *codes; - int maxLen; + FlateCode *codes; + int maxLen; }; // Decoding info for length and distance code words struct FlateDecode { - int bits; // # extra bits - int first; // first length/distance + int bits; // # extra bits + int first; // first length/distance }; -class FlateStream: public FilterStream { +class FlateStream : public FilterStream { public: - FlateStream(Stream *strA, int predictor, int columns, - int colors, int bits); - virtual ~FlateStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strFlate; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getRawChar(); - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + FlateStream(Stream *strA, int predictor, int columns, + int colors, int bits); + virtual ~FlateStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strFlate; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - StreamPredictor *pred; // predictor - Guchar buf[flateWindow]; // output data buffer - int index; // current index into output buffer - int remain; // number valid bytes in output buffer - int codeBuf; // input buffer - int codeSize; // number of bits in input buffer - int // literal and distance code lengths - codeLengths[flateMaxLitCodes + flateMaxDistCodes]; - FlateHuffmanTab litCodeTab; // literal code table - FlateHuffmanTab distCodeTab; // distance code table - GBool compressedBlock; // set if reading a compressed block - int blockLen; // remaining length of uncompressed block - GBool endOfBlock; // set when end of block is reached - GBool eof; // set when end of stream is reached + StreamPredictor *pred; // predictor + Guchar buf[flateWindow]; // output data buffer + int index; // current index into output buffer + int remain; // number valid bytes in output buffer + int codeBuf; // input buffer + int codeSize; // number of bits in input buffer + int // literal and distance code lengths + codeLengths[flateMaxLitCodes + flateMaxDistCodes]; + FlateHuffmanTab litCodeTab; // literal code table + FlateHuffmanTab distCodeTab; // distance code table + GBool compressedBlock; // set if reading a compressed block + int blockLen; // remaining length of uncompressed block + GBool endOfBlock; // set when end of block is reached + GBool eof; // set when end of stream is reached - static int // code length code reordering - codeLenCodeMap[flateMaxCodeLenCodes]; - static FlateDecode // length decoding info - lengthDecode[flateMaxLitCodes-257]; - static FlateDecode // distance decoding info - distDecode[flateMaxDistCodes]; - static FlateHuffmanTab // fixed literal code table - fixedLitCodeTab; - static FlateHuffmanTab // fixed distance code table - fixedDistCodeTab; + static int // code length code reordering + codeLenCodeMap[flateMaxCodeLenCodes]; + static FlateDecode // length decoding info + lengthDecode[flateMaxLitCodes-257]; + static FlateDecode // distance decoding info + distDecode[flateMaxDistCodes]; + static FlateHuffmanTab // fixed literal code table + fixedLitCodeTab; + static FlateHuffmanTab // fixed distance code table + fixedDistCodeTab; - void readSome(); - GBool startBlock(); - void loadFixedCodes(); - GBool readDynamicCodes(); - void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); - int getHuffmanCodeWord(FlateHuffmanTab *tab); - int getCodeWord(int bits); + void readSome(); + GBool startBlock(); + void loadFixedCodes(); + GBool readDynamicCodes(); + void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); + int getHuffmanCodeWord(FlateHuffmanTab *tab); + int getCodeWord(int bits); }; //------------------------------------------------------------------------ // EOFStream //------------------------------------------------------------------------ -class EOFStream: public FilterStream { +class EOFStream : public FilterStream { public: - EOFStream(Stream *strA); - virtual ~EOFStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset() {} - virtual int getChar() { return EOF; } - virtual int lookChar() { return EOF; } - virtual int getBlock(char *blk, int size) { return 0; } - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + EOFStream(Stream *strA); + virtual ~EOFStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset() {} + virtual int getChar() { + return EOF; + } + virtual int lookChar() { + return EOF; + } + virtual int getBlock(char *blk, int size) { + return 0; + } + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gFalse; + } }; //------------------------------------------------------------------------ // BufStream //------------------------------------------------------------------------ -class BufStream: public FilterStream { +class BufStream : public FilterStream { public: - BufStream(Stream *strA, int bufSizeA); - virtual ~BufStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue); + BufStream(Stream *strA, int bufSizeA); + virtual ~BufStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue); - int lookChar(int idx); + int lookChar(int idx); private: - int *buf; - int bufSize; + int *buf; + int bufSize; }; //------------------------------------------------------------------------ // FixedLengthEncoder //------------------------------------------------------------------------ -class FixedLengthEncoder: public FilterStream { +class FixedLengthEncoder : public FilterStream { public: - FixedLengthEncoder(Stream *strA, int lengthA); - ~FixedLengthEncoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue); - virtual GBool isEncoder() { return gTrue; } + FixedLengthEncoder(Stream *strA, int lengthA); + ~FixedLengthEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue); + virtual GBool isEncoder() { + return gTrue; + } private: - int length; - int count; + int length; + int count; }; //------------------------------------------------------------------------ // ASCIIHexEncoder //------------------------------------------------------------------------ -class ASCIIHexEncoder: public FilterStream { +class ASCIIHexEncoder : public FilterStream { public: - ASCIIHexEncoder(Stream *strA); - virtual ~ASCIIHexEncoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } - virtual GBool isEncoder() { return gTrue; } + ASCIIHexEncoder(Stream *strA); + virtual ~ASCIIHexEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gFalse; + } + virtual GBool isEncoder() { + return gTrue; + } private: - char buf[4]; - char *bufPtr; - char *bufEnd; - int lineLen; - GBool eof; + char buf[4]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; - GBool fillBuf(); + GBool fillBuf(); }; //------------------------------------------------------------------------ // ASCII85Encoder //------------------------------------------------------------------------ -class ASCII85Encoder: public FilterStream { +class ASCII85Encoder : public FilterStream { public: - ASCII85Encoder(Stream *strA); - virtual ~ASCII85Encoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } - virtual GBool isEncoder() { return gTrue; } + ASCII85Encoder(Stream *strA); + virtual ~ASCII85Encoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gFalse; + } + virtual GBool isEncoder() { + return gTrue; + } private: - char buf[8]; - char *bufPtr; - char *bufEnd; - int lineLen; - GBool eof; + char buf[8]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; - GBool fillBuf(); + GBool fillBuf(); }; //------------------------------------------------------------------------ // RunLengthEncoder //------------------------------------------------------------------------ -class RunLengthEncoder: public FilterStream { +class RunLengthEncoder : public FilterStream { public: - RunLengthEncoder(Stream *strA); - virtual ~RunLengthEncoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gTrue; } - virtual GBool isEncoder() { return gTrue; } + RunLengthEncoder(Stream *strA); + virtual ~RunLengthEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gTrue; + } + virtual GBool isEncoder() { + return gTrue; + } private: - char buf[131]; - char *bufPtr; - char *bufEnd; - char *nextEnd; - GBool eof; + char buf[131]; + char *bufPtr; + char *bufEnd; + char *nextEnd; + GBool eof; - GBool fillBuf(); + GBool fillBuf(); }; //------------------------------------------------------------------------ @@ -997,39 +1143,47 @@ private: //------------------------------------------------------------------------ struct LZWEncoderNode { - int byte; - LZWEncoderNode *next; // next sibling - LZWEncoderNode *children; // first child + int byte; + LZWEncoderNode *next; // next sibling + LZWEncoderNode *children; // first child }; -class LZWEncoder: public FilterStream { +class LZWEncoder : public FilterStream { public: - LZWEncoder(Stream *strA); - virtual ~LZWEncoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gTrue; } - virtual GBool isEncoder() { return gTrue; } + LZWEncoder(Stream *strA); + virtual ~LZWEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gTrue; + } + virtual GBool isEncoder() { + return gTrue; + } private: - LZWEncoderNode table[4096]; - int nextSeq; - int codeLen; - Guchar inBuf[8192]; - int inBufStart; - int inBufLen; - int outBuf; - int outBufLen; - GBool needEOD; + LZWEncoderNode table[4096]; + int nextSeq; + int codeLen; + Guchar inBuf[8192]; + int inBufStart; + int inBufLen; + int outBuf; + int outBufLen; + GBool needEOD; - void fillBuf(); + void fillBuf(); }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-10023/Function.h b/test/bug-hunting/cve/CVE-2019-10023/Function.h index 5cf45169a..615c2abfd 100644 --- a/test/bug-hunting/cve/CVE-2019-10023/Function.h +++ b/test/bug-hunting/cve/CVE-2019-10023/Function.h @@ -34,64 +34,84 @@ struct PSCode; class Function { public: - Function(); + Function(); - virtual ~Function(); + virtual ~Function(); - // Construct a function. Returns NULL if unsuccessful. - static Function *parse(Object *funcObj, int recursion = 0); + // Construct a function. Returns NULL if unsuccessful. + static Function *parse(Object *funcObj, int recursion = 0); - // Initialize the entries common to all function types. - GBool init(Dict *dict); + // Initialize the entries common to all function types. + GBool init(Dict *dict); - virtual Function *copy() = 0; + virtual Function *copy() = 0; - // Return the function type: - // -1 : identity - // 0 : sampled - // 2 : exponential - // 3 : stitching - // 4 : PostScript - virtual int getType() = 0; + // Return the function type: + // -1 : identity + // 0 : sampled + // 2 : exponential + // 3 : stitching + // 4 : PostScript + virtual int getType() = 0; - // Return size of input and output tuples. - int getInputSize() { return m; } - int getOutputSize() { return n; } + // Return size of input and output tuples. + int getInputSize() { + return m; + } + int getOutputSize() { + return n; + } - double getDomainMin(int i) { return domain[i][0]; } - double getDomainMax(int i) { return domain[i][1]; } - double getRangeMin(int i) { return range[i][0]; } - double getRangeMax(int i) { return range[i][1]; } - GBool getHasRange() { return hasRange; } + double getDomainMin(int i) { + return domain[i][0]; + } + double getDomainMax(int i) { + return domain[i][1]; + } + double getRangeMin(int i) { + return range[i][0]; + } + double getRangeMax(int i) { + return range[i][1]; + } + GBool getHasRange() { + return hasRange; + } - // Transform an input tuple into an output tuple. - virtual void transform(double *in, double *out) = 0; + // Transform an input tuple into an output tuple. + virtual void transform(double *in, double *out) = 0; - virtual GBool isOk() = 0; + virtual GBool isOk() = 0; protected: - int m, n; // size of input and output tuples - double // min and max values for function domain - domain[funcMaxInputs][2]; - double // min and max values for function range - range[funcMaxOutputs][2]; - GBool hasRange; // set if range is defined + int m, n; // size of input and output tuples + double // min and max values for function domain + domain[funcMaxInputs][2]; + double // min and max values for function range + range[funcMaxOutputs][2]; + GBool hasRange; // set if range is defined }; //------------------------------------------------------------------------ // IdentityFunction //------------------------------------------------------------------------ -class IdentityFunction: public Function { +class IdentityFunction : public Function { public: - IdentityFunction(); - virtual ~IdentityFunction(); - virtual Function *copy() { return new IdentityFunction(); } - virtual int getType() { return -1; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return gTrue; } + IdentityFunction(); + virtual ~IdentityFunction(); + virtual Function *copy() { + return new IdentityFunction(); + } + virtual int getType() { + return -1; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return gTrue; + } private: }; @@ -100,137 +120,191 @@ private: // SampledFunction //------------------------------------------------------------------------ -class SampledFunction: public Function { +class SampledFunction : public Function { public: - SampledFunction(Object *funcObj, Dict *dict); - virtual ~SampledFunction(); - virtual Function *copy() { return new SampledFunction(this); } - virtual int getType() { return 0; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + SampledFunction(Object *funcObj, Dict *dict); + virtual ~SampledFunction(); + virtual Function *copy() { + return new SampledFunction(this); + } + virtual int getType() { + return 0; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - int getSampleSize(int i) { return sampleSize[i]; } - double getEncodeMin(int i) { return encode[i][0]; } - double getEncodeMax(int i) { return encode[i][1]; } - double getDecodeMin(int i) { return decode[i][0]; } - double getDecodeMax(int i) { return decode[i][1]; } - double *getSamples() { return samples; } + int getSampleSize(int i) { + return sampleSize[i]; + } + double getEncodeMin(int i) { + return encode[i][0]; + } + double getEncodeMax(int i) { + return encode[i][1]; + } + double getDecodeMin(int i) { + return decode[i][0]; + } + double getDecodeMax(int i) { + return decode[i][1]; + } + double *getSamples() { + return samples; + } private: - SampledFunction(SampledFunction *func); + SampledFunction(SampledFunction *func); - int // number of samples for each domain element - sampleSize[funcMaxInputs]; - double // min and max values for domain encoder - encode[funcMaxInputs][2]; - double // min and max values for range decoder - decode[funcMaxOutputs][2]; - double // input multipliers - inputMul[funcMaxInputs]; - int *idxOffset; - double *samples; // the samples - int nSamples; // size of the samples array - double *sBuf; // buffer for the transform function - double cacheIn[funcMaxInputs]; - double cacheOut[funcMaxOutputs]; - GBool ok; + int // number of samples for each domain element + sampleSize[funcMaxInputs]; + double // min and max values for domain encoder + encode[funcMaxInputs][2]; + double // min and max values for range decoder + decode[funcMaxOutputs][2]; + double // input multipliers + inputMul[funcMaxInputs]; + int *idxOffset; + double *samples; // the samples + int nSamples; // size of the samples array + double *sBuf; // buffer for the transform function + double cacheIn[funcMaxInputs]; + double cacheOut[funcMaxOutputs]; + GBool ok; }; //------------------------------------------------------------------------ // ExponentialFunction //------------------------------------------------------------------------ -class ExponentialFunction: public Function { +class ExponentialFunction : public Function { public: - ExponentialFunction(Object *funcObj, Dict *dict); - virtual ~ExponentialFunction(); - virtual Function *copy() { return new ExponentialFunction(this); } - virtual int getType() { return 2; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + ExponentialFunction(Object *funcObj, Dict *dict); + virtual ~ExponentialFunction(); + virtual Function *copy() { + return new ExponentialFunction(this); + } + virtual int getType() { + return 2; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - double *getC0() { return c0; } - double *getC1() { return c1; } - double getE() { return e; } + double *getC0() { + return c0; + } + double *getC1() { + return c1; + } + double getE() { + return e; + } private: - ExponentialFunction(ExponentialFunction *func); + ExponentialFunction(ExponentialFunction *func); - double c0[funcMaxOutputs]; - double c1[funcMaxOutputs]; - double e; - GBool ok; + double c0[funcMaxOutputs]; + double c1[funcMaxOutputs]; + double e; + GBool ok; }; //------------------------------------------------------------------------ // StitchingFunction //------------------------------------------------------------------------ -class StitchingFunction: public Function { +class StitchingFunction : public Function { public: - StitchingFunction(Object *funcObj, Dict *dict, int recursion); - virtual ~StitchingFunction(); - virtual Function *copy() { return new StitchingFunction(this); } - virtual int getType() { return 3; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + StitchingFunction(Object *funcObj, Dict *dict, int recursion); + virtual ~StitchingFunction(); + virtual Function *copy() { + return new StitchingFunction(this); + } + virtual int getType() { + return 3; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - int getNumFuncs() { return k; } - Function *getFunc(int i) { return funcs[i]; } - double *getBounds() { return bounds; } - double *getEncode() { return encode; } - double *getScale() { return scale; } + int getNumFuncs() { + return k; + } + Function *getFunc(int i) { + return funcs[i]; + } + double *getBounds() { + return bounds; + } + double *getEncode() { + return encode; + } + double *getScale() { + return scale; + } private: - StitchingFunction(StitchingFunction *func); + StitchingFunction(StitchingFunction *func); - int k; - Function **funcs; - double *bounds; - double *encode; - double *scale; - GBool ok; + int k; + Function **funcs; + double *bounds; + double *encode; + double *scale; + GBool ok; }; //------------------------------------------------------------------------ // PostScriptFunction //------------------------------------------------------------------------ -class PostScriptFunction: public Function { +class PostScriptFunction : public Function { public: - PostScriptFunction(Object *funcObj, Dict *dict); - virtual ~PostScriptFunction(); - virtual Function *copy() { return new PostScriptFunction(this); } - virtual int getType() { return 4; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + PostScriptFunction(Object *funcObj, Dict *dict); + virtual ~PostScriptFunction(); + virtual Function *copy() { + return new PostScriptFunction(this); + } + virtual int getType() { + return 4; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - GString *getCodeString() { return codeString; } + GString *getCodeString() { + return codeString; + } private: - PostScriptFunction(PostScriptFunction *func); - GBool parseCode(GList *tokens, int *tokPtr, int *codePtr); - void addCode(int *codePtr, int op); - void addCodeI(int *codePtr, int op, int x); - void addCodeD(int *codePtr, int op, double x); - GString *getToken(Stream *str); - int exec(double *stack, int sp0); + PostScriptFunction(PostScriptFunction *func); + GBool parseCode(GList *tokens, int *tokPtr, int *codePtr); + void addCode(int *codePtr, int op); + void addCodeI(int *codePtr, int op, int x); + void addCodeD(int *codePtr, int op, double x); + GString *getToken(Stream *str); + int exec(double *stack, int sp0); - GString *codeString; - PSCode *code; - int codeLen; - int codeSize; - double cacheIn[funcMaxInputs]; - double cacheOut[funcMaxOutputs]; - GBool ok; + GString *codeString; + PSCode *code; + int codeLen; + int codeSize; + double cacheIn[funcMaxInputs]; + double cacheOut[funcMaxOutputs]; + GBool ok; }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-10024/Splash.h b/test/bug-hunting/cve/CVE-2019-10024/Splash.h index 423ed3605..dc6675121 100644 --- a/test/bug-hunting/cve/CVE-2019-10024/Splash.h +++ b/test/bug-hunting/cve/CVE-2019-10024/Splash.h @@ -40,27 +40,27 @@ typedef GBool (*SplashImageMaskSource)(void *data, Guchar *pixel); // * and returns true. If the image stream is exhausted, // returns false. typedef GBool (*SplashImageSource)(void *data, SplashColorPtr colorLine, - Guchar *alphaLine); + Guchar *alphaLine); //------------------------------------------------------------------------ enum SplashPipeResultColorCtrl { - splashPipeResultColorNoAlphaBlendMono, - splashPipeResultColorNoAlphaBlendRGB, + splashPipeResultColorNoAlphaBlendMono, + splashPipeResultColorNoAlphaBlendRGB, #if SPLASH_CMYK - splashPipeResultColorNoAlphaBlendCMYK, + splashPipeResultColorNoAlphaBlendCMYK, #endif - splashPipeResultColorAlphaNoBlendMono, - splashPipeResultColorAlphaNoBlendRGB, + splashPipeResultColorAlphaNoBlendMono, + splashPipeResultColorAlphaNoBlendRGB, #if SPLASH_CMYK - splashPipeResultColorAlphaNoBlendCMYK, + splashPipeResultColorAlphaNoBlendCMYK, #endif - splashPipeResultColorAlphaBlendMono, - splashPipeResultColorAlphaBlendRGB + splashPipeResultColorAlphaBlendMono, + splashPipeResultColorAlphaBlendRGB #if SPLASH_CMYK - , - splashPipeResultColorAlphaBlendCMYK + , + splashPipeResultColorAlphaBlendCMYK #endif }; @@ -71,367 +71,379 @@ enum SplashPipeResultColorCtrl { class Splash { public: - // Create a new rasterizer object. - Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, - SplashScreenParams *screenParams = NULL); - Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, - SplashScreen *screenA); + // Create a new rasterizer object. + Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, + SplashScreenParams *screenParams = NULL); + Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA, + SplashScreen *screenA); - ~Splash(); + ~Splash(); - //----- state read + //----- state read - SplashCoord *getMatrix(); - SplashPattern *getStrokePattern(); - SplashPattern *getFillPattern(); - SplashScreen *getScreen(); - SplashBlendFunc getBlendFunc(); - SplashCoord getStrokeAlpha(); - SplashCoord getFillAlpha(); - SplashCoord getLineWidth(); - int getLineCap(); - int getLineJoin(); - SplashCoord getMiterLimit(); - SplashCoord getFlatness(); - SplashCoord *getLineDash(); - int getLineDashLength(); - SplashCoord getLineDashPhase(); - SplashStrokeAdjustMode getStrokeAdjust(); - SplashClip *getClip(); - SplashBitmap *getSoftMask(); - GBool getInNonIsolatedGroup(); - GBool getInKnockoutGroup(); + SplashCoord *getMatrix(); + SplashPattern *getStrokePattern(); + SplashPattern *getFillPattern(); + SplashScreen *getScreen(); + SplashBlendFunc getBlendFunc(); + SplashCoord getStrokeAlpha(); + SplashCoord getFillAlpha(); + SplashCoord getLineWidth(); + int getLineCap(); + int getLineJoin(); + SplashCoord getMiterLimit(); + SplashCoord getFlatness(); + SplashCoord *getLineDash(); + int getLineDashLength(); + SplashCoord getLineDashPhase(); + SplashStrokeAdjustMode getStrokeAdjust(); + SplashClip *getClip(); + SplashBitmap *getSoftMask(); + GBool getInNonIsolatedGroup(); + GBool getInKnockoutGroup(); - //----- state write + //----- state write - void setMatrix(SplashCoord *matrix); - void setStrokePattern(SplashPattern *strokeColor); - void setFillPattern(SplashPattern *fillColor); - void setScreen(SplashScreen *screen); - void setBlendFunc(SplashBlendFunc func); - void setStrokeAlpha(SplashCoord alpha); - void setFillAlpha(SplashCoord alpha); - void setLineWidth(SplashCoord lineWidth); - void setLineCap(int lineCap); - void setLineJoin(int lineJoin); - void setMiterLimit(SplashCoord miterLimit); - void setFlatness(SplashCoord flatness); - // the array will be copied - void setLineDash(SplashCoord *lineDash, int lineDashLength, - SplashCoord lineDashPhase); - void setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust); - // NB: uses transformed coordinates. - void clipResetToRect(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1); - // NB: uses transformed coordinates. - SplashError clipToRect(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1); - // NB: uses untransformed coordinates. - SplashError clipToPath(SplashPath *path, GBool eo); - void setSoftMask(SplashBitmap *softMask); - void setInTransparencyGroup(SplashBitmap *groupBackBitmapA, - int groupBackXA, int groupBackYA, - GBool nonIsolated, GBool knockout); - void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray); - void setOverprintMask(Guint overprintMask); - void setEnablePathSimplification(GBool en); + void setMatrix(SplashCoord *matrix); + void setStrokePattern(SplashPattern *strokeColor); + void setFillPattern(SplashPattern *fillColor); + void setScreen(SplashScreen *screen); + void setBlendFunc(SplashBlendFunc func); + void setStrokeAlpha(SplashCoord alpha); + void setFillAlpha(SplashCoord alpha); + void setLineWidth(SplashCoord lineWidth); + void setLineCap(int lineCap); + void setLineJoin(int lineJoin); + void setMiterLimit(SplashCoord miterLimit); + void setFlatness(SplashCoord flatness); + // the array will be copied + void setLineDash(SplashCoord *lineDash, int lineDashLength, + SplashCoord lineDashPhase); + void setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust); + // NB: uses transformed coordinates. + void clipResetToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + // NB: uses transformed coordinates. + SplashError clipToRect(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1); + // NB: uses untransformed coordinates. + SplashError clipToPath(SplashPath *path, GBool eo); + void setSoftMask(SplashBitmap *softMask); + void setInTransparencyGroup(SplashBitmap *groupBackBitmapA, + int groupBackXA, int groupBackYA, + GBool nonIsolated, GBool knockout); + void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray); + void setOverprintMask(Guint overprintMask); + void setEnablePathSimplification(GBool en); - //----- state save/restore + //----- state save/restore - void saveState(); - SplashError restoreState(); + void saveState(); + SplashError restoreState(); - //----- drawing operations + //----- drawing operations - // Fill the bitmap with . This is not subject to clipping. - void clear(SplashColorPtr color, Guchar alpha = 0x00); + // Fill the bitmap with . This is not subject to clipping. + void clear(SplashColorPtr color, Guchar alpha = 0x00); - // Stroke a path using the current stroke pattern. - SplashError stroke(SplashPath *path); + // Stroke a path using the current stroke pattern. + SplashError stroke(SplashPath *path); - // Fill a path using the current fill pattern. - SplashError fill(SplashPath *path, GBool eo); + // Fill a path using the current fill pattern. + SplashError fill(SplashPath *path, GBool eo); - // Draw a character, using the current fill pattern. - SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font); + // Draw a character, using the current fill pattern. + SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font); - // Draw a glyph, using the current fill pattern. This function does - // not free any data, i.e., it ignores glyph->freeData. - SplashError fillGlyph(SplashCoord x, SplashCoord y, - SplashGlyphBitmap *glyph); + // Draw a glyph, using the current fill pattern. This function does + // not free any data, i.e., it ignores glyph->freeData. + SplashError fillGlyph(SplashCoord x, SplashCoord y, + SplashGlyphBitmap *glyph); - // Draws an image mask using the fill color. This will read - // lines of pixels from , starting with the top line. "1" - // pixels will be drawn with the current fill color; "0" pixels are - // transparent. The matrix: - // [ mat[0] mat[1] 0 ] - // [ mat[2] mat[3] 0 ] - // [ mat[4] mat[5] 1 ] - // maps a unit square to the desired destination for the image, in - // PostScript style: - // [x' y' 1] = [x y 1] * mat - // Note that the Splash y axis points downward, and the image source - // is assumed to produce pixels in raster order, starting from the - // top line. - SplashError fillImageMask(SplashImageMaskSource src, void *srcData, - int w, int h, SplashCoord *mat, - GBool glyphMode, GBool interpolate); + // Draws an image mask using the fill color. This will read + // lines of pixels from , starting with the top line. "1" + // pixels will be drawn with the current fill color; "0" pixels are + // transparent. The matrix: + // [ mat[0] mat[1] 0 ] + // [ mat[2] mat[3] 0 ] + // [ mat[4] mat[5] 1 ] + // maps a unit square to the desired destination for the image, in + // PostScript style: + // [x' y' 1] = [x y 1] * mat + // Note that the Splash y axis points downward, and the image source + // is assumed to produce pixels in raster order, starting from the + // top line. + SplashError fillImageMask(SplashImageMaskSource src, void *srcData, + int w, int h, SplashCoord *mat, + GBool glyphMode, GBool interpolate); - // Draw an image. This will read lines of pixels from - // , starting with the top line. These pixels are assumed to - // be in the source mode, . If is true, the - // alpha values returned by are used; otherwise they are - // ignored. The following combinations of source and target modes - // are supported: - // source target - // ------ ------ - // Mono8 Mono1 -- with dithering - // Mono8 Mono8 - // RGB8 RGB8 - // BGR8 RGB8 - // CMYK8 CMYK8 - // The matrix behaves as for fillImageMask. - SplashError drawImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, GBool srcAlpha, - int w, int h, SplashCoord *mat, - GBool interpolate); + // Draw an image. This will read lines of pixels from + // , starting with the top line. These pixels are assumed to + // be in the source mode, . If is true, the + // alpha values returned by are used; otherwise they are + // ignored. The following combinations of source and target modes + // are supported: + // source target + // ------ ------ + // Mono8 Mono1 -- with dithering + // Mono8 Mono8 + // RGB8 RGB8 + // BGR8 RGB8 + // CMYK8 CMYK8 + // The matrix behaves as for fillImageMask. + SplashError drawImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, GBool srcAlpha, + int w, int h, SplashCoord *mat, + GBool interpolate); - // Composite a rectangular region from onto this Splash - // object. - SplashError composite(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h, - GBool noClip, GBool nonIsolated); + // Composite a rectangular region from onto this Splash + // object. + SplashError composite(SplashBitmap *src, int xSrc, int ySrc, + int xDest, int yDest, int w, int h, + GBool noClip, GBool nonIsolated); - // Composite this Splash object onto a background color. The - // background alpha is assumed to be 1. - void compositeBackground(SplashColorPtr color); + // Composite this Splash object onto a background color. The + // background alpha is assumed to be 1. + void compositeBackground(SplashColorPtr color); - // Copy a rectangular region from onto the bitmap belonging to - // this Splash object. The destination alpha values are all set to - // zero. - SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h); + // Copy a rectangular region from onto the bitmap belonging to + // this Splash object. The destination alpha values are all set to + // zero. + SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc, + int xDest, int yDest, int w, int h); - // Copy a rectangular region from the bitmap belonging to this - // Splash object to . The alpha values are corrected for a - // non-isolated group. - SplashError blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc, - int xDest, int yDest, int w, int h); + // Copy a rectangular region from the bitmap belonging to this + // Splash object to . The alpha values are corrected for a + // non-isolated group. + SplashError blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc, + int xDest, int yDest, int w, int h); - //----- misc + //----- misc - // Construct a path for a stroke, given the path to be stroked and - // the line width . All other stroke parameters are taken from - // the current state. If is true, this function will - // first flatten the path and handle the linedash. - SplashPath *makeStrokePath(SplashPath *path, SplashCoord w, - int lineCap, int lineJoin, - GBool flatten = gTrue); + // Construct a path for a stroke, given the path to be stroked and + // the line width . All other stroke parameters are taken from + // the current state. If is true, this function will + // first flatten the path and handle the linedash. + SplashPath *makeStrokePath(SplashPath *path, SplashCoord w, + int lineCap, int lineJoin, + GBool flatten = gTrue); - // Reduce the size of a rectangle as much as possible by moving any - // edges that are completely outside the clip region. Returns the - // clipping status of the resulting rectangle. - SplashClipResult limitRectToClipRect(int *xMin, int *yMin, - int *xMax, int *yMax); + // Reduce the size of a rectangle as much as possible by moving any + // edges that are completely outside the clip region. Returns the + // clipping status of the resulting rectangle. + SplashClipResult limitRectToClipRect(int *xMin, int *yMin, + int *xMax, int *yMax); - // Return the associated bitmap. - SplashBitmap *getBitmap() { return bitmap; } + // Return the associated bitmap. + SplashBitmap *getBitmap() { + return bitmap; + } - // Set the minimum line width. - void setMinLineWidth(SplashCoord w) { minLineWidth = w; } + // Set the minimum line width. + void setMinLineWidth(SplashCoord w) { + minLineWidth = w; + } - // Get a bounding box which includes all modifications since the - // last call to clearModRegion. - void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax) - { *xMin = modXMin; *yMin = modYMin; *xMax = modXMax; *yMax = modYMax; } + // Get a bounding box which includes all modifications since the + // last call to clearModRegion. + void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax) + { + *xMin = modXMin; *yMin = modYMin; *xMax = modXMax; *yMax = modYMax; + } - // Clear the modified region bounding box. - void clearModRegion(); + // Clear the modified region bounding box. + void clearModRegion(); - // Get clipping status for the last drawing operation subject to - // clipping. - SplashClipResult getClipRes() { return opClipRes; } + // Get clipping status for the last drawing operation subject to + // clipping. + SplashClipResult getClipRes() { + return opClipRes; + } - // Toggle debug mode on or off. - void setDebugMode(GBool debugModeA) { debugMode = debugModeA; } + // Toggle debug mode on or off. + void setDebugMode(GBool debugModeA) { + debugMode = debugModeA; + } #if 1 //~tmp: turn off anti-aliasing temporarily - void setInShading(GBool sh) { inShading = sh; } + void setInShading(GBool sh) { + inShading = sh; + } #endif private: - void pipeInit(SplashPipe *pipe, SplashPattern *pattern, - Guchar aInput, GBool usesShape, - GBool nonIsolatedGroup); - void pipeRun(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeInit(SplashPipe *pipe, SplashPattern *pattern, + Guchar aInput, GBool usesShape, + GBool nonIsolatedGroup); + void pipeRun(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleRGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleBGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #if SPLASH_CMYK - void pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #endif - void pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #if SPLASH_CMYK - void pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #endif - void pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); - void pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #if SPLASH_CMYK - void pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, - Guchar *shapePtr, SplashColorPtr cSrcPtr); + void pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y, + Guchar *shapePtr, SplashColorPtr cSrcPtr); #endif - void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, - SplashCoord *xo, SplashCoord *yo); - void updateModX(int x); - void updateModY(int y); - void strokeNarrow(SplashPath *path); - void drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip); - void strokeWide(SplashPath *path, SplashCoord w, - int lineCap, int lineJoin); - SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix, - SplashCoord flatness); - void flattenCurve(SplashCoord x0, SplashCoord y0, - SplashCoord x1, SplashCoord y1, - SplashCoord x2, SplashCoord y2, - SplashCoord x3, SplashCoord y3, - SplashCoord *matrix, SplashCoord flatness2, - SplashPath *fPath); - SplashPath *makeDashedPath(SplashPath *xPath); - SplashError fillWithPattern(SplashPath *path, GBool eo, - SplashPattern *pattern, SplashCoord alpha); - SplashPath *tweakFillPath(SplashPath *path); - GBool pathAllOutside(SplashPath *path); - SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph); - void getImageBounds(SplashCoord xyMin, SplashCoord xyMax, - int *xyMinI, int *xyMaxI); - void upscaleMask(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - SplashCoord *mat, GBool glyphMode, - GBool interpolate); - void arbitraryTransformMask(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - SplashCoord *mat, GBool glyphMode, - GBool interpolate); - SplashBitmap *scaleMask(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - GBool interpolate); - void scaleMaskYdXd(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleMaskYdXu(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleMaskYuXd(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleMaskYuXu(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleMaskYuXuI(SplashImageMaskSource src, void *srcData, - int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void blitMask(SplashBitmap *src, int xDest, int yDest, - SplashClipResult clipRes); - void upscaleImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - SplashCoord *mat, GBool interpolate); - void arbitraryTransformImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, - int srcWidth, int srcHeight, - SplashCoord *mat, GBool interpolate); - SplashBitmap *scaleImage(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - GBool interpolate); - void scaleImageYdXd(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleImageYdXu(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleImageYuXd(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleImageYuXu(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void scaleImageYuXuI(SplashImageSource src, void *srcData, - SplashColorMode srcMode, int nComps, - GBool srcAlpha, int srcWidth, int srcHeight, - int scaledWidth, int scaledHeight, - SplashBitmap *dest); - void vertFlipImage(SplashBitmap *img, int width, int height, - int nComps); - void horizFlipImage(SplashBitmap *img, int width, int height, - int nComps); - void blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest, - SplashClipResult clipRes); - void blitImageClipped(SplashBitmap *src, GBool srcAlpha, - int xSrc, int ySrc, int xDest, int yDest, - int w, int h); - void dumpPath(SplashPath *path); - void dumpXPath(SplashXPath *path); + void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi, + SplashCoord *xo, SplashCoord *yo); + void updateModX(int x); + void updateModY(int y); + void strokeNarrow(SplashPath *path); + void drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip); + void strokeWide(SplashPath *path, SplashCoord w, + int lineCap, int lineJoin); + SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix, + SplashCoord flatness); + void flattenCurve(SplashCoord x0, SplashCoord y0, + SplashCoord x1, SplashCoord y1, + SplashCoord x2, SplashCoord y2, + SplashCoord x3, SplashCoord y3, + SplashCoord *matrix, SplashCoord flatness2, + SplashPath *fPath); + SplashPath *makeDashedPath(SplashPath *xPath); + SplashError fillWithPattern(SplashPath *path, GBool eo, + SplashPattern *pattern, SplashCoord alpha); + SplashPath *tweakFillPath(SplashPath *path); + GBool pathAllOutside(SplashPath *path); + SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph); + void getImageBounds(SplashCoord xyMin, SplashCoord xyMax, + int *xyMinI, int *xyMaxI); + void upscaleMask(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + SplashCoord *mat, GBool glyphMode, + GBool interpolate); + void arbitraryTransformMask(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + SplashCoord *mat, GBool glyphMode, + GBool interpolate); + SplashBitmap *scaleMask(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + GBool interpolate); + void scaleMaskYdXd(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleMaskYdXu(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleMaskYuXd(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleMaskYuXu(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleMaskYuXuI(SplashImageMaskSource src, void *srcData, + int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void blitMask(SplashBitmap *src, int xDest, int yDest, + SplashClipResult clipRes); + void upscaleImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + SplashCoord *mat, GBool interpolate); + void arbitraryTransformImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, + int srcWidth, int srcHeight, + SplashCoord *mat, GBool interpolate); + SplashBitmap *scaleImage(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + GBool interpolate); + void scaleImageYdXd(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleImageYdXu(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleImageYuXd(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleImageYuXu(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void scaleImageYuXuI(SplashImageSource src, void *srcData, + SplashColorMode srcMode, int nComps, + GBool srcAlpha, int srcWidth, int srcHeight, + int scaledWidth, int scaledHeight, + SplashBitmap *dest); + void vertFlipImage(SplashBitmap *img, int width, int height, + int nComps); + void horizFlipImage(SplashBitmap *img, int width, int height, + int nComps); + void blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest, + SplashClipResult clipRes); + void blitImageClipped(SplashBitmap *src, GBool srcAlpha, + int xSrc, int ySrc, int xDest, int yDest, + int w, int h); + void dumpPath(SplashPath *path); + void dumpXPath(SplashXPath *path); - static SplashPipeResultColorCtrl pipeResultColorNoAlphaBlend[]; - static SplashPipeResultColorCtrl pipeResultColorAlphaNoBlend[]; - static SplashPipeResultColorCtrl pipeResultColorAlphaBlend[]; - static int pipeNonIsoGroupCorrection[]; + static SplashPipeResultColorCtrl pipeResultColorNoAlphaBlend[]; + static SplashPipeResultColorCtrl pipeResultColorAlphaNoBlend[]; + static SplashPipeResultColorCtrl pipeResultColorAlphaBlend[]; + static int pipeNonIsoGroupCorrection[]; - SplashBitmap *bitmap; - int bitmapComps; - SplashState *state; - Guchar *scanBuf; - Guchar *scanBuf2; - SplashBitmap // for transparency groups, this is the bitmap - *groupBackBitmap; // containing the alpha0/color0 values - int groupBackX, groupBackY; // offset within groupBackBitmap - SplashCoord minLineWidth; - int modXMin, modYMin, modXMax, modYMax; - SplashClipResult opClipRes; - GBool vectorAntialias; - GBool inShading; - GBool debugMode; + SplashBitmap *bitmap; + int bitmapComps; + SplashState *state; + Guchar *scanBuf; + Guchar *scanBuf2; + SplashBitmap // for transparency groups, this is the bitmap + *groupBackBitmap; // containing the alpha0/color0 values + int groupBackX, groupBackY; // offset within groupBackBitmap + SplashCoord minLineWidth; + int modXMin, modYMin, modXMax, modYMax; + SplashClipResult opClipRes; + GBool vectorAntialias; + GBool inShading; + GBool debugMode; }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-10025/Stream.h b/test/bug-hunting/cve/CVE-2019-10025/Stream.h index c25d46b2c..3c036e9c3 100644 --- a/test/bug-hunting/cve/CVE-2019-10025/Stream.h +++ b/test/bug-hunting/cve/CVE-2019-10025/Stream.h @@ -30,24 +30,24 @@ class SharedFile; //------------------------------------------------------------------------ enum StreamKind { - strFile, - strASCIIHex, - strASCII85, - strLZW, - strRunLength, - strCCITTFax, - strDCT, - strFlate, - strJBIG2, - strJPX, - strWeird // internal-use stream types + strFile, + strASCIIHex, + strASCII85, + strLZW, + strRunLength, + strCCITTFax, + strDCT, + strFlate, + strJBIG2, + strJPX, + strWeird // internal-use stream types }; enum StreamColorSpaceMode { - streamCSNone, - streamCSDeviceGray, - streamCSDeviceRGB, - streamCSDeviceCMYK + streamCSNone, + streamCSDeviceGray, + streamCSDeviceRGB, + streamCSDeviceCMYK }; //------------------------------------------------------------------------ @@ -55,9 +55,9 @@ enum StreamColorSpaceMode { // This is in Stream.h instead of Decrypt.h to avoid really annoying // include file dependency loops. enum CryptAlgorithm { - cryptRC4, - cryptAES, - cryptAES256 + cryptRC4, + cryptAES, + cryptAES256 }; //------------------------------------------------------------------------ @@ -67,88 +67,94 @@ enum CryptAlgorithm { class Stream { public: - // Constructor. - Stream(); + // Constructor. + Stream(); - // Destructor. - virtual ~Stream(); + // Destructor. + virtual ~Stream(); - virtual Stream *copy() = 0; + virtual Stream *copy() = 0; - // Get kind of stream. - virtual StreamKind getKind() = 0; + // Get kind of stream. + virtual StreamKind getKind() = 0; - virtual GBool isEmbedStream() { return gFalse; } + virtual GBool isEmbedStream() { + return gFalse; + } - // Reset stream to beginning. - virtual void reset() = 0; + // Reset stream to beginning. + virtual void reset() = 0; - // Close down the stream. - virtual void close(); + // Close down the stream. + virtual void close(); - // Get next char from stream. - virtual int getChar() = 0; + // Get next char from stream. + virtual int getChar() = 0; - // Peek at next char in stream. - virtual int lookChar() = 0; + // Peek at next char in stream. + virtual int lookChar() = 0; - // Get next char from stream without using the predictor. - // This is only used by StreamPredictor. - virtual int getRawChar(); + // Get next char from stream without using the predictor. + // This is only used by StreamPredictor. + virtual int getRawChar(); - // Get exactly bytes from stream. Returns the number of - // bytes read -- the returned count will be less than at EOF. - virtual int getBlock(char *blk, int size); + // Get exactly bytes from stream. Returns the number of + // bytes read -- the returned count will be less than at EOF. + virtual int getBlock(char *blk, int size); - // Get next line from stream. - virtual char *getLine(char *buf, int size); + // Get next line from stream. + virtual char *getLine(char *buf, int size); - // Discard the next bytes from stream. Returns the number of - // bytes discarded, which will be less than only if EOF is - // reached. - virtual Guint discardChars(Guint n); + // Discard the next bytes from stream. Returns the number of + // bytes discarded, which will be less than only if EOF is + // reached. + virtual Guint discardChars(Guint n); - // Get current position in file. - virtual GFileOffset getPos() = 0; + // Get current position in file. + virtual GFileOffset getPos() = 0; - // Go to a position in the stream. If is negative, the - // position is from the end of the file; otherwise the position is - // from the start of the file. - virtual void setPos(GFileOffset pos, int dir = 0) = 0; + // Go to a position in the stream. If is negative, the + // position is from the end of the file; otherwise the position is + // from the start of the file. + virtual void setPos(GFileOffset pos, int dir = 0) = 0; - // Get PostScript command for the filter(s). - virtual GString *getPSFilter(int psLevel, const char *indent); + // Get PostScript command for the filter(s). + virtual GString *getPSFilter(int psLevel, const char *indent); - // Does this stream type potentially contain non-printable chars? - virtual GBool isBinary(GBool last = gTrue) = 0; + // Does this stream type potentially contain non-printable chars? + virtual GBool isBinary(GBool last = gTrue) = 0; - // Get the BaseStream of this stream. - virtual BaseStream *getBaseStream() = 0; + // Get the BaseStream of this stream. + virtual BaseStream *getBaseStream() = 0; - // Get the stream after the last decoder (this may be a BaseStream - // or a DecryptStream). - virtual Stream *getUndecodedStream() = 0; + // Get the stream after the last decoder (this may be a BaseStream + // or a DecryptStream). + virtual Stream *getUndecodedStream() = 0; - // Get the dictionary associated with this stream. - virtual Dict *getDict() = 0; + // Get the dictionary associated with this stream. + virtual Dict *getDict() = 0; - // Is this an encoding filter? - virtual GBool isEncoder() { return gFalse; } + // Is this an encoding filter? + virtual GBool isEncoder() { + return gFalse; + } - // Get image parameters which are defined by the stream contents. - virtual void getImageParams(int *bitsPerComponent, - StreamColorSpaceMode *csMode) {} + // Get image parameters which are defined by the stream contents. + virtual void getImageParams(int *bitsPerComponent, + StreamColorSpaceMode *csMode) {} - // Return the next stream in the "stack". - virtual Stream *getNextStream() { return NULL; } + // Return the next stream in the "stack". + virtual Stream *getNextStream() { + return NULL; + } - // Add filters to this stream according to the parameters in . - // Returns the new stream. - Stream *addFilters(Object *dict, int recursion = 0); + // Add filters to this stream according to the parameters in . + // Returns the new stream. + Stream *addFilters(Object *dict, int recursion = 0); private: - Stream *makeFilter(char *name, Stream *str, Object *params, int recursion); + Stream *makeFilter(char *name, Stream *str, Object *params, int recursion); }; //------------------------------------------------------------------------ @@ -157,27 +163,37 @@ private: // This is the base class for all streams that read directly from a file. //------------------------------------------------------------------------ -class BaseStream: public Stream { +class BaseStream : public Stream { public: - BaseStream(Object *dictA); - virtual ~BaseStream(); - virtual Stream *makeSubStream(GFileOffset start, GBool limited, - GFileOffset length, Object *dict) = 0; - virtual void setPos(GFileOffset pos, int dir = 0) = 0; - virtual GBool isBinary(GBool last = gTrue) { return last; } - virtual BaseStream *getBaseStream() { return this; } - virtual Stream *getUndecodedStream() { return this; } - virtual Dict *getDict() { return dict.getDict(); } - virtual GString *getFileName() { return NULL; } + BaseStream(Object *dictA); + virtual ~BaseStream(); + virtual Stream *makeSubStream(GFileOffset start, GBool limited, + GFileOffset length, Object *dict) = 0; + virtual void setPos(GFileOffset pos, int dir = 0) = 0; + virtual GBool isBinary(GBool last = gTrue) { + return last; + } + virtual BaseStream *getBaseStream() { + return this; + } + virtual Stream *getUndecodedStream() { + return this; + } + virtual Dict *getDict() { + return dict.getDict(); + } + virtual GString *getFileName() { + return NULL; + } - // Get/set position of first byte of stream within the file. - virtual GFileOffset getStart() = 0; - virtual void moveStart(int delta) = 0; + // Get/set position of first byte of stream within the file. + virtual GFileOffset getStart() = 0; + virtual void moveStart(int delta) = 0; protected: - Object dict; + Object dict; }; //------------------------------------------------------------------------ @@ -186,22 +202,32 @@ protected: // This is the base class for all streams that filter another stream. //------------------------------------------------------------------------ -class FilterStream: public Stream { +class FilterStream : public Stream { public: - FilterStream(Stream *strA); - virtual ~FilterStream(); - virtual void close(); - virtual GFileOffset getPos() { return str->getPos(); } - virtual void setPos(GFileOffset pos, int dir = 0); - virtual BaseStream *getBaseStream() { return str->getBaseStream(); } - virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); } - virtual Dict *getDict() { return str->getDict(); } - virtual Stream *getNextStream() { return str; } + FilterStream(Stream *strA); + virtual ~FilterStream(); + virtual void close(); + virtual GFileOffset getPos() { + return str->getPos(); + } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual BaseStream *getBaseStream() { + return str->getBaseStream(); + } + virtual Stream *getUndecodedStream() { + return str->getUndecodedStream(); + } + virtual Dict *getDict() { + return str->getDict(); + } + virtual Stream *getNextStream() { + return str; + } protected: - Stream *str; + Stream *str; }; //------------------------------------------------------------------------ @@ -211,41 +237,41 @@ protected: class ImageStream { public: - // Create an image stream object for an image with the specified - // parameters. Note that these are the actual image parameters, - // which may be different from the predictor parameters. - ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA); + // Create an image stream object for an image with the specified + // parameters. Note that these are the actual image parameters, + // which may be different from the predictor parameters. + ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA); - ~ImageStream(); + ~ImageStream(); - // Reset the stream. - void reset(); + // Reset the stream. + void reset(); - // Close down the stream. - void close(); + // Close down the stream. + void close(); - // Gets the next pixel from the stream. should be able to hold - // at least nComps elements. Returns false at end of file. - GBool getPixel(Guchar *pix); + // Gets the next pixel from the stream. should be able to hold + // at least nComps elements. Returns false at end of file. + GBool getPixel(Guchar *pix); - // Returns a pointer to the next line of pixels. Returns NULL at - // end of file. - Guchar *getLine(); + // Returns a pointer to the next line of pixels. Returns NULL at + // end of file. + Guchar *getLine(); - // Skip an entire line from the image. - void skipLine(); + // Skip an entire line from the image. + void skipLine(); private: - Stream *str; // base stream - int width; // pixels per line - int nComps; // components per pixel - int nBits; // bits per component - int nVals; // components per line - int inputLineSize; // input line buffer size - char *inputLine; // input line buffer - Guchar *imgLine; // line buffer - int imgIdx; // current index in imgLine + Stream *str; // base stream + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + int inputLineSize; // input line buffer size + char *inputLine; // input line buffer + Guchar *imgLine; // line buffer + int imgIdx; // current index in imgLine }; @@ -256,41 +282,51 @@ private: class StreamPredictor { public: - // Create a predictor object. Note that the parameters are for the - // predictor, and may not match the actual image parameters. - StreamPredictor(Stream *strA, int predictorA, - int widthA, int nCompsA, int nBitsA); + // Create a predictor object. Note that the parameters are for the + // predictor, and may not match the actual image parameters. + StreamPredictor(Stream *strA, int predictorA, + int widthA, int nCompsA, int nBitsA); - ~StreamPredictor(); + ~StreamPredictor(); - GBool isOk() { return ok; } + GBool isOk() { + return ok; + } - void reset(); + void reset(); - int lookChar(); - int getChar(); - int getBlock(char *blk, int size); + int lookChar(); + int getChar(); + int getBlock(char *blk, int size); - int getPredictor() { return predictor; } - int getWidth() { return width; } - int getNComps() { return nComps; } - int getNBits() { return nBits; } + int getPredictor() { + return predictor; + } + int getWidth() { + return width; + } + int getNComps() { + return nComps; + } + int getNBits() { + return nBits; + } private: - GBool getNextLine(); + GBool getNextLine(); - Stream *str; // base stream - int predictor; // predictor - int width; // pixels per line - int nComps; // components per pixel - int nBits; // bits per component - int nVals; // components per line - int pixBytes; // bytes per pixel - int rowBytes; // bytes per line - Guchar *predLine; // line buffer - int predIdx; // current index in predLine - GBool ok; + Stream *str; // base stream + int predictor; // predictor + int width; // pixels per line + int nComps; // components per pixel + int nBits; // bits per component + int nVals; // components per line + int pixBytes; // bytes per pixel + int rowBytes; // bytes per line + Guchar *predLine; // line buffer + int predIdx; // current index in predLine + GBool ok; }; //------------------------------------------------------------------------ @@ -299,76 +335,96 @@ private: #define fileStreamBufSize 256 -class FileStream: public BaseStream { +class FileStream : public BaseStream { public: - FileStream(FILE *fA, GFileOffset startA, GBool limitedA, - GFileOffset lengthA, Object *dictA); - virtual ~FileStream(); - virtual Stream *copy(); - virtual Stream *makeSubStream(GFileOffset startA, GBool limitedA, - GFileOffset lengthA, Object *dictA); - virtual StreamKind getKind() { return strFile; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual int getBlock(char *blk, int size); - virtual GFileOffset getPos() { return bufPos + (int)(bufPtr - buf); } - virtual void setPos(GFileOffset pos, int dir = 0); - virtual GFileOffset getStart() { return start; } - virtual void moveStart(int delta); + FileStream(FILE *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual ~FileStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { + return strFile; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { + return bufPos + (int)(bufPtr - buf); + } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart() { + return start; + } + virtual void moveStart(int delta); private: - FileStream(SharedFile *fA, GFileOffset startA, GBool limitedA, - GFileOffset lengthA, Object *dictA); - GBool fillBuf(); + FileStream(SharedFile *fA, GFileOffset startA, GBool limitedA, + GFileOffset lengthA, Object *dictA); + GBool fillBuf(); - SharedFile *f; - GFileOffset start; - GBool limited; - GFileOffset length; - char buf[fileStreamBufSize]; - char *bufPtr; - char *bufEnd; - GFileOffset bufPos; + SharedFile *f; + GFileOffset start; + GBool limited; + GFileOffset length; + char buf[fileStreamBufSize]; + char *bufPtr; + char *bufEnd; + GFileOffset bufPos; }; //------------------------------------------------------------------------ // MemStream //------------------------------------------------------------------------ -class MemStream: public BaseStream { +class MemStream : public BaseStream { public: - MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); - virtual ~MemStream(); - virtual Stream *copy(); - virtual Stream *makeSubStream(GFileOffset start, GBool limited, - GFileOffset lengthA, Object *dictA); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual void close(); - virtual int getChar() - { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; } - virtual int lookChar() - { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; } - virtual int getBlock(char *blk, int size); - virtual GFileOffset getPos() { return (GFileOffset)(bufPtr - buf); } - virtual void setPos(GFileOffset pos, int dir = 0); - virtual GFileOffset getStart() { return start; } - virtual void moveStart(int delta); + MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); + virtual ~MemStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset start, GBool limited, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual void close(); + virtual int getChar() + { + return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; + } + virtual int lookChar() + { + return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; + } + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { + return (GFileOffset)(bufPtr - buf); + } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart() { + return start; + } + virtual void moveStart(int delta); private: - char *buf; - Guint start; - Guint length; - char *bufEnd; - char *bufPtr; - GBool needFree; + char *buf; + Guint start; + Guint length; + char *bufEnd; + char *bufPtr; + GBool needFree; }; //------------------------------------------------------------------------ @@ -381,156 +437,178 @@ private: // that creating a new FileStream (using makeSubStream). //------------------------------------------------------------------------ -class EmbedStream: public BaseStream { +class EmbedStream : public BaseStream { public: - EmbedStream(Stream *strA, Object *dictA, GBool limitedA, GFileOffset lengthA); - virtual ~EmbedStream(); - virtual Stream *copy(); - virtual Stream *makeSubStream(GFileOffset start, GBool limitedA, - GFileOffset lengthA, Object *dictA); - virtual StreamKind getKind() { return str->getKind(); } - virtual GBool isEmbedStream() { return gTrue; } - virtual void reset() {} - virtual int getChar(); - virtual int lookChar(); - virtual int getBlock(char *blk, int size); - virtual GFileOffset getPos() { return str->getPos(); } - virtual void setPos(GFileOffset pos, int dir = 0); - virtual GFileOffset getStart(); - virtual void moveStart(int delta); + EmbedStream(Stream *strA, Object *dictA, GBool limitedA, GFileOffset lengthA); + virtual ~EmbedStream(); + virtual Stream *copy(); + virtual Stream *makeSubStream(GFileOffset start, GBool limitedA, + GFileOffset lengthA, Object *dictA); + virtual StreamKind getKind() { + return str->getKind(); + } + virtual GBool isEmbedStream() { + return gTrue; + } + virtual void reset() {} + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GFileOffset getPos() { + return str->getPos(); + } + virtual void setPos(GFileOffset pos, int dir = 0); + virtual GFileOffset getStart(); + virtual void moveStart(int delta); private: - Stream *str; - GBool limited; - GFileOffset length; + Stream *str; + GBool limited; + GFileOffset length; }; //------------------------------------------------------------------------ // ASCIIHexStream //------------------------------------------------------------------------ -class ASCIIHexStream: public FilterStream { +class ASCIIHexStream : public FilterStream { public: - ASCIIHexStream(Stream *strA); - virtual ~ASCIIHexStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strASCIIHex; } - virtual void reset(); - virtual int getChar() - { int c = lookChar(); buf = EOF; return c; } - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + ASCIIHexStream(Stream *strA); + virtual ~ASCIIHexStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strASCIIHex; + } + virtual void reset(); + virtual int getChar() + { + int c = lookChar(); buf = EOF; return c; + } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - int buf; - GBool eof; + int buf; + GBool eof; }; //------------------------------------------------------------------------ // ASCII85Stream //------------------------------------------------------------------------ -class ASCII85Stream: public FilterStream { +class ASCII85Stream : public FilterStream { public: - ASCII85Stream(Stream *strA); - virtual ~ASCII85Stream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strASCII85; } - virtual void reset(); - virtual int getChar() - { int ch = lookChar(); ++index; return ch; } - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + ASCII85Stream(Stream *strA); + virtual ~ASCII85Stream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strASCII85; + } + virtual void reset(); + virtual int getChar() + { + int ch = lookChar(); ++index; return ch; + } + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - int c[5]; - int b[4]; - int index, n; - GBool eof; + int c[5]; + int b[4]; + int index, n; + GBool eof; }; //------------------------------------------------------------------------ // LZWStream //------------------------------------------------------------------------ -class LZWStream: public FilterStream { +class LZWStream : public FilterStream { public: - LZWStream(Stream *strA, int predictor, int columns, int colors, - int bits, int earlyA); - virtual ~LZWStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strLZW; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getRawChar(); - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + LZWStream(Stream *strA, int predictor, int columns, int colors, + int bits, int earlyA); + virtual ~LZWStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strLZW; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - StreamPredictor *pred; // predictor - int early; // early parameter - GBool eof; // true if at eof - int inputBuf; // input buffer - int inputBits; // number of bits in input buffer - struct { // decoding table - int length; - int head; - Guchar tail; - } table[4097]; - int nextCode; // next code to be used - int nextBits; // number of bits in next code word - int prevCode; // previous code used in stream - int newChar; // next char to be added to table - Guchar seqBuf[4097]; // buffer for current sequence - int seqLength; // length of current sequence - int seqIndex; // index into current sequence - GBool first; // first code after a table clear + StreamPredictor *pred; // predictor + int early; // early parameter + GBool eof; // true if at eof + int inputBuf; // input buffer + int inputBits; // number of bits in input buffer + struct { // decoding table + int length; + int head; + Guchar tail; + } table[4097]; + int nextCode; // next code to be used + int nextBits; // number of bits in next code word + int prevCode; // previous code used in stream + int newChar; // next char to be added to table + Guchar seqBuf[4097]; // buffer for current sequence + int seqLength; // length of current sequence + int seqIndex; // index into current sequence + GBool first; // first code after a table clear - GBool processNextCode(); - void clearTable(); - int getCode(); + GBool processNextCode(); + void clearTable(); + int getCode(); }; //------------------------------------------------------------------------ // RunLengthStream //------------------------------------------------------------------------ -class RunLengthStream: public FilterStream { +class RunLengthStream : public FilterStream { public: - RunLengthStream(Stream *strA); - virtual ~RunLengthStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strRunLength; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + RunLengthStream(Stream *strA); + virtual ~RunLengthStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strRunLength; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - char buf[128]; // buffer - char *bufPtr; // next char to read - char *bufEnd; // end of buffer - GBool eof; + char buf[128]; // buffer + char *bufPtr; // next char to read + char *bufEnd; // end of buffer + GBool eof; - GBool fillBuf(); + GBool fillBuf(); }; //------------------------------------------------------------------------ @@ -539,52 +617,56 @@ private: struct CCITTCodeTable; -class CCITTFaxStream: public FilterStream { +class CCITTFaxStream : public FilterStream { public: - CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, - GBool byteAlignA, int columnsA, int rowsA, - GBool endOfBlockA, GBool blackA); - virtual ~CCITTFaxStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strCCITTFax; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, + GBool byteAlignA, int columnsA, int rowsA, + GBool endOfBlockA, GBool blackA); + virtual ~CCITTFaxStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strCCITTFax; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - int encoding; // 'K' parameter - GBool endOfLine; // 'EndOfLine' parameter - GBool byteAlign; // 'EncodedByteAlign' parameter - int columns; // 'Columns' parameter - int rows; // 'Rows' parameter - GBool endOfBlock; // 'EndOfBlock' parameter - GBool black; // 'BlackIs1' parameter - int blackXOR; - GBool eof; // true if at eof - GBool nextLine2D; // true if next line uses 2D encoding - int row; // current row - Guint inputBuf; // input buffer - int inputBits; // number of bits in input buffer - int *codingLine; // coding line changing elements - int *refLine; // reference line changing elements - int nextCol; // next column to read - int a0i; // index into codingLine - GBool err; // error on current line - int nErrors; // number of errors so far in this stream + int encoding; // 'K' parameter + GBool endOfLine; // 'EndOfLine' parameter + GBool byteAlign; // 'EncodedByteAlign' parameter + int columns; // 'Columns' parameter + int rows; // 'Rows' parameter + GBool endOfBlock; // 'EndOfBlock' parameter + GBool black; // 'BlackIs1' parameter + int blackXOR; + GBool eof; // true if at eof + GBool nextLine2D; // true if next line uses 2D encoding + int row; // current row + Guint inputBuf; // input buffer + int inputBits; // number of bits in input buffer + int *codingLine; // coding line changing elements + int *refLine; // reference line changing elements + int nextCol; // next column to read + int a0i; // index into codingLine + GBool err; // error on current line + int nErrors; // number of errors so far in this stream - void addPixels(int a1, int blackPixels); - void addPixelsNeg(int a1, int blackPixels); - GBool readRow(); - short getTwoDimCode(); - short getWhiteCode(); - short getBlackCode(); - short lookBits(int n); - void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; } + void addPixels(int a1, int blackPixels); + void addPixelsNeg(int a1, int blackPixels); + GBool readRow(); + short getTwoDimCode(); + short getWhiteCode(); + short getBlackCode(); + short lookBits(int n); + void eatBits(int n) { + if ((inputBits -= n) < 0) inputBits = 0; + } }; //------------------------------------------------------------------------ @@ -598,148 +680,152 @@ class DCTStream; #define dctStreamBufSize 4096 struct DCTSourceMgr { - jpeg_source_mgr src; - DCTStream *str; - char buf[dctStreamBufSize]; + jpeg_source_mgr src; + DCTStream *str; + char buf[dctStreamBufSize]; }; struct DCTErrorMgr { - struct jpeg_error_mgr err; - jmp_buf setjmpBuf; + struct jpeg_error_mgr err; + jmp_buf setjmpBuf; }; #else // HAVE_JPEGLIB // DCT component info struct DCTCompInfo { - int id; // component ID - int hSample, vSample; // horiz/vert sampling resolutions - int quantTable; // quantization table number - int prevDC; // DC coefficient accumulator + int id; // component ID + int hSample, vSample; // horiz/vert sampling resolutions + int quantTable; // quantization table number + int prevDC; // DC coefficient accumulator }; struct DCTScanInfo { - GBool comp[4]; // comp[i] is set if component i is - // included in this scan - int numComps; // number of components in the scan - int dcHuffTable[4]; // DC Huffman table numbers - int acHuffTable[4]; // AC Huffman table numbers - int firstCoeff, lastCoeff; // first and last DCT coefficient - int ah, al; // successive approximation parameters + GBool comp[4]; // comp[i] is set if component i is + // included in this scan + int numComps; // number of components in the scan + int dcHuffTable[4]; // DC Huffman table numbers + int acHuffTable[4]; // AC Huffman table numbers + int firstCoeff, lastCoeff; // first and last DCT coefficient + int ah, al; // successive approximation parameters }; // DCT Huffman decoding table struct DCTHuffTable { - Guchar firstSym[17]; // first symbol for this bit length - Gushort firstCode[17]; // first code for this bit length - Gushort numCodes[17]; // number of codes of this bit length - Guchar sym[256]; // symbols + Guchar firstSym[17]; // first symbol for this bit length + Gushort firstCode[17]; // first code for this bit length + Gushort numCodes[17]; // number of codes of this bit length + Guchar sym[256]; // symbols }; #endif // HAVE_JPEGLIB -class DCTStream: public FilterStream { +class DCTStream : public FilterStream { public: - DCTStream(Stream *strA, int colorXformA); - virtual ~DCTStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strDCT; } - virtual void reset(); - virtual void close(); - virtual int getChar(); - virtual int lookChar(); - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); - Stream *getRawStream() { return str; } + DCTStream(Stream *strA, int colorXformA); + virtual ~DCTStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strDCT; + } + virtual void reset(); + virtual void close(); + virtual int getChar(); + virtual int lookChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); + Stream *getRawStream() { + return str; + } private: #if HAVE_JPEGLIB - int colorXform; // color transform: -1 = unspecified - // 0 = none - // 1 = YUV/YUVK -> RGB/CMYK - jpeg_decompress_struct decomp; - DCTErrorMgr errorMgr; - DCTSourceMgr sourceMgr; - GBool error; - char *lineBuf; - int lineBufHeight; - char *lineBufRows[4]; - char *bufPtr; - char *bufEnd; - GBool inlineImage; + int colorXform; // color transform: -1 = unspecified + // 0 = none + // 1 = YUV/YUVK -> RGB/CMYK + jpeg_decompress_struct decomp; + DCTErrorMgr errorMgr; + DCTSourceMgr sourceMgr; + GBool error; + char *lineBuf; + int lineBufHeight; + char *lineBufRows[4]; + char *bufPtr; + char *bufEnd; + GBool inlineImage; - GBool fillBuf(); - static void errorExit(j_common_ptr d); - static void errorMessage(j_common_ptr d); - static void initSourceCbk(j_decompress_ptr d); - static boolean fillInputBufferCbk(j_decompress_ptr d); - static void skipInputDataCbk(j_decompress_ptr d, long numBytes); - static void termSourceCbk(j_decompress_ptr d); + GBool fillBuf(); + static void errorExit(j_common_ptr d); + static void errorMessage(j_common_ptr d); + static void initSourceCbk(j_decompress_ptr d); + static boolean fillInputBufferCbk(j_decompress_ptr d); + static void skipInputDataCbk(j_decompress_ptr d, long numBytes); + static void termSourceCbk(j_decompress_ptr d); #else // HAVE_JPEGLIB - GBool progressive; // set if in progressive mode - GBool interleaved; // set if in interleaved mode - int width, height; // image size - int mcuWidth, mcuHeight; // size of min coding unit, in data units - int bufWidth, bufHeight; // frameBuf size - DCTCompInfo compInfo[4]; // info for each component - DCTScanInfo scanInfo; // info for the current scan - int numComps; // number of components in image - int colorXform; // color transform: -1 = unspecified - // 0 = none - // 1 = YUV/YUVK -> RGB/CMYK - GBool gotJFIFMarker; // set if APP0 JFIF marker was present - GBool gotAdobeMarker; // set if APP14 Adobe marker was present - int restartInterval; // restart interval, in MCUs - Gushort quantTables[4][64]; // quantization tables - int numQuantTables; // number of quantization tables - DCTHuffTable dcHuffTables[4]; // DC Huffman tables - DCTHuffTable acHuffTables[4]; // AC Huffman tables - int numDCHuffTables; // number of DC Huffman tables - int numACHuffTables; // number of AC Huffman tables - Guchar *rowBuf; - Guchar *rowBufPtr; // current position within rowBuf - Guchar *rowBufEnd; // end of valid data in rowBuf - int *frameBuf[4]; // buffer for frame (progressive mode) - int comp, x, y; // current position within image/MCU - int restartCtr; // MCUs left until restart - int restartMarker; // next restart marker - int eobRun; // number of EOBs left in the current run - int inputBuf; // input buffer for variable length codes - int inputBits; // number of valid bits in input buffer + GBool progressive; // set if in progressive mode + GBool interleaved; // set if in interleaved mode + int width, height; // image size + int mcuWidth, mcuHeight; // size of min coding unit, in data units + int bufWidth, bufHeight; // frameBuf size + DCTCompInfo compInfo[4]; // info for each component + DCTScanInfo scanInfo; // info for the current scan + int numComps; // number of components in image + int colorXform; // color transform: -1 = unspecified + // 0 = none + // 1 = YUV/YUVK -> RGB/CMYK + GBool gotJFIFMarker; // set if APP0 JFIF marker was present + GBool gotAdobeMarker; // set if APP14 Adobe marker was present + int restartInterval; // restart interval, in MCUs + Gushort quantTables[4][64]; // quantization tables + int numQuantTables; // number of quantization tables + DCTHuffTable dcHuffTables[4]; // DC Huffman tables + DCTHuffTable acHuffTables[4]; // AC Huffman tables + int numDCHuffTables; // number of DC Huffman tables + int numACHuffTables; // number of AC Huffman tables + Guchar *rowBuf; + Guchar *rowBufPtr; // current position within rowBuf + Guchar *rowBufEnd; // end of valid data in rowBuf + int *frameBuf[4]; // buffer for frame (progressive mode) + int comp, x, y; // current position within image/MCU + int restartCtr; // MCUs left until restart + int restartMarker; // next restart marker + int eobRun; // number of EOBs left in the current run + int inputBuf; // input buffer for variable length codes + int inputBits; // number of valid bits in input buffer - void restart(); - GBool readMCURow(); - void readScan(); - GBool readDataUnit(DCTHuffTable *dcHuffTable, - DCTHuffTable *acHuffTable, - int *prevDC, int data[64]); - GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, - DCTHuffTable *acHuffTable, - int *prevDC, int data[64]); - void decodeImage(); - void transformDataUnit(Gushort *quantTable, - int dataIn[64], Guchar dataOut[64]); - int readHuffSym(DCTHuffTable *table); - int readAmp(int size); - int readBit(); - GBool readHeader(GBool frame); - GBool readBaselineSOF(); - GBool readProgressiveSOF(); - GBool readScanInfo(); - GBool readQuantTables(); - GBool readHuffmanTables(); - GBool readRestartInterval(); - GBool readJFIFMarker(); - GBool readAdobeMarker(); - GBool readTrailer(); - int readMarker(); - int read16(); + void restart(); + GBool readMCURow(); + void readScan(); + GBool readDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]); + GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, + DCTHuffTable *acHuffTable, + int *prevDC, int data[64]); + void decodeImage(); + void transformDataUnit(Gushort *quantTable, + int dataIn[64], Guchar dataOut[64]); + int readHuffSym(DCTHuffTable *table); + int readAmp(int size); + int readBit(); + GBool readHeader(GBool frame); + GBool readBaselineSOF(); + GBool readProgressiveSOF(); + GBool readScanInfo(); + GBool readQuantTables(); + GBool readHuffmanTables(); + GBool readRestartInterval(); + GBool readJFIFMarker(); + GBool readAdobeMarker(); + GBool readTrailer(); + int readMarker(); + int read16(); #endif // HAVE_JPEGLIB }; @@ -757,239 +843,299 @@ private: // Huffman code table entry struct FlateCode { - Gushort len; // code length, in bits - Gushort val; // value represented by this code + Gushort len; // code length, in bits + Gushort val; // value represented by this code }; struct FlateHuffmanTab { - FlateCode *codes; - int maxLen; + FlateCode *codes; + int maxLen; }; // Decoding info for length and distance code words struct FlateDecode { - int bits; // # extra bits - int first; // first length/distance + int bits; // # extra bits + int first; // first length/distance }; -class FlateStream: public FilterStream { +class FlateStream : public FilterStream { public: - FlateStream(Stream *strA, int predictor, int columns, - int colors, int bits); - virtual ~FlateStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strFlate; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getRawChar(); - virtual int getBlock(char *blk, int size); - virtual GString *getPSFilter(int psLevel, const char *indent); - virtual GBool isBinary(GBool last = gTrue); + FlateStream(Stream *strA, int predictor, int columns, + int colors, int bits); + virtual ~FlateStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strFlate; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual int getRawChar(); + virtual int getBlock(char *blk, int size); + virtual GString *getPSFilter(int psLevel, const char *indent); + virtual GBool isBinary(GBool last = gTrue); private: - StreamPredictor *pred; // predictor - Guchar buf[flateWindow]; // output data buffer - int index; // current index into output buffer - int remain; // number valid bytes in output buffer - int codeBuf; // input buffer - int codeSize; // number of bits in input buffer - int // literal and distance code lengths - codeLengths[flateMaxLitCodes + flateMaxDistCodes]; - FlateHuffmanTab litCodeTab; // literal code table - FlateHuffmanTab distCodeTab; // distance code table - GBool compressedBlock; // set if reading a compressed block - int blockLen; // remaining length of uncompressed block - GBool endOfBlock; // set when end of block is reached - GBool eof; // set when end of stream is reached + StreamPredictor *pred; // predictor + Guchar buf[flateWindow]; // output data buffer + int index; // current index into output buffer + int remain; // number valid bytes in output buffer + int codeBuf; // input buffer + int codeSize; // number of bits in input buffer + int // literal and distance code lengths + codeLengths[flateMaxLitCodes + flateMaxDistCodes]; + FlateHuffmanTab litCodeTab; // literal code table + FlateHuffmanTab distCodeTab; // distance code table + GBool compressedBlock; // set if reading a compressed block + int blockLen; // remaining length of uncompressed block + GBool endOfBlock; // set when end of block is reached + GBool eof; // set when end of stream is reached - static int // code length code reordering - codeLenCodeMap[flateMaxCodeLenCodes]; - static FlateDecode // length decoding info - lengthDecode[flateMaxLitCodes-257]; - static FlateDecode // distance decoding info - distDecode[flateMaxDistCodes]; - static FlateHuffmanTab // fixed literal code table - fixedLitCodeTab; - static FlateHuffmanTab // fixed distance code table - fixedDistCodeTab; + static int // code length code reordering + codeLenCodeMap[flateMaxCodeLenCodes]; + static FlateDecode // length decoding info + lengthDecode[flateMaxLitCodes-257]; + static FlateDecode // distance decoding info + distDecode[flateMaxDistCodes]; + static FlateHuffmanTab // fixed literal code table + fixedLitCodeTab; + static FlateHuffmanTab // fixed distance code table + fixedDistCodeTab; - void readSome(); - GBool startBlock(); - void loadFixedCodes(); - GBool readDynamicCodes(); - void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); - int getHuffmanCodeWord(FlateHuffmanTab *tab); - int getCodeWord(int bits); + void readSome(); + GBool startBlock(); + void loadFixedCodes(); + GBool readDynamicCodes(); + void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); + int getHuffmanCodeWord(FlateHuffmanTab *tab); + int getCodeWord(int bits); }; //------------------------------------------------------------------------ // EOFStream //------------------------------------------------------------------------ -class EOFStream: public FilterStream { +class EOFStream : public FilterStream { public: - EOFStream(Stream *strA); - virtual ~EOFStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset() {} - virtual int getChar() { return EOF; } - virtual int lookChar() { return EOF; } - virtual int getBlock(char *blk, int size) { return 0; } - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } + EOFStream(Stream *strA); + virtual ~EOFStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset() {} + virtual int getChar() { + return EOF; + } + virtual int lookChar() { + return EOF; + } + virtual int getBlock(char *blk, int size) { + return 0; + } + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gFalse; + } }; //------------------------------------------------------------------------ // BufStream //------------------------------------------------------------------------ -class BufStream: public FilterStream { +class BufStream : public FilterStream { public: - BufStream(Stream *strA, int bufSizeA); - virtual ~BufStream(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue); + BufStream(Stream *strA, int bufSizeA); + virtual ~BufStream(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue); - int lookChar(int idx); + int lookChar(int idx); private: - int *buf; - int bufSize; + int *buf; + int bufSize; }; //------------------------------------------------------------------------ // FixedLengthEncoder //------------------------------------------------------------------------ -class FixedLengthEncoder: public FilterStream { +class FixedLengthEncoder : public FilterStream { public: - FixedLengthEncoder(Stream *strA, int lengthA); - ~FixedLengthEncoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue); - virtual GBool isEncoder() { return gTrue; } + FixedLengthEncoder(Stream *strA, int lengthA); + ~FixedLengthEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue); + virtual GBool isEncoder() { + return gTrue; + } private: - int length; - int count; + int length; + int count; }; //------------------------------------------------------------------------ // ASCIIHexEncoder //------------------------------------------------------------------------ -class ASCIIHexEncoder: public FilterStream { +class ASCIIHexEncoder : public FilterStream { public: - ASCIIHexEncoder(Stream *strA); - virtual ~ASCIIHexEncoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } - virtual GBool isEncoder() { return gTrue; } + ASCIIHexEncoder(Stream *strA); + virtual ~ASCIIHexEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gFalse; + } + virtual GBool isEncoder() { + return gTrue; + } private: - char buf[4]; - char *bufPtr; - char *bufEnd; - int lineLen; - GBool eof; + char buf[4]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; - GBool fillBuf(); + GBool fillBuf(); }; //------------------------------------------------------------------------ // ASCII85Encoder //------------------------------------------------------------------------ -class ASCII85Encoder: public FilterStream { +class ASCII85Encoder : public FilterStream { public: - ASCII85Encoder(Stream *strA); - virtual ~ASCII85Encoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } - virtual GBool isEncoder() { return gTrue; } + ASCII85Encoder(Stream *strA); + virtual ~ASCII85Encoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gFalse; + } + virtual GBool isEncoder() { + return gTrue; + } private: - char buf[8]; - char *bufPtr; - char *bufEnd; - int lineLen; - GBool eof; + char buf[8]; + char *bufPtr; + char *bufEnd; + int lineLen; + GBool eof; - GBool fillBuf(); + GBool fillBuf(); }; //------------------------------------------------------------------------ // RunLengthEncoder //------------------------------------------------------------------------ -class RunLengthEncoder: public FilterStream { +class RunLengthEncoder : public FilterStream { public: - RunLengthEncoder(Stream *strA); - virtual ~RunLengthEncoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gTrue; } - virtual GBool isEncoder() { return gTrue; } + RunLengthEncoder(Stream *strA); + virtual ~RunLengthEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); + } + virtual int lookChar() + { + return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); + } + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gTrue; + } + virtual GBool isEncoder() { + return gTrue; + } private: - char buf[131]; - char *bufPtr; - char *bufEnd; - char *nextEnd; - GBool eof; + char buf[131]; + char *bufPtr; + char *bufEnd; + char *nextEnd; + GBool eof; - GBool fillBuf(); + GBool fillBuf(); }; //------------------------------------------------------------------------ @@ -997,39 +1143,47 @@ private: //------------------------------------------------------------------------ struct LZWEncoderNode { - int byte; - LZWEncoderNode *next; // next sibling - LZWEncoderNode *children; // first child + int byte; + LZWEncoderNode *next; // next sibling + LZWEncoderNode *children; // first child }; -class LZWEncoder: public FilterStream { +class LZWEncoder : public FilterStream { public: - LZWEncoder(Stream *strA); - virtual ~LZWEncoder(); - virtual Stream *copy(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, const char *indent) - { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gTrue; } - virtual GBool isEncoder() { return gTrue; } + LZWEncoder(Stream *strA); + virtual ~LZWEncoder(); + virtual Stream *copy(); + virtual StreamKind getKind() { + return strWeird; + } + virtual void reset(); + virtual int getChar(); + virtual int lookChar(); + virtual GString *getPSFilter(int psLevel, const char *indent) + { + return NULL; + } + virtual GBool isBinary(GBool last = gTrue) { + return gTrue; + } + virtual GBool isEncoder() { + return gTrue; + } private: - LZWEncoderNode table[4096]; - int nextSeq; - int codeLen; - Guchar inBuf[8192]; - int inBufStart; - int inBufLen; - int outBuf; - int outBufLen; - GBool needEOD; + LZWEncoderNode table[4096]; + int nextSeq; + int codeLen; + Guchar inBuf[8192]; + int inBufStart; + int inBufLen; + int outBuf; + int outBufLen; + GBool needEOD; - void fillBuf(); + void fillBuf(); }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-10026/Function.h b/test/bug-hunting/cve/CVE-2019-10026/Function.h index 5cf45169a..615c2abfd 100644 --- a/test/bug-hunting/cve/CVE-2019-10026/Function.h +++ b/test/bug-hunting/cve/CVE-2019-10026/Function.h @@ -34,64 +34,84 @@ struct PSCode; class Function { public: - Function(); + Function(); - virtual ~Function(); + virtual ~Function(); - // Construct a function. Returns NULL if unsuccessful. - static Function *parse(Object *funcObj, int recursion = 0); + // Construct a function. Returns NULL if unsuccessful. + static Function *parse(Object *funcObj, int recursion = 0); - // Initialize the entries common to all function types. - GBool init(Dict *dict); + // Initialize the entries common to all function types. + GBool init(Dict *dict); - virtual Function *copy() = 0; + virtual Function *copy() = 0; - // Return the function type: - // -1 : identity - // 0 : sampled - // 2 : exponential - // 3 : stitching - // 4 : PostScript - virtual int getType() = 0; + // Return the function type: + // -1 : identity + // 0 : sampled + // 2 : exponential + // 3 : stitching + // 4 : PostScript + virtual int getType() = 0; - // Return size of input and output tuples. - int getInputSize() { return m; } - int getOutputSize() { return n; } + // Return size of input and output tuples. + int getInputSize() { + return m; + } + int getOutputSize() { + return n; + } - double getDomainMin(int i) { return domain[i][0]; } - double getDomainMax(int i) { return domain[i][1]; } - double getRangeMin(int i) { return range[i][0]; } - double getRangeMax(int i) { return range[i][1]; } - GBool getHasRange() { return hasRange; } + double getDomainMin(int i) { + return domain[i][0]; + } + double getDomainMax(int i) { + return domain[i][1]; + } + double getRangeMin(int i) { + return range[i][0]; + } + double getRangeMax(int i) { + return range[i][1]; + } + GBool getHasRange() { + return hasRange; + } - // Transform an input tuple into an output tuple. - virtual void transform(double *in, double *out) = 0; + // Transform an input tuple into an output tuple. + virtual void transform(double *in, double *out) = 0; - virtual GBool isOk() = 0; + virtual GBool isOk() = 0; protected: - int m, n; // size of input and output tuples - double // min and max values for function domain - domain[funcMaxInputs][2]; - double // min and max values for function range - range[funcMaxOutputs][2]; - GBool hasRange; // set if range is defined + int m, n; // size of input and output tuples + double // min and max values for function domain + domain[funcMaxInputs][2]; + double // min and max values for function range + range[funcMaxOutputs][2]; + GBool hasRange; // set if range is defined }; //------------------------------------------------------------------------ // IdentityFunction //------------------------------------------------------------------------ -class IdentityFunction: public Function { +class IdentityFunction : public Function { public: - IdentityFunction(); - virtual ~IdentityFunction(); - virtual Function *copy() { return new IdentityFunction(); } - virtual int getType() { return -1; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return gTrue; } + IdentityFunction(); + virtual ~IdentityFunction(); + virtual Function *copy() { + return new IdentityFunction(); + } + virtual int getType() { + return -1; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return gTrue; + } private: }; @@ -100,137 +120,191 @@ private: // SampledFunction //------------------------------------------------------------------------ -class SampledFunction: public Function { +class SampledFunction : public Function { public: - SampledFunction(Object *funcObj, Dict *dict); - virtual ~SampledFunction(); - virtual Function *copy() { return new SampledFunction(this); } - virtual int getType() { return 0; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + SampledFunction(Object *funcObj, Dict *dict); + virtual ~SampledFunction(); + virtual Function *copy() { + return new SampledFunction(this); + } + virtual int getType() { + return 0; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - int getSampleSize(int i) { return sampleSize[i]; } - double getEncodeMin(int i) { return encode[i][0]; } - double getEncodeMax(int i) { return encode[i][1]; } - double getDecodeMin(int i) { return decode[i][0]; } - double getDecodeMax(int i) { return decode[i][1]; } - double *getSamples() { return samples; } + int getSampleSize(int i) { + return sampleSize[i]; + } + double getEncodeMin(int i) { + return encode[i][0]; + } + double getEncodeMax(int i) { + return encode[i][1]; + } + double getDecodeMin(int i) { + return decode[i][0]; + } + double getDecodeMax(int i) { + return decode[i][1]; + } + double *getSamples() { + return samples; + } private: - SampledFunction(SampledFunction *func); + SampledFunction(SampledFunction *func); - int // number of samples for each domain element - sampleSize[funcMaxInputs]; - double // min and max values for domain encoder - encode[funcMaxInputs][2]; - double // min and max values for range decoder - decode[funcMaxOutputs][2]; - double // input multipliers - inputMul[funcMaxInputs]; - int *idxOffset; - double *samples; // the samples - int nSamples; // size of the samples array - double *sBuf; // buffer for the transform function - double cacheIn[funcMaxInputs]; - double cacheOut[funcMaxOutputs]; - GBool ok; + int // number of samples for each domain element + sampleSize[funcMaxInputs]; + double // min and max values for domain encoder + encode[funcMaxInputs][2]; + double // min and max values for range decoder + decode[funcMaxOutputs][2]; + double // input multipliers + inputMul[funcMaxInputs]; + int *idxOffset; + double *samples; // the samples + int nSamples; // size of the samples array + double *sBuf; // buffer for the transform function + double cacheIn[funcMaxInputs]; + double cacheOut[funcMaxOutputs]; + GBool ok; }; //------------------------------------------------------------------------ // ExponentialFunction //------------------------------------------------------------------------ -class ExponentialFunction: public Function { +class ExponentialFunction : public Function { public: - ExponentialFunction(Object *funcObj, Dict *dict); - virtual ~ExponentialFunction(); - virtual Function *copy() { return new ExponentialFunction(this); } - virtual int getType() { return 2; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + ExponentialFunction(Object *funcObj, Dict *dict); + virtual ~ExponentialFunction(); + virtual Function *copy() { + return new ExponentialFunction(this); + } + virtual int getType() { + return 2; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - double *getC0() { return c0; } - double *getC1() { return c1; } - double getE() { return e; } + double *getC0() { + return c0; + } + double *getC1() { + return c1; + } + double getE() { + return e; + } private: - ExponentialFunction(ExponentialFunction *func); + ExponentialFunction(ExponentialFunction *func); - double c0[funcMaxOutputs]; - double c1[funcMaxOutputs]; - double e; - GBool ok; + double c0[funcMaxOutputs]; + double c1[funcMaxOutputs]; + double e; + GBool ok; }; //------------------------------------------------------------------------ // StitchingFunction //------------------------------------------------------------------------ -class StitchingFunction: public Function { +class StitchingFunction : public Function { public: - StitchingFunction(Object *funcObj, Dict *dict, int recursion); - virtual ~StitchingFunction(); - virtual Function *copy() { return new StitchingFunction(this); } - virtual int getType() { return 3; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + StitchingFunction(Object *funcObj, Dict *dict, int recursion); + virtual ~StitchingFunction(); + virtual Function *copy() { + return new StitchingFunction(this); + } + virtual int getType() { + return 3; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - int getNumFuncs() { return k; } - Function *getFunc(int i) { return funcs[i]; } - double *getBounds() { return bounds; } - double *getEncode() { return encode; } - double *getScale() { return scale; } + int getNumFuncs() { + return k; + } + Function *getFunc(int i) { + return funcs[i]; + } + double *getBounds() { + return bounds; + } + double *getEncode() { + return encode; + } + double *getScale() { + return scale; + } private: - StitchingFunction(StitchingFunction *func); + StitchingFunction(StitchingFunction *func); - int k; - Function **funcs; - double *bounds; - double *encode; - double *scale; - GBool ok; + int k; + Function **funcs; + double *bounds; + double *encode; + double *scale; + GBool ok; }; //------------------------------------------------------------------------ // PostScriptFunction //------------------------------------------------------------------------ -class PostScriptFunction: public Function { +class PostScriptFunction : public Function { public: - PostScriptFunction(Object *funcObj, Dict *dict); - virtual ~PostScriptFunction(); - virtual Function *copy() { return new PostScriptFunction(this); } - virtual int getType() { return 4; } - virtual void transform(double *in, double *out); - virtual GBool isOk() { return ok; } + PostScriptFunction(Object *funcObj, Dict *dict); + virtual ~PostScriptFunction(); + virtual Function *copy() { + return new PostScriptFunction(this); + } + virtual int getType() { + return 4; + } + virtual void transform(double *in, double *out); + virtual GBool isOk() { + return ok; + } - GString *getCodeString() { return codeString; } + GString *getCodeString() { + return codeString; + } private: - PostScriptFunction(PostScriptFunction *func); - GBool parseCode(GList *tokens, int *tokPtr, int *codePtr); - void addCode(int *codePtr, int op); - void addCodeI(int *codePtr, int op, int x); - void addCodeD(int *codePtr, int op, double x); - GString *getToken(Stream *str); - int exec(double *stack, int sp0); + PostScriptFunction(PostScriptFunction *func); + GBool parseCode(GList *tokens, int *tokPtr, int *codePtr); + void addCode(int *codePtr, int op); + void addCodeI(int *codePtr, int op, int x); + void addCodeD(int *codePtr, int op, double x); + GString *getToken(Stream *str); + int exec(double *stack, int sp0); - GString *codeString; - PSCode *code; - int codeLen; - int codeSize; - double cacheIn[funcMaxInputs]; - double cacheOut[funcMaxOutputs]; - GBool ok; + GString *codeString; + PSCode *code; + int codeLen; + int codeSize; + double cacheIn[funcMaxInputs]; + double cacheOut[funcMaxOutputs]; + GBool ok; }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-1010315/dsdiff.c b/test/bug-hunting/cve/CVE-2019-1010315/dsdiff.c index 0ac43212e..2fe6aa6e5 100644 --- a/test/bug-hunting/cve/CVE-2019-1010315/dsdiff.c +++ b/test/bug-hunting/cve/CVE-2019-1010315/dsdiff.c @@ -34,38 +34,38 @@ extern int debug_logging_mode; #pragma pack(push,2) typedef struct { - char ckID [4]; + char ckID[4]; int64_t ckDataSize; } DFFChunkHeader; typedef struct { - char ckID [4]; + char ckID[4]; int64_t ckDataSize; - char formType [4]; + char formType[4]; } DFFFileHeader; typedef struct { - char ckID [4]; + char ckID[4]; int64_t ckDataSize; uint32_t version; } DFFVersionChunk; typedef struct { - char ckID [4]; + char ckID[4]; int64_t ckDataSize; uint32_t sampleRate; } DFFSampleRateChunk; typedef struct { - char ckID [4]; + char ckID[4]; int64_t ckDataSize; uint16_t numChannels; } DFFChannelsHeader; typedef struct { - char ckID [4]; + char ckID[4]; int64_t ckDataSize; - char compressionType [4]; + char compressionType[4]; } DFFCompressionHeader; #pragma pack(pop) @@ -88,14 +88,14 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa memcpy (&dff_file_header, fourcc, 4); if ((!DoReadFile (infile, ((char *) &dff_file_header) + 4, sizeof (DFFFileHeader) - 4, &bcount) || - bcount != sizeof (DFFFileHeader) - 4) || strncmp (dff_file_header.formType, "DSD ", 4)) { - error_line ("%s is not a valid .DFF file!", infilename); - return WAVPACK_SOFT_ERROR; + bcount != sizeof (DFFFileHeader) - 4) || strncmp (dff_file_header.formType, "DSD ", 4)) { + error_line ("%s is not a valid .DFF file!", infilename); + return WAVPACK_SOFT_ERROR; } else if (!(config->qmode & QMODE_NO_STORE_WRAPPER) && - !WavpackAddWrapper (wpc, &dff_file_header, sizeof (DFFFileHeader))) { - error_line ("%s", WavpackGetErrorMessage (wpc)); - return WAVPACK_SOFT_ERROR; + !WavpackAddWrapper (wpc, &dff_file_header, sizeof (DFFFileHeader))) { + error_line ("%s", WavpackGetErrorMessage (wpc)); + return WAVPACK_SOFT_ERROR; } #if 1 // this might be a little too picky... @@ -103,8 +103,8 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa if (infilesize && !(config->qmode & QMODE_IGNORE_LENGTH) && dff_file_header.ckDataSize && dff_file_header.ckDataSize + 1 && dff_file_header.ckDataSize + 12 != infilesize) { - error_line ("%s is not a valid .DFF file (by total size)!", infilename); - return WAVPACK_SOFT_ERROR; + error_line ("%s is not a valid .DFF file (by total size)!", infilename); + return WAVPACK_SOFT_ERROR; } if (debug_logging_mode) @@ -118,13 +118,13 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa while (1) { if (!DoReadFile (infile, &dff_chunk_header, sizeof (DFFChunkHeader), &bcount) || bcount != sizeof (DFFChunkHeader)) { - error_line ("%s is not a valid .DFF file!", infilename); - return WAVPACK_SOFT_ERROR; + error_line ("%s is not a valid .DFF file!", infilename); + return WAVPACK_SOFT_ERROR; } else if (!(config->qmode & QMODE_NO_STORE_WRAPPER) && - !WavpackAddWrapper (wpc, &dff_chunk_header, sizeof (DFFChunkHeader))) { - error_line ("%s", WavpackGetErrorMessage (wpc)); - return WAVPACK_SOFT_ERROR; + !WavpackAddWrapper (wpc, &dff_chunk_header, sizeof (DFFChunkHeader))) { + error_line ("%s", WavpackGetErrorMessage (wpc)); + return WAVPACK_SOFT_ERROR; } WavpackBigEndianToNative (&dff_chunk_header, DFFChunkHeaderFormat); @@ -138,13 +138,13 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa if (dff_chunk_header.ckDataSize != sizeof (version) || !DoReadFile (infile, &version, sizeof (version), &bcount) || bcount != sizeof (version)) { - error_line ("%s is not a valid .DFF file!", infilename); - return WAVPACK_SOFT_ERROR; + error_line ("%s is not a valid .DFF file!", infilename); + return WAVPACK_SOFT_ERROR; } else if (!(config->qmode & QMODE_NO_STORE_WRAPPER) && - !WavpackAddWrapper (wpc, &version, sizeof (version))) { - error_line ("%s", WavpackGetErrorMessage (wpc)); - return WAVPACK_SOFT_ERROR; + !WavpackAddWrapper (wpc, &version, sizeof (version))) { + error_line ("%s", WavpackGetErrorMessage (wpc)); + return WAVPACK_SOFT_ERROR; } WavpackBigEndianToNative (&version, "L"); @@ -167,15 +167,15 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa if (!DoReadFile (infile, prop_chunk, (uint32_t) dff_chunk_header.ckDataSize, &bcount) || bcount != dff_chunk_header.ckDataSize) { - error_line ("%s is not a valid .DFF file!", infilename); - free (prop_chunk); - return WAVPACK_SOFT_ERROR; + error_line ("%s is not a valid .DFF file!", infilename); + free (prop_chunk); + return WAVPACK_SOFT_ERROR; } else if (!(config->qmode & QMODE_NO_STORE_WRAPPER) && - !WavpackAddWrapper (wpc, prop_chunk, (uint32_t) dff_chunk_header.ckDataSize)) { - error_line ("%s", WavpackGetErrorMessage (wpc)); - free (prop_chunk); - return WAVPACK_SOFT_ERROR; + !WavpackAddWrapper (wpc, prop_chunk, (uint32_t) dff_chunk_header.ckDataSize)) { + error_line ("%s", WavpackGetErrorMessage (wpc)); + free (prop_chunk); + return WAVPACK_SOFT_ERROR; } if (!strncmp (prop_chunk, "SND ", 4)) { @@ -224,8 +224,8 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa else if (!strncmp (cptr, "LFE ", 4)) chanMask |= 0x8; else - if (debug_logging_mode) - error_line ("undefined channel ID %c%c%c%c", cptr [0], cptr [1], cptr [2], cptr [3]); + if (debug_logging_mode) + error_line ("undefined channel ID %c%c%c%c", cptr [0], cptr [1], cptr [2], cptr [3]); cptr += 4; } @@ -236,7 +236,7 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa else if (!strncmp (dff_chunk_header.ckID, "CMPR", 4) && dff_chunk_header.ckDataSize >= 4) { if (strncmp (cptr, "DSD ", 4)) { error_line ("DSDIFF files must be uncompressed, not \"%c%c%c%c\"!", - cptr [0], cptr [1], cptr [2], cptr [3]); + cptr [0], cptr [1], cptr [2], cptr [3]); free (prop_chunk); return WAVPACK_SOFT_ERROR; } @@ -246,7 +246,7 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa else { if (debug_logging_mode) error_line ("got PROP/SND chunk type \"%c%c%c%c\" of %d bytes", dff_chunk_header.ckID [0], - dff_chunk_header.ckID [1], dff_chunk_header.ckID [2], dff_chunk_header.ckID [3], dff_chunk_header.ckDataSize); + dff_chunk_header.ckID [1], dff_chunk_header.ckID [2], dff_chunk_header.ckID [3], dff_chunk_header.ckDataSize); cptr += dff_chunk_header.ckDataSize; } @@ -274,7 +274,7 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa } else if (debug_logging_mode) error_line ("got unknown PROP chunk type \"%c%c%c%c\" of %d bytes", - prop_chunk [0], prop_chunk [1], prop_chunk [2], prop_chunk [3], dff_chunk_header.ckDataSize); + prop_chunk [0], prop_chunk [1], prop_chunk [2], prop_chunk [3], dff_chunk_header.ckDataSize); free (prop_chunk); } @@ -296,16 +296,16 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa if (debug_logging_mode) error_line ("extra unknown chunk \"%c%c%c%c\" of %d bytes", - dff_chunk_header.ckID [0], dff_chunk_header.ckID [1], dff_chunk_header.ckID [2], - dff_chunk_header.ckID [3], dff_chunk_header.ckDataSize); + dff_chunk_header.ckID [0], dff_chunk_header.ckID [1], dff_chunk_header.ckID [2], + dff_chunk_header.ckID [3], dff_chunk_header.ckDataSize); if (!DoReadFile (infile, buff, bytes_to_copy, &bcount) || bcount != bytes_to_copy || (!(config->qmode & QMODE_NO_STORE_WRAPPER) && - !WavpackAddWrapper (wpc, buff, bytes_to_copy))) { - error_line ("%s", WavpackGetErrorMessage (wpc)); - free (buff); - return WAVPACK_SOFT_ERROR; + !WavpackAddWrapper (wpc, buff, bytes_to_copy))) { + error_line ("%s", WavpackGetErrorMessage (wpc)); + free (buff); + return WAVPACK_SOFT_ERROR; } free (buff); @@ -340,7 +340,7 @@ int WriteDsdiffHeader (FILE *outfile, WavpackContext *wpc, int64_t total_samples if (debug_logging_mode) error_line ("WriteDsdiffHeader (), total samples = %lld, qmode = 0x%02x\n", - (long long) total_samples, qmode); + (long long) total_samples, qmode); cmpr_name_size = (strlen (cmpr_name) + 1) & ~1; chan_ids_size = num_channels * 4; @@ -432,9 +432,9 @@ int WriteDsdiffHeader (FILE *outfile, WavpackContext *wpc, int64_t total_samples !DoWriteFile (outfile, &cmpr_header, sizeof (cmpr_header), &bcount) || bcount != sizeof (cmpr_header) || !DoWriteFile (outfile, cmpr_name, cmpr_name_size, &bcount) || bcount != cmpr_name_size || !DoWriteFile (outfile, &data_header, sizeof (data_header), &bcount) || bcount != sizeof (data_header)) { - error_line ("can't write .DSF data, disk probably full!"); - free (chan_ids); - return FALSE; + error_line ("can't write .DSF data, disk probably full!"); + free (chan_ids); + return FALSE; } free (chan_ids); diff --git a/test/bug-hunting/cve/CVE-2019-12977/jp2.c b/test/bug-hunting/cve/CVE-2019-12977/jp2.c index d4d68ab51..911f705b1 100644 --- a/test/bug-hunting/cve/CVE-2019-12977/jp2.c +++ b/test/bug-hunting/cve/CVE-2019-12977/jp2.c @@ -1,44 +1,44 @@ /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% JJJ PPPP 222 % -% J P P 2 2 % -% J PPPP 22 % -% J J P 2 % -% JJ P 22222 % -% % -% % -% Read/Write JPEG-2000 Image Format % -% % -% Cristy % -% Nathan Brown % -% June 2001 % -% % -% % -% Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % -% dedicated to making software imaging solutions freely available. % -% % -% You may not use this file except in compliance with the License. You may % -% obtain a copy of the License at % -% % -% https://imagemagick.org/script/license.php % -% % -% Unless required by applicable law or agreed to in writing, software % -% distributed under the License is distributed on an "AS IS" BASIS, % -% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % -% See the License for the specific language governing permissions and % -% limitations under the License. % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% -*/ - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % JJJ PPPP 222 % + % J P P 2 2 % + % J PPPP 22 % + % J J P 2 % + % JJ P 22222 % + % % + % % + % Read/Write JPEG-2000 Image Format % + % % + % Cristy % + % Nathan Brown % + % June 2001 % + % % + % % + % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % + % dedicated to making software imaging solutions freely available. % + % % + % You may not use this file except in compliance with the License. You may % + % obtain a copy of the License at % + % % + % https://imagemagick.org/script/license.php % + % % + % Unless required by applicable law or agreed to in writing, software % + % distributed under the License is distributed on an "AS IS" BASIS, % + % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % + % See the License for the specific language governing permissions and % + % limitations under the License. % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % + */ + /* - Include declarations. -*/ + Include declarations. + */ #include "MagickCore/studio.h" #include "MagickCore/artifact.h" #include "MagickCore/attribute.h" @@ -73,1034 +73,1034 @@ #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) #include #endif - + /* - Forward declarations. -*/ + Forward declarations. + */ #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) static MagickBooleanType - WriteJP2Image(const ImageInfo *,Image *,ExceptionInfo *); +WriteJP2Image(const ImageInfo *,Image *,ExceptionInfo *); #endif - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% I s J 2 K % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% IsJ2K() returns MagickTrue if the image format type, identified by the -% magick string, is J2K. -% -% The format of the IsJ2K method is: -% -% MagickBooleanType IsJ2K(const unsigned char *magick,const size_t length) -% -% A description of each parameter follows: -% -% o magick: compare image format pattern against these bytes. -% -% o length: Specifies the length of the magick string. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % I s J 2 K % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % IsJ2K() returns MagickTrue if the image format type, identified by the + % magick string, is J2K. + % + % The format of the IsJ2K method is: + % + % MagickBooleanType IsJ2K(const unsigned char *magick,const size_t length) + % + % A description of each parameter follows: + % + % o magick: compare image format pattern against these bytes. + % + % o length: Specifies the length of the magick string. + % + */ static MagickBooleanType IsJ2K(const unsigned char *magick,const size_t length) { - if (length < 4) + if (length < 4) + return(MagickFalse); + if (memcmp(magick,"\xff\x4f\xff\x51",4) == 0) + return(MagickTrue); return(MagickFalse); - if (memcmp(magick,"\xff\x4f\xff\x51",4) == 0) - return(MagickTrue); - return(MagickFalse); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% I s J P 2 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% IsJP2() returns MagickTrue if the image format type, identified by the -% magick string, is JP2. -% -% The format of the IsJP2 method is: -% -% MagickBooleanType IsJP2(const unsigned char *magick,const size_t length) -% -% A description of each parameter follows: -% -% o magick: compare image format pattern against these bytes. -% -% o length: Specifies the length of the magick string. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % I s J P 2 % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % IsJP2() returns MagickTrue if the image format type, identified by the + % magick string, is JP2. + % + % The format of the IsJP2 method is: + % + % MagickBooleanType IsJP2(const unsigned char *magick,const size_t length) + % + % A description of each parameter follows: + % + % o magick: compare image format pattern against these bytes. + % + % o length: Specifies the length of the magick string. + % + */ static MagickBooleanType IsJP2(const unsigned char *magick,const size_t length) { - if (length < 4) + if (length < 4) + return(MagickFalse); + if (memcmp(magick,"\x0d\x0a\x87\x0a",4) == 0) + return(MagickTrue); + if (length < 12) + return(MagickFalse); + if (memcmp(magick,"\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a",12) == 0) + return(MagickTrue); return(MagickFalse); - if (memcmp(magick,"\x0d\x0a\x87\x0a",4) == 0) - return(MagickTrue); - if (length < 12) - return(MagickFalse); - if (memcmp(magick,"\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a",12) == 0) - return(MagickTrue); - return(MagickFalse); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% R e a d J P 2 I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% ReadJP2Image() reads a JPEG 2000 Image file (JP2) or JPEG 2000 -% codestream (JPC) image file and returns it. It allocates the memory -% necessary for the new Image structure and returns a pointer to the new -% image or set of images. -% -% JP2 support is originally written by Nathan Brown, nathanbrown@letu.edu. -% -% The format of the ReadJP2Image method is: -% -% Image *ReadJP2Image(const ImageInfo *image_info, -% ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image_info: the image info. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % R e a d J P 2 I m a g e % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % ReadJP2Image() reads a JPEG 2000 Image file (JP2) or JPEG 2000 + % codestream (JPC) image file and returns it. It allocates the memory + % necessary for the new Image structure and returns a pointer to the new + % image or set of images. + % + % JP2 support is originally written by Nathan Brown, nathanbrown@letu.edu. + % + % The format of the ReadJP2Image method is: + % + % Image *ReadJP2Image(const ImageInfo *image_info, + % ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image_info: the image info. + % + % o exception: return any errors or warnings in this structure. + % + */ #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) static void JP2ErrorHandler(const char *message,void *client_data) { - ExceptionInfo + ExceptionInfo *exception; - exception=(ExceptionInfo *) client_data; - (void) ThrowMagickException(exception,GetMagickModule(),CoderError, - message,"`%s'","OpenJP2"); + exception=(ExceptionInfo *) client_data; + (void) ThrowMagickException(exception,GetMagickModule(),CoderError, + message,"`%s'","OpenJP2"); } static OPJ_SIZE_T JP2ReadHandler(void *buffer,OPJ_SIZE_T length,void *context) { - Image + Image *image; - ssize_t - count; + ssize_t + count; - image=(Image *) context; - count=ReadBlob(image,(ssize_t) length,(unsigned char *) buffer); - if (count == 0) - return((OPJ_SIZE_T) -1); - return((OPJ_SIZE_T) count); + image=(Image *) context; + count=ReadBlob(image,(ssize_t) length,(unsigned char *) buffer); + if (count == 0) + return((OPJ_SIZE_T) -1); + return((OPJ_SIZE_T) count); } static OPJ_BOOL JP2SeekHandler(OPJ_OFF_T offset,void *context) { - Image + Image *image; - image=(Image *) context; - return(SeekBlob(image,offset,SEEK_SET) < 0 ? OPJ_FALSE : OPJ_TRUE); + image=(Image *) context; + return(SeekBlob(image,offset,SEEK_SET) < 0 ? OPJ_FALSE : OPJ_TRUE); } static OPJ_OFF_T JP2SkipHandler(OPJ_OFF_T offset,void *context) { - Image + Image *image; - image=(Image *) context; - return(SeekBlob(image,offset,SEEK_CUR) < 0 ? -1 : offset); + image=(Image *) context; + return(SeekBlob(image,offset,SEEK_CUR) < 0 ? -1 : offset); } static void JP2WarningHandler(const char *message,void *client_data) { - ExceptionInfo + ExceptionInfo *exception; - exception=(ExceptionInfo *) client_data; - (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning, - message,"`%s'","OpenJP2"); + exception=(ExceptionInfo *) client_data; + (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning, + message,"`%s'","OpenJP2"); } static OPJ_SIZE_T JP2WriteHandler(void *buffer,OPJ_SIZE_T length,void *context) { - Image + Image *image; - ssize_t - count; + ssize_t + count; - image=(Image *) context; - count=WriteBlob(image,(ssize_t) length,(unsigned char *) buffer); - return((OPJ_SIZE_T) count); + image=(Image *) context; + count=WriteBlob(image,(ssize_t) length,(unsigned char *) buffer); + return((OPJ_SIZE_T) count); } static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception) { - const char + const char *option; - Image + Image *image; - int - jp2_status; + int + jp2_status; - MagickBooleanType - status; + MagickBooleanType + status; - opj_codec_t + opj_codec_t *jp2_codec; - opj_dparameters_t - parameters; + opj_dparameters_t + parameters; - opj_image_t + opj_image_t *jp2_image; - opj_stream_t + opj_stream_t *jp2_stream; - register ssize_t - i; + register ssize_t + i; - ssize_t - y; + ssize_t + y; - unsigned char - sans[4]; + unsigned char + sans[4]; - /* - Open image file. - */ - assert(image_info != (const ImageInfo *) NULL); - assert(image_info->signature == MagickCoreSignature); - if (image_info->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", - image_info->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - image=AcquireImage(image_info,exception); - status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); - if (status == MagickFalse) + /* + Open image file. + */ + assert(image_info != (const ImageInfo *) NULL); + assert(image_info->signature == MagickCoreSignature); + if (image_info->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", + image_info->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + image=AcquireImage(image_info,exception); + status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); + if (status == MagickFalse) { - image=DestroyImageList(image); - return((Image *) NULL); + image=DestroyImageList(image); + return((Image *) NULL); } - /* - Initialize JP2 codec. - */ - if (ReadBlob(image,4,sans) != 4) + /* + Initialize JP2 codec. + */ + if (ReadBlob(image,4,sans) != 4) { - image=DestroyImageList(image); - return((Image *) NULL); + image=DestroyImageList(image); + return((Image *) NULL); } - (void) SeekBlob(image,SEEK_SET,0); - if (LocaleCompare(image_info->magick,"JPT") == 0) - jp2_codec=opj_create_decompress(OPJ_CODEC_JPT); - else - if (IsJ2K(sans,4) != MagickFalse) - jp2_codec=opj_create_decompress(OPJ_CODEC_J2K); + (void) SeekBlob(image,SEEK_SET,0); + if (LocaleCompare(image_info->magick,"JPT") == 0) + jp2_codec=opj_create_decompress(OPJ_CODEC_JPT); else - jp2_codec=opj_create_decompress(OPJ_CODEC_JP2); - opj_set_warning_handler(jp2_codec,JP2WarningHandler,exception); - opj_set_error_handler(jp2_codec,JP2ErrorHandler,exception); - opj_set_default_decoder_parameters(¶meters); - option=GetImageOption(image_info,"jp2:reduce-factor"); - if (option != (const char *) NULL) - parameters.cp_reduce=StringToInteger(option); - option=GetImageOption(image_info,"jp2:quality-layers"); - if (option != (const char *) NULL) - parameters.cp_layer=StringToInteger(option); - if (opj_setup_decoder(jp2_codec,¶meters) == 0) + if (IsJ2K(sans,4) != MagickFalse) + jp2_codec=opj_create_decompress(OPJ_CODEC_J2K); + else + jp2_codec=opj_create_decompress(OPJ_CODEC_JP2); + opj_set_warning_handler(jp2_codec,JP2WarningHandler,exception); + opj_set_error_handler(jp2_codec,JP2ErrorHandler,exception); + opj_set_default_decoder_parameters(¶meters); + option=GetImageOption(image_info,"jp2:reduce-factor"); + if (option != (const char *) NULL) + parameters.cp_reduce=StringToInteger(option); + option=GetImageOption(image_info,"jp2:quality-layers"); + if (option != (const char *) NULL) + parameters.cp_layer=StringToInteger(option); + if (opj_setup_decoder(jp2_codec,¶meters) == 0) { - opj_destroy_codec(jp2_codec); - ThrowReaderException(DelegateError,"UnableToManageJP2Stream"); + opj_destroy_codec(jp2_codec); + ThrowReaderException(DelegateError,"UnableToManageJP2Stream"); } - jp2_stream=opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE,1); - opj_stream_set_read_function(jp2_stream,JP2ReadHandler); - opj_stream_set_write_function(jp2_stream,JP2WriteHandler); - opj_stream_set_seek_function(jp2_stream,JP2SeekHandler); - opj_stream_set_skip_function(jp2_stream,JP2SkipHandler); - opj_stream_set_user_data(jp2_stream,image,NULL); - opj_stream_set_user_data_length(jp2_stream,GetBlobSize(image)); - if (opj_read_header(jp2_stream,jp2_codec,&jp2_image) == 0) + jp2_stream=opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE,1); + opj_stream_set_read_function(jp2_stream,JP2ReadHandler); + opj_stream_set_write_function(jp2_stream,JP2WriteHandler); + opj_stream_set_seek_function(jp2_stream,JP2SeekHandler); + opj_stream_set_skip_function(jp2_stream,JP2SkipHandler); + opj_stream_set_user_data(jp2_stream,image,NULL); + opj_stream_set_user_data_length(jp2_stream,GetBlobSize(image)); + if (opj_read_header(jp2_stream,jp2_codec,&jp2_image) == 0) { - opj_stream_destroy(jp2_stream); - opj_destroy_codec(jp2_codec); - ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); + opj_stream_destroy(jp2_stream); + opj_destroy_codec(jp2_codec); + ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); } - jp2_status=OPJ_TRUE; - if (image->ping == MagickFalse) + jp2_status=OPJ_TRUE; + if (image->ping == MagickFalse) { - if ((image->columns != 0) && (image->rows != 0)) - /* - Extract an area from the image. - */ - jp2_status=opj_set_decode_area(jp2_codec,jp2_image, - (OPJ_INT32) image->extract_info.x,(OPJ_INT32) image->extract_info.y, - (OPJ_INT32) (image->extract_info.x+(ssize_t) image->columns), - (OPJ_INT32) (image->extract_info.y+(ssize_t) image->rows)); - else - jp2_status=opj_set_decode_area(jp2_codec,jp2_image,0,0, - jp2_image->comps[0].w,jp2_image->comps[0].h); - if (jp2_status == OPJ_FALSE) + if ((image->columns != 0) && (image->rows != 0)) + /* + Extract an area from the image. + */ + jp2_status=opj_set_decode_area(jp2_codec,jp2_image, + (OPJ_INT32) image->extract_info.x,(OPJ_INT32) image->extract_info.y, + (OPJ_INT32) (image->extract_info.x+(ssize_t) image->columns), + (OPJ_INT32) (image->extract_info.y+(ssize_t) image->rows)); + else + jp2_status=opj_set_decode_area(jp2_codec,jp2_image,0,0, + jp2_image->comps[0].w,jp2_image->comps[0].h); + if (jp2_status == OPJ_FALSE) { - opj_stream_destroy(jp2_stream); - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); + opj_stream_destroy(jp2_stream); + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); } } - if ((AcquireMagickResource(WidthResource,(size_t) jp2_image->comps[0].w) == MagickFalse) || - (AcquireMagickResource(HeightResource,(size_t) jp2_image->comps[0].h) == MagickFalse)) + if ((AcquireMagickResource(WidthResource,(size_t) jp2_image->comps[0].w) == MagickFalse) || + (AcquireMagickResource(HeightResource,(size_t) jp2_image->comps[0].h) == MagickFalse)) { - opj_stream_destroy(jp2_stream); - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); - } - if ((image_info->number_scenes != 0) && (image_info->scene != 0)) - jp2_status=opj_get_decoded_tile(jp2_codec,jp2_stream,jp2_image, - (unsigned int) image_info->scene-1); - else - if (image->ping == MagickFalse) - { - jp2_status=opj_decode(jp2_codec,jp2_stream,jp2_image); - if (jp2_status != OPJ_FALSE) - jp2_status=opj_end_decompress(jp2_codec,jp2_stream); - } - if (jp2_status == OPJ_FALSE) - { - opj_stream_destroy(jp2_stream); - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); - } - opj_stream_destroy(jp2_stream); - for (i=0; i < (ssize_t) jp2_image->numcomps; i++) - { - if ((jp2_image->comps[0].dx == 0) || (jp2_image->comps[0].dy == 0) || - (jp2_image->comps[0].prec != jp2_image->comps[i].prec) || - (jp2_image->comps[0].sgnd != jp2_image->comps[i].sgnd) || - ((image->ping == MagickFalse) && (jp2_image->comps[i].data == NULL))) - { + opj_stream_destroy(jp2_stream); opj_destroy_codec(jp2_codec); opj_image_destroy(jp2_image); - ThrowReaderException(CoderError,"IrregularChannelGeometryNotSupported") - } - } - /* - Convert JP2 image. - */ - image->columns=(size_t) jp2_image->comps[0].w; - image->rows=(size_t) jp2_image->comps[0].h; - image->depth=jp2_image->comps[0].prec; - image->compression=JPEG2000Compression; - if (jp2_image->numcomps == 1) - SetImageColorspace(image,GRAYColorspace,exception); - else + ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); + } + if ((image_info->number_scenes != 0) && (image_info->scene != 0)) + jp2_status=opj_get_decoded_tile(jp2_codec,jp2_stream,jp2_image, + (unsigned int) image_info->scene-1); + else + if (image->ping == MagickFalse) + { + jp2_status=opj_decode(jp2_codec,jp2_stream,jp2_image); + if (jp2_status != OPJ_FALSE) + jp2_status=opj_end_decompress(jp2_codec,jp2_stream); + } + if (jp2_status == OPJ_FALSE) + { + opj_stream_destroy(jp2_stream); + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); + } + opj_stream_destroy(jp2_stream); + for (i=0; i < (ssize_t) jp2_image->numcomps; i++) + { + if ((jp2_image->comps[0].dx == 0) || (jp2_image->comps[0].dy == 0) || + (jp2_image->comps[0].prec != jp2_image->comps[i].prec) || + (jp2_image->comps[0].sgnd != jp2_image->comps[i].sgnd) || + ((image->ping == MagickFalse) && (jp2_image->comps[i].data == NULL))) + { + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + ThrowReaderException(CoderError,"IrregularChannelGeometryNotSupported") + } + } + /* + Convert JP2 image. + */ + image->columns=(size_t) jp2_image->comps[0].w; + image->rows=(size_t) jp2_image->comps[0].h; + image->depth=jp2_image->comps[0].prec; + image->compression=JPEG2000Compression; + if (jp2_image->numcomps == 1) + SetImageColorspace(image,GRAYColorspace,exception); + else if (jp2_image->color_space == 2) - { + { SetImageColorspace(image,GRAYColorspace,exception); if (jp2_image->numcomps > 1) - image->alpha_trait=BlendPixelTrait; - } + image->alpha_trait=BlendPixelTrait; + } else - if (jp2_image->color_space == 3) + if (jp2_image->color_space == 3) SetImageColorspace(image,Rec601YCbCrColorspace,exception); - if (jp2_image->numcomps > 3) - image->alpha_trait=BlendPixelTrait; - if (jp2_image->icc_profile_buf != (unsigned char *) NULL) + if (jp2_image->numcomps > 3) + image->alpha_trait=BlendPixelTrait; + if (jp2_image->icc_profile_buf != (unsigned char *) NULL) { - StringInfo + StringInfo *profile; - profile=BlobToStringInfo(jp2_image->icc_profile_buf, - jp2_image->icc_profile_len); - if (profile != (StringInfo *) NULL) + profile=BlobToStringInfo(jp2_image->icc_profile_buf, + jp2_image->icc_profile_len); + if (profile != (StringInfo *) NULL) { - SetImageProfile(image,"icc",profile,exception); - profile=DestroyStringInfo(profile); + SetImageProfile(image,"icc",profile,exception); + profile=DestroyStringInfo(profile); } } - if (image->ping != MagickFalse) + if (image->ping != MagickFalse) { - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - return(GetFirstImageInList(image)); + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + return(GetFirstImageInList(image)); } - status=SetImageExtent(image,image->columns,image->rows,exception); - if (status == MagickFalse) - { - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - return(DestroyImageList(image)); - } - for (y=0; y < (ssize_t) image->rows; y++) - { - register Quantum - *magick_restrict q; - - register ssize_t - x; - - q=GetAuthenticPixels(image,0,y,image->columns,1,exception); - if (q == (Quantum *) NULL) - break; - for (x=0; x < (ssize_t) image->columns; x++) - { - for (i=0; i < (ssize_t) jp2_image->numcomps; i++) - { - double - pixel, - scale; - - scale=QuantumRange/(double) ((1UL << jp2_image->comps[i].prec)-1); - pixel=scale*(jp2_image->comps[i].data[y/jp2_image->comps[i].dy* - image->columns/jp2_image->comps[i].dx+x/jp2_image->comps[i].dx]+ - (jp2_image->comps[i].sgnd ? 1UL << (jp2_image->comps[i].prec-1) : 0)); - switch (i) - { - case 0: - { - if (jp2_image->numcomps == 1) - { - SetPixelGray(image,ClampToQuantum(pixel),q); - SetPixelAlpha(image,OpaqueAlpha,q); - break; - } - SetPixelRed(image,ClampToQuantum(pixel),q); - SetPixelGreen(image,ClampToQuantum(pixel),q); - SetPixelBlue(image,ClampToQuantum(pixel),q); - SetPixelAlpha(image,OpaqueAlpha,q); - break; - } - case 1: - { - if (jp2_image->numcomps == 2) - { - SetPixelAlpha(image,ClampToQuantum(pixel),q); - break; - } - SetPixelGreen(image,ClampToQuantum(pixel),q); - break; - } - case 2: - { - SetPixelBlue(image,ClampToQuantum(pixel),q); - break; - } - case 3: - { - SetPixelAlpha(image,ClampToQuantum(pixel),q); - break; - } - } - } - q+=GetPixelChannels(image); - } - if (SyncAuthenticPixels(image,exception) == MagickFalse) - break; - status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, - image->rows); + status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) - break; - } - /* - Free resources. - */ - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - (void) CloseBlob(image); - if ((image_info->number_scenes != 0) && (image_info->scene != 0)) - AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception)); - return(GetFirstImageInList(image)); + { + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + return(DestroyImageList(image)); + } + for (y=0; y < (ssize_t) image->rows; y++) + { + register Quantum + *magick_restrict q; + + register ssize_t + x; + + q=GetAuthenticPixels(image,0,y,image->columns,1,exception); + if (q == (Quantum *) NULL) + break; + for (x=0; x < (ssize_t) image->columns; x++) + { + for (i=0; i < (ssize_t) jp2_image->numcomps; i++) + { + double + pixel, + scale; + + scale=QuantumRange/(double) ((1UL << jp2_image->comps[i].prec)-1); + pixel=scale*(jp2_image->comps[i].data[y/jp2_image->comps[i].dy* + image->columns/jp2_image->comps[i].dx+x/jp2_image->comps[i].dx]+ + (jp2_image->comps[i].sgnd ? 1UL << (jp2_image->comps[i].prec-1) : 0)); + switch (i) + { + case 0: + { + if (jp2_image->numcomps == 1) + { + SetPixelGray(image,ClampToQuantum(pixel),q); + SetPixelAlpha(image,OpaqueAlpha,q); + break; + } + SetPixelRed(image,ClampToQuantum(pixel),q); + SetPixelGreen(image,ClampToQuantum(pixel),q); + SetPixelBlue(image,ClampToQuantum(pixel),q); + SetPixelAlpha(image,OpaqueAlpha,q); + break; + } + case 1: + { + if (jp2_image->numcomps == 2) + { + SetPixelAlpha(image,ClampToQuantum(pixel),q); + break; + } + SetPixelGreen(image,ClampToQuantum(pixel),q); + break; + } + case 2: + { + SetPixelBlue(image,ClampToQuantum(pixel),q); + break; + } + case 3: + { + SetPixelAlpha(image,ClampToQuantum(pixel),q); + break; + } + } + } + q+=GetPixelChannels(image); + } + if (SyncAuthenticPixels(image,exception) == MagickFalse) + break; + status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, + image->rows); + if (status == MagickFalse) + break; + } + /* + Free resources. + */ + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + (void) CloseBlob(image); + if ((image_info->number_scenes != 0) && (image_info->scene != 0)) + AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception)); + return(GetFirstImageInList(image)); } #endif - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% R e g i s t e r J P 2 I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% RegisterJP2Image() adds attributes for the JP2 image format to the list of -% supported formats. The attributes include the image format tag, a method -% method to read and/or write the format, whether the format supports the -% saving of more than one frame to the same file or blob, whether the format -% supports native in-memory I/O, and a brief description of the format. -% -% The format of the RegisterJP2Image method is: -% -% size_t RegisterJP2Image(void) -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % R e g i s t e r J P 2 I m a g e % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % RegisterJP2Image() adds attributes for the JP2 image format to the list of + % supported formats. The attributes include the image format tag, a method + % method to read and/or write the format, whether the format supports the + % saving of more than one frame to the same file or blob, whether the format + % supports native in-memory I/O, and a brief description of the format. + % + % The format of the RegisterJP2Image method is: + % + % size_t RegisterJP2Image(void) + % + */ ModuleExport size_t RegisterJP2Image(void) { - char - version[MagickPathExtent]; + char + version[MagickPathExtent]; - MagickInfo + MagickInfo *entry; - *version='\0'; + *version='\0'; #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) - (void) FormatLocaleString(version,MagickPathExtent,"%s",opj_version()); + (void) FormatLocaleString(version,MagickPathExtent,"%s",opj_version()); #endif - entry=AcquireMagickInfo("JP2","JP2","JPEG-2000 File Format Syntax"); - if (*version != '\0') - entry->version=ConstantString(version); - entry->mime_type=ConstantString("image/jp2"); - entry->magick=(IsImageFormatHandler *) IsJP2; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->flags|=CoderEncoderSeekableStreamFlag; + entry=AcquireMagickInfo("JP2","JP2","JPEG-2000 File Format Syntax"); + if (*version != '\0') + entry->version=ConstantString(version); + entry->mime_type=ConstantString("image/jp2"); + entry->magick=(IsImageFormatHandler *) IsJP2; + entry->flags^=CoderAdjoinFlag; + entry->flags|=CoderDecoderSeekableStreamFlag; + entry->flags|=CoderEncoderSeekableStreamFlag; #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) - entry->decoder=(DecodeImageHandler *) ReadJP2Image; - entry->encoder=(EncodeImageHandler *) WriteJP2Image; + entry->decoder=(DecodeImageHandler *) ReadJP2Image; + entry->encoder=(EncodeImageHandler *) WriteJP2Image; #endif - (void) RegisterMagickInfo(entry); - entry=AcquireMagickInfo("JP2","J2C","JPEG-2000 Code Stream Syntax"); - if (*version != '\0') - entry->version=ConstantString(version); - entry->mime_type=ConstantString("image/jp2"); - entry->magick=(IsImageFormatHandler *) IsJ2K; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->flags|=CoderEncoderSeekableStreamFlag; + (void) RegisterMagickInfo(entry); + entry=AcquireMagickInfo("JP2","J2C","JPEG-2000 Code Stream Syntax"); + if (*version != '\0') + entry->version=ConstantString(version); + entry->mime_type=ConstantString("image/jp2"); + entry->magick=(IsImageFormatHandler *) IsJ2K; + entry->flags^=CoderAdjoinFlag; + entry->flags|=CoderDecoderSeekableStreamFlag; + entry->flags|=CoderEncoderSeekableStreamFlag; #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) - entry->decoder=(DecodeImageHandler *) ReadJP2Image; - entry->encoder=(EncodeImageHandler *) WriteJP2Image; + entry->decoder=(DecodeImageHandler *) ReadJP2Image; + entry->encoder=(EncodeImageHandler *) WriteJP2Image; #endif - (void) RegisterMagickInfo(entry); - entry=AcquireMagickInfo("JP2","J2K","JPEG-2000 Code Stream Syntax"); - if (*version != '\0') - entry->version=ConstantString(version); - entry->mime_type=ConstantString("image/jp2"); - entry->magick=(IsImageFormatHandler *) IsJ2K; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->flags|=CoderEncoderSeekableStreamFlag; + (void) RegisterMagickInfo(entry); + entry=AcquireMagickInfo("JP2","J2K","JPEG-2000 Code Stream Syntax"); + if (*version != '\0') + entry->version=ConstantString(version); + entry->mime_type=ConstantString("image/jp2"); + entry->magick=(IsImageFormatHandler *) IsJ2K; + entry->flags^=CoderAdjoinFlag; + entry->flags|=CoderDecoderSeekableStreamFlag; + entry->flags|=CoderEncoderSeekableStreamFlag; #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) - entry->decoder=(DecodeImageHandler *) ReadJP2Image; - entry->encoder=(EncodeImageHandler *) WriteJP2Image; + entry->decoder=(DecodeImageHandler *) ReadJP2Image; + entry->encoder=(EncodeImageHandler *) WriteJP2Image; #endif - (void) RegisterMagickInfo(entry); - entry=AcquireMagickInfo("JP2","JPM","JPEG-2000 File Format Syntax"); - if (*version != '\0') - entry->version=ConstantString(version); - entry->mime_type=ConstantString("image/jp2"); - entry->magick=(IsImageFormatHandler *) IsJP2; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->flags|=CoderEncoderSeekableStreamFlag; + (void) RegisterMagickInfo(entry); + entry=AcquireMagickInfo("JP2","JPM","JPEG-2000 File Format Syntax"); + if (*version != '\0') + entry->version=ConstantString(version); + entry->mime_type=ConstantString("image/jp2"); + entry->magick=(IsImageFormatHandler *) IsJP2; + entry->flags^=CoderAdjoinFlag; + entry->flags|=CoderDecoderSeekableStreamFlag; + entry->flags|=CoderEncoderSeekableStreamFlag; #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) - entry->decoder=(DecodeImageHandler *) ReadJP2Image; - entry->encoder=(EncodeImageHandler *) WriteJP2Image; + entry->decoder=(DecodeImageHandler *) ReadJP2Image; + entry->encoder=(EncodeImageHandler *) WriteJP2Image; #endif - (void) RegisterMagickInfo(entry); - entry=AcquireMagickInfo("JP2","JPT","JPEG-2000 File Format Syntax"); - if (*version != '\0') - entry->version=ConstantString(version); - entry->mime_type=ConstantString("image/jp2"); - entry->magick=(IsImageFormatHandler *) IsJP2; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->flags|=CoderEncoderSeekableStreamFlag; + (void) RegisterMagickInfo(entry); + entry=AcquireMagickInfo("JP2","JPT","JPEG-2000 File Format Syntax"); + if (*version != '\0') + entry->version=ConstantString(version); + entry->mime_type=ConstantString("image/jp2"); + entry->magick=(IsImageFormatHandler *) IsJP2; + entry->flags^=CoderAdjoinFlag; + entry->flags|=CoderDecoderSeekableStreamFlag; + entry->flags|=CoderEncoderSeekableStreamFlag; #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) - entry->decoder=(DecodeImageHandler *) ReadJP2Image; - entry->encoder=(EncodeImageHandler *) WriteJP2Image; + entry->decoder=(DecodeImageHandler *) ReadJP2Image; + entry->encoder=(EncodeImageHandler *) WriteJP2Image; #endif - (void) RegisterMagickInfo(entry); - entry=AcquireMagickInfo("JP2","JPC","JPEG-2000 Code Stream Syntax"); - if (*version != '\0') - entry->version=ConstantString(version); - entry->mime_type=ConstantString("image/jp2"); - entry->magick=(IsImageFormatHandler *) IsJP2; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->flags|=CoderEncoderSeekableStreamFlag; + (void) RegisterMagickInfo(entry); + entry=AcquireMagickInfo("JP2","JPC","JPEG-2000 Code Stream Syntax"); + if (*version != '\0') + entry->version=ConstantString(version); + entry->mime_type=ConstantString("image/jp2"); + entry->magick=(IsImageFormatHandler *) IsJP2; + entry->flags^=CoderAdjoinFlag; + entry->flags|=CoderDecoderSeekableStreamFlag; + entry->flags|=CoderEncoderSeekableStreamFlag; #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) - entry->decoder=(DecodeImageHandler *) ReadJP2Image; - entry->encoder=(EncodeImageHandler *) WriteJP2Image; + entry->decoder=(DecodeImageHandler *) ReadJP2Image; + entry->encoder=(EncodeImageHandler *) WriteJP2Image; #endif - (void) RegisterMagickInfo(entry); - return(MagickImageCoderSignature); + (void) RegisterMagickInfo(entry); + return(MagickImageCoderSignature); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% U n r e g i s t e r J P 2 I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% UnregisterJP2Image() removes format registrations made by the JP2 module -% from the list of supported formats. -% -% The format of the UnregisterJP2Image method is: -% -% UnregisterJP2Image(void) -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % U n r e g i s t e r J P 2 I m a g e % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % UnregisterJP2Image() removes format registrations made by the JP2 module + % from the list of supported formats. + % + % The format of the UnregisterJP2Image method is: + % + % UnregisterJP2Image(void) + % + */ ModuleExport void UnregisterJP2Image(void) { - (void) UnregisterMagickInfo("JPC"); - (void) UnregisterMagickInfo("JPT"); - (void) UnregisterMagickInfo("JPM"); - (void) UnregisterMagickInfo("JP2"); - (void) UnregisterMagickInfo("J2K"); + (void) UnregisterMagickInfo("JPC"); + (void) UnregisterMagickInfo("JPT"); + (void) UnregisterMagickInfo("JPM"); + (void) UnregisterMagickInfo("JP2"); + (void) UnregisterMagickInfo("J2K"); } - + #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE) /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% W r i t e J P 2 I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% WriteJP2Image() writes an image in the JPEG 2000 image format. -% -% JP2 support originally written by Nathan Brown, nathanbrown@letu.edu -% -% The format of the WriteJP2Image method is: -% -% MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image, -% ExceptionInfo *exception) -% -% A description of each parameter follows. -% -% o image_info: the image info. -% -% o image: The image. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % W r i t e J P 2 I m a g e % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % WriteJP2Image() writes an image in the JPEG 2000 image format. + % + % JP2 support originally written by Nathan Brown, nathanbrown@letu.edu + % + % The format of the WriteJP2Image method is: + % + % MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image, + % ExceptionInfo *exception) + % + % A description of each parameter follows. + % + % o image_info: the image info. + % + % o image: The image. + % + */ static void CinemaProfileCompliance(const opj_image_t *jp2_image, - opj_cparameters_t *parameters) + opj_cparameters_t *parameters) { - /* - Digital Cinema 4K profile compliant codestream. - */ - parameters->tile_size_on=OPJ_FALSE; - parameters->cp_tdx=1; - parameters->cp_tdy=1; - parameters->tp_flag='C'; - parameters->tp_on=1; - parameters->cp_tx0=0; - parameters->cp_ty0=0; - parameters->image_offset_x0=0; - parameters->image_offset_y0=0; - parameters->cblockw_init=32; - parameters->cblockh_init=32; - parameters->csty|=0x01; - parameters->prog_order=OPJ_CPRL; - parameters->roi_compno=(-1); - parameters->subsampling_dx=1; - parameters->subsampling_dy=1; - parameters->irreversible=1; - if ((jp2_image->comps[0].w == 2048) || (jp2_image->comps[0].h == 1080)) + /* + Digital Cinema 4K profile compliant codestream. + */ + parameters->tile_size_on=OPJ_FALSE; + parameters->cp_tdx=1; + parameters->cp_tdy=1; + parameters->tp_flag='C'; + parameters->tp_on=1; + parameters->cp_tx0=0; + parameters->cp_ty0=0; + parameters->image_offset_x0=0; + parameters->image_offset_y0=0; + parameters->cblockw_init=32; + parameters->cblockh_init=32; + parameters->csty|=0x01; + parameters->prog_order=OPJ_CPRL; + parameters->roi_compno=(-1); + parameters->subsampling_dx=1; + parameters->subsampling_dy=1; + parameters->irreversible=1; + if ((jp2_image->comps[0].w == 2048) || (jp2_image->comps[0].h == 1080)) { - /* - Digital Cinema 2K. - */ - parameters->cp_cinema=OPJ_CINEMA2K_24; - parameters->cp_rsiz=OPJ_CINEMA2K; - parameters->max_comp_size=1041666; - if (parameters->numresolution > 6) - parameters->numresolution=6; + /* + Digital Cinema 2K. + */ + parameters->cp_cinema=OPJ_CINEMA2K_24; + parameters->cp_rsiz=OPJ_CINEMA2K; + parameters->max_comp_size=1041666; + if (parameters->numresolution > 6) + parameters->numresolution=6; } - if ((jp2_image->comps[0].w == 4096) || (jp2_image->comps[0].h == 2160)) + if ((jp2_image->comps[0].w == 4096) || (jp2_image->comps[0].h == 2160)) { - /* - Digital Cinema 4K. - */ - parameters->cp_cinema=OPJ_CINEMA4K_24; - parameters->cp_rsiz=OPJ_CINEMA4K; - parameters->max_comp_size=1041666; - if (parameters->numresolution < 1) - parameters->numresolution=1; - if (parameters->numresolution > 7) - parameters->numresolution=7; - parameters->numpocs=2; - parameters->POC[0].tile=1; - parameters->POC[0].resno0=0; - parameters->POC[0].compno0=0; - parameters->POC[0].layno1=1; - parameters->POC[0].resno1=parameters->numresolution-1; - parameters->POC[0].compno1=3; - parameters->POC[0].prg1=OPJ_CPRL; - parameters->POC[1].tile=1; - parameters->POC[1].resno0=parameters->numresolution-1; - parameters->POC[1].compno0=0; - parameters->POC[1].layno1=1; - parameters->POC[1].resno1=parameters->numresolution; - parameters->POC[1].compno1=3; - parameters->POC[1].prg1=OPJ_CPRL; + /* + Digital Cinema 4K. + */ + parameters->cp_cinema=OPJ_CINEMA4K_24; + parameters->cp_rsiz=OPJ_CINEMA4K; + parameters->max_comp_size=1041666; + if (parameters->numresolution < 1) + parameters->numresolution=1; + if (parameters->numresolution > 7) + parameters->numresolution=7; + parameters->numpocs=2; + parameters->POC[0].tile=1; + parameters->POC[0].resno0=0; + parameters->POC[0].compno0=0; + parameters->POC[0].layno1=1; + parameters->POC[0].resno1=parameters->numresolution-1; + parameters->POC[0].compno1=3; + parameters->POC[0].prg1=OPJ_CPRL; + parameters->POC[1].tile=1; + parameters->POC[1].resno0=parameters->numresolution-1; + parameters->POC[1].compno0=0; + parameters->POC[1].layno1=1; + parameters->POC[1].resno1=parameters->numresolution; + parameters->POC[1].compno1=3; + parameters->POC[1].prg1=OPJ_CPRL; } - parameters->tcp_numlayers=1; - parameters->tcp_rates[0]=((float) (jp2_image->numcomps*jp2_image->comps[0].w* - jp2_image->comps[0].h*jp2_image->comps[0].prec))/(parameters->max_comp_size* - 8*jp2_image->comps[0].dx*jp2_image->comps[0].dy); - parameters->cp_disto_alloc=1; + parameters->tcp_numlayers=1; + parameters->tcp_rates[0]=((float) (jp2_image->numcomps*jp2_image->comps[0].w* + jp2_image->comps[0].h*jp2_image->comps[0].prec))/(parameters->max_comp_size* + 8*jp2_image->comps[0].dx*jp2_image->comps[0].dy); + parameters->cp_disto_alloc=1; } static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image, - ExceptionInfo *exception) + ExceptionInfo *exception) { - const char + const char *option, *property; - int - jp2_status; + int + jp2_status; - MagickBooleanType - status; + MagickBooleanType + status; - opj_codec_t + opj_codec_t *jp2_codec; - OPJ_COLOR_SPACE - jp2_colorspace; + OPJ_COLOR_SPACE + jp2_colorspace; - opj_cparameters_t - parameters; + opj_cparameters_t + parameters; - opj_image_cmptparm_t - jp2_info[5]; + opj_image_cmptparm_t + jp2_info[5]; - opj_image_t + opj_image_t *jp2_image; - opj_stream_t + opj_stream_t *jp2_stream; - register ssize_t - i; - - ssize_t - y; - - unsigned int - channels; - - /* - Open image file. - */ - assert(image_info != (const ImageInfo *) NULL); - assert(image_info->signature == MagickCoreSignature); - assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); - if (status == MagickFalse) - return(status); - /* - Initialize JPEG 2000 API. - */ - opj_set_default_encoder_parameters(¶meters); - for (i=1; i < 6; i++) - if (((size_t) (1UL << (i+2)) > image->columns) && - ((size_t) (1UL << (i+2)) > image->rows)) - break; - parameters.numresolution=i; - option=GetImageOption(image_info,"jp2:number-resolutions"); - if (option != (const char *) NULL) - parameters.numresolution=StringToInteger(option); - parameters.tcp_numlayers=1; - parameters.tcp_rates[0]=0; /* lossless */ - parameters.cp_disto_alloc=1; - if ((image_info->quality != 0) && (image_info->quality != 100)) - { - parameters.tcp_distoratio[0]=(double) image_info->quality; - parameters.cp_fixed_quality=OPJ_TRUE; - } - if (image_info->extract != (char *) NULL) - { - RectangleInfo - geometry; - - int - flags; - - /* - Set tile size. - */ - flags=ParseAbsoluteGeometry(image_info->extract,&geometry); - parameters.cp_tdx=(int) geometry.width; - parameters.cp_tdy=(int) geometry.width; - if ((flags & HeightValue) != 0) - parameters.cp_tdy=(int) geometry.height; - if ((flags & XValue) != 0) - parameters.cp_tx0=geometry.x; - if ((flags & YValue) != 0) - parameters.cp_ty0=geometry.y; - parameters.tile_size_on=OPJ_TRUE; - } - option=GetImageOption(image_info,"jp2:quality"); - if (option != (const char *) NULL) - { - register const char - *p; - - /* - Set quality PSNR. - */ - p=option; - for (i=0; sscanf(p,"%f",¶meters.tcp_distoratio[i]) == 1; i++) - { - if (i > 100) - break; - while ((*p != '\0') && (*p != ',')) - p++; - if (*p == '\0') - break; - p++; - } - parameters.tcp_numlayers=i+1; - parameters.cp_fixed_quality=OPJ_TRUE; - } - option=GetImageOption(image_info,"jp2:progression-order"); - if (option != (const char *) NULL) - { - if (LocaleCompare(option,"LRCP") == 0) - parameters.prog_order=OPJ_LRCP; - if (LocaleCompare(option,"RLCP") == 0) - parameters.prog_order=OPJ_RLCP; - if (LocaleCompare(option,"RPCL") == 0) - parameters.prog_order=OPJ_RPCL; - if (LocaleCompare(option,"PCRL") == 0) - parameters.prog_order=OPJ_PCRL; - if (LocaleCompare(option,"CPRL") == 0) - parameters.prog_order=OPJ_CPRL; - } - option=GetImageOption(image_info,"jp2:rate"); - if (option != (const char *) NULL) - { - register const char - *p; - - /* - Set compression rate. - */ - p=option; - for (i=0; sscanf(p,"%f",¶meters.tcp_rates[i]) == 1; i++) - { - if (i >= 100) - break; - while ((*p != '\0') && (*p != ',')) - p++; - if (*p == '\0') - break; - p++; - } - parameters.tcp_numlayers=i+1; - parameters.cp_disto_alloc=OPJ_TRUE; - } - if (image_info->sampling_factor != (const char *) NULL) - (void) sscanf(image_info->sampling_factor,"%d,%d", - ¶meters.subsampling_dx,¶meters.subsampling_dy); - property=GetImageProperty(image,"comment",exception); - if (property != (const char *) NULL) - parameters.cp_comment=(char *) property; - channels=3; - jp2_colorspace=OPJ_CLRSPC_SRGB; - if (image->colorspace == YUVColorspace) - { - jp2_colorspace=OPJ_CLRSPC_SYCC; - parameters.subsampling_dx=2; - } - else - { - if (IsGrayColorspace(image->colorspace) != MagickFalse) - { - channels=1; - jp2_colorspace=OPJ_CLRSPC_GRAY; - } - else - (void) TransformImageColorspace(image,sRGBColorspace,exception); - if (image->alpha_trait != UndefinedPixelTrait) - channels++; - } - parameters.tcp_mct=channels == 3 ? 1 : 0; - memset(jp2_info,0,sizeof(jp2_info)); - for (i=0; i < (ssize_t) channels; i++) - { - jp2_info[i].prec=(OPJ_UINT32) image->depth; - jp2_info[i].bpp=(OPJ_UINT32) image->depth; - if ((image->depth == 1) && - ((LocaleCompare(image_info->magick,"JPT") == 0) || - (LocaleCompare(image_info->magick,"JP2") == 0))) - { - jp2_info[i].prec++; /* OpenJPEG returns exception for depth @ 1 */ - jp2_info[i].bpp++; - } - jp2_info[i].sgnd=0; - jp2_info[i].dx=parameters.subsampling_dx; - jp2_info[i].dy=parameters.subsampling_dy; - jp2_info[i].w=(OPJ_UINT32) image->columns; - jp2_info[i].h=(OPJ_UINT32) image->rows; - } - jp2_image=opj_image_create((OPJ_UINT32) channels,jp2_info,jp2_colorspace); - if (jp2_image == (opj_image_t *) NULL) - ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); - jp2_image->x0=parameters.image_offset_x0; - jp2_image->y0=parameters.image_offset_y0; - jp2_image->x1=(unsigned int) (2*parameters.image_offset_x0+(image->columns-1)* - parameters.subsampling_dx+1); - jp2_image->y1=(unsigned int) (2*parameters.image_offset_y0+(image->rows-1)* - parameters.subsampling_dx+1); - if ((image->depth == 12) && - ((image->columns == 2048) || (image->rows == 1080) || - (image->columns == 4096) || (image->rows == 2160))) - CinemaProfileCompliance(jp2_image,¶meters); - if (channels == 4) - jp2_image->comps[3].alpha=1; - else - if ((channels == 2) && (jp2_colorspace == OPJ_CLRSPC_GRAY)) - jp2_image->comps[1].alpha=1; - /* - Convert to JP2 pixels. - */ - for (y=0; y < (ssize_t) image->rows; y++) - { - register const Quantum - *p; + register ssize_t + i; ssize_t - x; + y; - p=GetVirtualPixels(image,0,y,image->columns,1,exception); - if (p == (const Quantum *) NULL) - break; - for (x=0; x < (ssize_t) image->columns; x++) - { - for (i=0; i < (ssize_t) channels; i++) - { - double - scale; + unsigned int + channels; - register int - *q; - - scale=(double) ((1UL << jp2_image->comps[i].prec)-1)/QuantumRange; - q=jp2_image->comps[i].data+(y/jp2_image->comps[i].dy* - image->columns/jp2_image->comps[i].dx+x/jp2_image->comps[i].dx); - switch (i) - { - case 0: - { - if (jp2_colorspace == OPJ_CLRSPC_GRAY) - { - *q=(int) (scale*GetPixelGray(image,p)); - break; - } - *q=(int) (scale*GetPixelRed(image,p)); - break; - } - case 1: - { - if (jp2_colorspace == OPJ_CLRSPC_GRAY) - { - *q=(int) (scale*GetPixelAlpha(image,p)); - break; - } - *q=(int) (scale*GetPixelGreen(image,p)); - break; - } - case 2: - { - *q=(int) (scale*GetPixelBlue(image,p)); - break; - } - case 3: - { - *q=(int) (scale*GetPixelAlpha(image,p)); - break; - } - } - } - p+=GetPixelChannels(image); - } - status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, - image->rows); + /* + Open image file. + */ + assert(image_info != (const ImageInfo *) NULL); + assert(image_info->signature == MagickCoreSignature); + assert(image != (Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) - break; - } - if (LocaleCompare(image_info->magick,"JPT") == 0) - jp2_codec=opj_create_compress(OPJ_CODEC_JPT); - else - if (LocaleCompare(image_info->magick,"J2K") == 0) - jp2_codec=opj_create_compress(OPJ_CODEC_J2K); + return(status); + /* + Initialize JPEG 2000 API. + */ + opj_set_default_encoder_parameters(¶meters); + for (i=1; i < 6; i++) + if (((size_t) (1UL << (i+2)) > image->columns) && + ((size_t) (1UL << (i+2)) > image->rows)) + break; + parameters.numresolution=i; + option=GetImageOption(image_info,"jp2:number-resolutions"); + if (option != (const char *) NULL) + parameters.numresolution=StringToInteger(option); + parameters.tcp_numlayers=1; + parameters.tcp_rates[0]=0; /* lossless */ + parameters.cp_disto_alloc=1; + if ((image_info->quality != 0) && (image_info->quality != 100)) + { + parameters.tcp_distoratio[0]=(double) image_info->quality; + parameters.cp_fixed_quality=OPJ_TRUE; + } + if (image_info->extract != (char *) NULL) + { + RectangleInfo + geometry; + + int + flags; + + /* + Set tile size. + */ + flags=ParseAbsoluteGeometry(image_info->extract,&geometry); + parameters.cp_tdx=(int) geometry.width; + parameters.cp_tdy=(int) geometry.width; + if ((flags & HeightValue) != 0) + parameters.cp_tdy=(int) geometry.height; + if ((flags & XValue) != 0) + parameters.cp_tx0=geometry.x; + if ((flags & YValue) != 0) + parameters.cp_ty0=geometry.y; + parameters.tile_size_on=OPJ_TRUE; + } + option=GetImageOption(image_info,"jp2:quality"); + if (option != (const char *) NULL) + { + register const char + *p; + + /* + Set quality PSNR. + */ + p=option; + for (i=0; sscanf(p,"%f",¶meters.tcp_distoratio[i]) == 1; i++) + { + if (i > 100) + break; + while ((*p != '\0') && (*p != ',')) + p++; + if (*p == '\0') + break; + p++; + } + parameters.tcp_numlayers=i+1; + parameters.cp_fixed_quality=OPJ_TRUE; + } + option=GetImageOption(image_info,"jp2:progression-order"); + if (option != (const char *) NULL) + { + if (LocaleCompare(option,"LRCP") == 0) + parameters.prog_order=OPJ_LRCP; + if (LocaleCompare(option,"RLCP") == 0) + parameters.prog_order=OPJ_RLCP; + if (LocaleCompare(option,"RPCL") == 0) + parameters.prog_order=OPJ_RPCL; + if (LocaleCompare(option,"PCRL") == 0) + parameters.prog_order=OPJ_PCRL; + if (LocaleCompare(option,"CPRL") == 0) + parameters.prog_order=OPJ_CPRL; + } + option=GetImageOption(image_info,"jp2:rate"); + if (option != (const char *) NULL) + { + register const char + *p; + + /* + Set compression rate. + */ + p=option; + for (i=0; sscanf(p,"%f",¶meters.tcp_rates[i]) == 1; i++) + { + if (i >= 100) + break; + while ((*p != '\0') && (*p != ',')) + p++; + if (*p == '\0') + break; + p++; + } + parameters.tcp_numlayers=i+1; + parameters.cp_disto_alloc=OPJ_TRUE; + } + if (image_info->sampling_factor != (const char *) NULL) + (void) sscanf(image_info->sampling_factor,"%d,%d", + ¶meters.subsampling_dx,¶meters.subsampling_dy); + property=GetImageProperty(image,"comment",exception); + if (property != (const char *) NULL) + parameters.cp_comment=(char *) property; + channels=3; + jp2_colorspace=OPJ_CLRSPC_SRGB; + if (image->colorspace == YUVColorspace) + { + jp2_colorspace=OPJ_CLRSPC_SYCC; + parameters.subsampling_dx=2; + } else - jp2_codec=opj_create_compress(OPJ_CODEC_JP2); - opj_set_warning_handler(jp2_codec,JP2WarningHandler,exception); - opj_set_error_handler(jp2_codec,JP2ErrorHandler,exception); - opj_setup_encoder(jp2_codec,¶meters,jp2_image); - jp2_stream=opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE,OPJ_FALSE); - if (jp2_stream == (opj_stream_t *) NULL) { - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + if (IsGrayColorspace(image->colorspace) != MagickFalse) + { + channels=1; + jp2_colorspace=OPJ_CLRSPC_GRAY; + } + else + (void) TransformImageColorspace(image,sRGBColorspace,exception); + if (image->alpha_trait != UndefinedPixelTrait) + channels++; } - opj_stream_set_read_function(jp2_stream,JP2ReadHandler); - opj_stream_set_write_function(jp2_stream,JP2WriteHandler); - opj_stream_set_seek_function(jp2_stream,JP2SeekHandler); - opj_stream_set_skip_function(jp2_stream,JP2SkipHandler); - opj_stream_set_user_data(jp2_stream,image,NULL); - jp2_status=opj_start_compress(jp2_codec,jp2_image,jp2_stream); - if ((jp2_status == 0) || (opj_encode(jp2_codec,jp2_stream) == 0) || - (opj_end_compress(jp2_codec,jp2_stream) == 0)) + parameters.tcp_mct=channels == 3 ? 1 : 0; + memset(jp2_info,0,sizeof(jp2_info)); + for (i=0; i < (ssize_t) channels; i++) { - opj_stream_destroy(jp2_stream); - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + jp2_info[i].prec=(OPJ_UINT32) image->depth; + jp2_info[i].bpp=(OPJ_UINT32) image->depth; + if ((image->depth == 1) && + ((LocaleCompare(image_info->magick,"JPT") == 0) || + (LocaleCompare(image_info->magick,"JP2") == 0))) + { + jp2_info[i].prec++; /* OpenJPEG returns exception for depth @ 1 */ + jp2_info[i].bpp++; + } + jp2_info[i].sgnd=0; + jp2_info[i].dx=parameters.subsampling_dx; + jp2_info[i].dy=parameters.subsampling_dy; + jp2_info[i].w=(OPJ_UINT32) image->columns; + jp2_info[i].h=(OPJ_UINT32) image->rows; } - /* - Free resources. - */ - opj_stream_destroy(jp2_stream); - opj_destroy_codec(jp2_codec); - opj_image_destroy(jp2_image); - (void) CloseBlob(image); - return(MagickTrue); + jp2_image=opj_image_create((OPJ_UINT32) channels,jp2_info,jp2_colorspace); + if (jp2_image == (opj_image_t *) NULL) + ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + jp2_image->x0=parameters.image_offset_x0; + jp2_image->y0=parameters.image_offset_y0; + jp2_image->x1=(unsigned int) (2*parameters.image_offset_x0+(image->columns-1)* + parameters.subsampling_dx+1); + jp2_image->y1=(unsigned int) (2*parameters.image_offset_y0+(image->rows-1)* + parameters.subsampling_dx+1); + if ((image->depth == 12) && + ((image->columns == 2048) || (image->rows == 1080) || + (image->columns == 4096) || (image->rows == 2160))) + CinemaProfileCompliance(jp2_image,¶meters); + if (channels == 4) + jp2_image->comps[3].alpha=1; + else + if ((channels == 2) && (jp2_colorspace == OPJ_CLRSPC_GRAY)) + jp2_image->comps[1].alpha=1; + /* + Convert to JP2 pixels. + */ + for (y=0; y < (ssize_t) image->rows; y++) + { + register const Quantum + *p; + + ssize_t + x; + + p=GetVirtualPixels(image,0,y,image->columns,1,exception); + if (p == (const Quantum *) NULL) + break; + for (x=0; x < (ssize_t) image->columns; x++) + { + for (i=0; i < (ssize_t) channels; i++) + { + double + scale; + + register int + *q; + + scale=(double) ((1UL << jp2_image->comps[i].prec)-1)/QuantumRange; + q=jp2_image->comps[i].data+(y/jp2_image->comps[i].dy* + image->columns/jp2_image->comps[i].dx+x/jp2_image->comps[i].dx); + switch (i) + { + case 0: + { + if (jp2_colorspace == OPJ_CLRSPC_GRAY) + { + *q=(int) (scale*GetPixelGray(image,p)); + break; + } + *q=(int) (scale*GetPixelRed(image,p)); + break; + } + case 1: + { + if (jp2_colorspace == OPJ_CLRSPC_GRAY) + { + *q=(int) (scale*GetPixelAlpha(image,p)); + break; + } + *q=(int) (scale*GetPixelGreen(image,p)); + break; + } + case 2: + { + *q=(int) (scale*GetPixelBlue(image,p)); + break; + } + case 3: + { + *q=(int) (scale*GetPixelAlpha(image,p)); + break; + } + } + } + p+=GetPixelChannels(image); + } + status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, + image->rows); + if (status == MagickFalse) + break; + } + if (LocaleCompare(image_info->magick,"JPT") == 0) + jp2_codec=opj_create_compress(OPJ_CODEC_JPT); + else + if (LocaleCompare(image_info->magick,"J2K") == 0) + jp2_codec=opj_create_compress(OPJ_CODEC_J2K); + else + jp2_codec=opj_create_compress(OPJ_CODEC_JP2); + opj_set_warning_handler(jp2_codec,JP2WarningHandler,exception); + opj_set_error_handler(jp2_codec,JP2ErrorHandler,exception); + opj_setup_encoder(jp2_codec,¶meters,jp2_image); + jp2_stream=opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE,OPJ_FALSE); + if (jp2_stream == (opj_stream_t *) NULL) + { + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + } + opj_stream_set_read_function(jp2_stream,JP2ReadHandler); + opj_stream_set_write_function(jp2_stream,JP2WriteHandler); + opj_stream_set_seek_function(jp2_stream,JP2SeekHandler); + opj_stream_set_skip_function(jp2_stream,JP2SkipHandler); + opj_stream_set_user_data(jp2_stream,image,NULL); + jp2_status=opj_start_compress(jp2_codec,jp2_image,jp2_stream); + if ((jp2_status == 0) || (opj_encode(jp2_codec,jp2_stream) == 0) || + (opj_end_compress(jp2_codec,jp2_stream) == 0)) + { + opj_stream_destroy(jp2_stream); + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + } + /* + Free resources. + */ + opj_stream_destroy(jp2_stream); + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + (void) CloseBlob(image); + return(MagickTrue); } #endif diff --git a/test/bug-hunting/cve/CVE-2019-13390/libavformat_rawenc.c b/test/bug-hunting/cve/CVE-2019-13390/libavformat_rawenc.c index 993d232b7..b74d1118c 100644 --- a/test/bug-hunting/cve/CVE-2019-13390/libavformat_rawenc.c +++ b/test/bug-hunting/cve/CVE-2019-13390/libavformat_rawenc.c @@ -319,7 +319,7 @@ static int h264_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) { AVStream *st = s->streams[0]; if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && - AV_RB24(pkt->data) != 0x000001) + AV_RB24(pkt->data) != 0x000001) return ff_stream_add_bitstream_filter(st, "h264_mp4toannexb", NULL); return 1; } @@ -342,7 +342,7 @@ static int hevc_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) { AVStream *st = s->streams[0]; if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && - AV_RB24(pkt->data) != 0x000001) + AV_RB24(pkt->data) != 0x000001) return ff_stream_add_bitstream_filter(st, "hevc_mp4toannexb", NULL); return 1; } diff --git a/test/bug-hunting/cve/CVE-2019-13454/layer.c b/test/bug-hunting/cve/CVE-2019-13454/layer.c index b520e9247..6d1cc9a3f 100644 --- a/test/bug-hunting/cve/CVE-2019-13454/layer.c +++ b/test/bug-hunting/cve/CVE-2019-13454/layer.c @@ -1,42 +1,42 @@ /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% L AAA Y Y EEEEE RRRR % -% L A A Y Y E R R % -% L AAAAA Y EEE RRRR % -% L A A Y E R R % -% LLLLL A A Y EEEEE R R % -% % -% MagickCore Image Layering Methods % -% % -% Software Design % -% Cristy % -% Anthony Thyssen % -% January 2006 % -% % -% % -% Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % -% dedicated to making software imaging solutions freely available. % -% % -% You may not use this file except in compliance with the License. You may % -% obtain a copy of the License at % -% % -% https://imagemagick.org/script/license.php % -% % -% Unless required by applicable law or agreed to in writing, software % -% distributed under the License is distributed on an "AS IS" BASIS, % -% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % -% See the License for the specific language governing permissions and % -% limitations under the License. % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -*/ - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % L AAA Y Y EEEEE RRRR % + % L A A Y Y E R R % + % L AAAAA Y EEE RRRR % + % L A A Y E R R % + % LLLLL A A Y EEEEE R R % + % % + % MagickCore Image Layering Methods % + % % + % Software Design % + % Cristy % + % Anthony Thyssen % + % January 2006 % + % % + % % + % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % + % dedicated to making software imaging solutions freely available. % + % % + % You may not use this file except in compliance with the License. You may % + % obtain a copy of the License at % + % % + % https://imagemagick.org/script/license.php % + % % + % Unless required by applicable law or agreed to in writing, software % + % distributed under the License is distributed on an "AS IS" BASIS, % + % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % + % See the License for the specific language governing permissions and % + % limitations under the License. % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + */ + /* - Include declarations. -*/ + Include declarations. + */ #include "MagickCore/studio.h" #include "MagickCore/artifact.h" #include "MagickCore/cache.h" @@ -63,1141 +63,1141 @@ #include "MagickCore/statistic.h" #include "MagickCore/string_.h" #include "MagickCore/transform.h" - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ C l e a r B o u n d s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% ClearBounds() Clear the area specified by the bounds in an image to -% transparency. This typically used to handle Background Disposal for the -% previous frame in an animation sequence. -% -% Warning: no bounds checks are performed, except for the null or missed -% image, for images that don't change. in all other cases bound must fall -% within the image. -% -% The format is: -% -% void ClearBounds(Image *image,RectangleInfo *bounds, -% ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image to had the area cleared in -% -% o bounds: the area to be clear within the imag image -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + + C l e a r B o u n d s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % ClearBounds() Clear the area specified by the bounds in an image to + % transparency. This typically used to handle Background Disposal for the + % previous frame in an animation sequence. + % + % Warning: no bounds checks are performed, except for the null or missed + % image, for images that don't change. in all other cases bound must fall + % within the image. + % + % The format is: + % + % void ClearBounds(Image *image,RectangleInfo *bounds, + % ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image to had the area cleared in + % + % o bounds: the area to be clear within the imag image + % + % o exception: return any errors or warnings in this structure. + % + */ static void ClearBounds(Image *image,RectangleInfo *bounds, - ExceptionInfo *exception) + ExceptionInfo *exception) { - ssize_t - y; + ssize_t + y; - if (bounds->x < 0) - return; - if (image->alpha_trait == UndefinedPixelTrait) - (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); - for (y=0; y < (ssize_t) bounds->height; y++) - { - register ssize_t - x; - - register Quantum - *magick_restrict q; - - q=GetAuthenticPixels(image,bounds->x,bounds->y+y,bounds->width,1,exception); - if (q == (Quantum *) NULL) - break; - for (x=0; x < (ssize_t) bounds->width; x++) + if (bounds->x < 0) + return; + if (image->alpha_trait == UndefinedPixelTrait) + (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); + for (y=0; y < (ssize_t) bounds->height; y++) { - SetPixelAlpha(image,TransparentAlpha,q); - q+=GetPixelChannels(image); + register ssize_t + x; + + register Quantum + *magick_restrict q; + + q=GetAuthenticPixels(image,bounds->x,bounds->y+y,bounds->width,1,exception); + if (q == (Quantum *) NULL) + break; + for (x=0; x < (ssize_t) bounds->width; x++) + { + SetPixelAlpha(image,TransparentAlpha,q); + q+=GetPixelChannels(image); + } + if (SyncAuthenticPixels(image,exception) == MagickFalse) + break; } - if (SyncAuthenticPixels(image,exception) == MagickFalse) - break; - } } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ I s B o u n d s C l e a r e d % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% IsBoundsCleared() tests whether any pixel in the bounds given, gets cleared -% when going from the first image to the second image. This typically used -% to check if a proposed disposal method will work successfully to generate -% the second frame image from the first disposed form of the previous frame. -% -% Warning: no bounds checks are performed, except for the null or missed -% image, for images that don't change. in all other cases bound must fall -% within the image. -% -% The format is: -% -% MagickBooleanType IsBoundsCleared(const Image *image1, -% const Image *image2,RectangleInfo bounds,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image1, image 2: the images to check for cleared pixels -% -% o bounds: the area to be clear within the imag image -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + + I s B o u n d s C l e a r e d % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % IsBoundsCleared() tests whether any pixel in the bounds given, gets cleared + % when going from the first image to the second image. This typically used + % to check if a proposed disposal method will work successfully to generate + % the second frame image from the first disposed form of the previous frame. + % + % Warning: no bounds checks are performed, except for the null or missed + % image, for images that don't change. in all other cases bound must fall + % within the image. + % + % The format is: + % + % MagickBooleanType IsBoundsCleared(const Image *image1, + % const Image *image2,RectangleInfo bounds,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image1, image 2: the images to check for cleared pixels + % + % o bounds: the area to be clear within the imag image + % + % o exception: return any errors or warnings in this structure. + % + */ static MagickBooleanType IsBoundsCleared(const Image *image1, - const Image *image2,RectangleInfo *bounds,ExceptionInfo *exception) + const Image *image2,RectangleInfo *bounds,ExceptionInfo *exception) { - register const Quantum + register const Quantum *p, *q; - register ssize_t - x; + register ssize_t + x; - ssize_t - y; + ssize_t + y; - if (bounds->x < 0) - return(MagickFalse); - for (y=0; y < (ssize_t) bounds->height; y++) - { - p=GetVirtualPixels(image1,bounds->x,bounds->y+y,bounds->width,1,exception); - q=GetVirtualPixels(image2,bounds->x,bounds->y+y,bounds->width,1,exception); - if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) - break; - for (x=0; x < (ssize_t) bounds->width; x++) + if (bounds->x < 0) + return(MagickFalse); + for (y=0; y < (ssize_t) bounds->height; y++) { - if ((GetPixelAlpha(image1,p) >= (Quantum) (QuantumRange/2)) && - (GetPixelAlpha(image2,q) < (Quantum) (QuantumRange/2))) - break; - p+=GetPixelChannels(image1); - q+=GetPixelChannels(image2); + p=GetVirtualPixels(image1,bounds->x,bounds->y+y,bounds->width,1,exception); + q=GetVirtualPixels(image2,bounds->x,bounds->y+y,bounds->width,1,exception); + if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) + break; + for (x=0; x < (ssize_t) bounds->width; x++) + { + if ((GetPixelAlpha(image1,p) >= (Quantum) (QuantumRange/2)) && + (GetPixelAlpha(image2,q) < (Quantum) (QuantumRange/2))) + break; + p+=GetPixelChannels(image1); + q+=GetPixelChannels(image2); + } + if (x < (ssize_t) bounds->width) + break; } - if (x < (ssize_t) bounds->width) - break; - } - return(y < (ssize_t) bounds->height ? MagickTrue : MagickFalse); + return(y < (ssize_t) bounds->height ? MagickTrue : MagickFalse); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% C o a l e s c e I m a g e s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% CoalesceImages() composites a set of images while respecting any page -% offsets and disposal methods. GIF, MIFF, and MNG animation sequences -% typically start with an image background and each subsequent image -% varies in size and offset. A new image sequence is returned with all -% images the same size as the first images virtual canvas and composited -% with the next image in the sequence. -% -% The format of the CoalesceImages method is: -% -% Image *CoalesceImages(Image *image,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image sequence. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % C o a l e s c e I m a g e s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % CoalesceImages() composites a set of images while respecting any page + % offsets and disposal methods. GIF, MIFF, and MNG animation sequences + % typically start with an image background and each subsequent image + % varies in size and offset. A new image sequence is returned with all + % images the same size as the first images virtual canvas and composited + % with the next image in the sequence. + % + % The format of the CoalesceImages method is: + % + % Image *CoalesceImages(Image *image,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image sequence. + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport Image *CoalesceImages(const Image *image,ExceptionInfo *exception) { - Image + Image *coalesce_image, *dispose_image, *previous; - register Image + register Image *next; - RectangleInfo - bounds; + RectangleInfo + bounds; - /* - Coalesce the image sequence. - */ - assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - next=GetFirstImageInList(image); - bounds=next->page; - if (bounds.width == 0) + /* + Coalesce the image sequence. + */ + assert(image != (Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + next=GetFirstImageInList(image); + bounds=next->page; + if (bounds.width == 0) { - bounds.width=next->columns; - if (bounds.x > 0) - bounds.width+=bounds.x; + bounds.width=next->columns; + if (bounds.x > 0) + bounds.width+=bounds.x; } - if (bounds.height == 0) + if (bounds.height == 0) { - bounds.height=next->rows; - if (bounds.y > 0) - bounds.height+=bounds.y; + bounds.height=next->rows; + if (bounds.y > 0) + bounds.height+=bounds.y; } - bounds.x=0; - bounds.y=0; - coalesce_image=CloneImage(next,bounds.width,bounds.height,MagickTrue, - exception); - if (coalesce_image == (Image *) NULL) - return((Image *) NULL); - coalesce_image->background_color.alpha=(MagickRealType) TransparentAlpha; - (void) SetImageBackgroundColor(coalesce_image,exception); - coalesce_image->alpha_trait=next->alpha_trait; - coalesce_image->page=bounds; - coalesce_image->dispose=NoneDispose; - /* - Coalesce rest of the images. - */ - dispose_image=CloneImage(coalesce_image,0,0,MagickTrue,exception); - (void) CompositeImage(coalesce_image,next,CopyCompositeOp,MagickTrue, - next->page.x,next->page.y,exception); - next=GetNextImageInList(next); - for ( ; next != (Image *) NULL; next=GetNextImageInList(next)) - { + bounds.x=0; + bounds.y=0; + coalesce_image=CloneImage(next,bounds.width,bounds.height,MagickTrue, + exception); + if (coalesce_image == (Image *) NULL) + return((Image *) NULL); + coalesce_image->background_color.alpha=(MagickRealType) TransparentAlpha; + (void) SetImageBackgroundColor(coalesce_image,exception); + coalesce_image->alpha_trait=next->alpha_trait; + coalesce_image->page=bounds; + coalesce_image->dispose=NoneDispose; /* - Determine the bounds that was overlaid in the previous image. - */ - previous=GetPreviousImageInList(next); - bounds=previous->page; - bounds.width=previous->columns; - bounds.height=previous->rows; - if (bounds.x < 0) - { - bounds.width+=bounds.x; - bounds.x=0; - } - if ((ssize_t) (bounds.x+bounds.width) > (ssize_t) coalesce_image->columns) - bounds.width=coalesce_image->columns-bounds.x; - if (bounds.y < 0) - { - bounds.height+=bounds.y; - bounds.y=0; - } - if ((ssize_t) (bounds.y+bounds.height) > (ssize_t) coalesce_image->rows) - bounds.height=coalesce_image->rows-bounds.y; - /* - Replace the dispose image with the new coalesced image. - */ - if (GetPreviousImageInList(next)->dispose != PreviousDispose) - { - dispose_image=DestroyImage(dispose_image); - dispose_image=CloneImage(coalesce_image,0,0,MagickTrue,exception); - if (dispose_image == (Image *) NULL) - { - coalesce_image=DestroyImageList(coalesce_image); - return((Image *) NULL); - } - } - /* - Clear the overlaid area of the coalesced bounds for background disposal - */ - if (next->previous->dispose == BackgroundDispose) - ClearBounds(dispose_image,&bounds,exception); - /* - Next image is the dispose image, overlaid with next frame in sequence. - */ - coalesce_image->next=CloneImage(dispose_image,0,0,MagickTrue,exception); - coalesce_image->next->previous=coalesce_image; - previous=coalesce_image; - coalesce_image=GetNextImageInList(coalesce_image); - (void) CompositeImage(coalesce_image,next, - next->alpha_trait != UndefinedPixelTrait ? OverCompositeOp : CopyCompositeOp, - MagickTrue,next->page.x,next->page.y,exception); - (void) CloneImageProfiles(coalesce_image,next); - (void) CloneImageProperties(coalesce_image,next); - (void) CloneImageArtifacts(coalesce_image,next); - coalesce_image->page=previous->page; - /* - If a pixel goes opaque to transparent, use background dispose. - */ - if (IsBoundsCleared(previous,coalesce_image,&bounds,exception) != MagickFalse) - coalesce_image->dispose=BackgroundDispose; - else - coalesce_image->dispose=NoneDispose; - previous->dispose=coalesce_image->dispose; - } - dispose_image=DestroyImage(dispose_image); - return(GetFirstImageInList(coalesce_image)); + Coalesce rest of the images. + */ + dispose_image=CloneImage(coalesce_image,0,0,MagickTrue,exception); + (void) CompositeImage(coalesce_image,next,CopyCompositeOp,MagickTrue, + next->page.x,next->page.y,exception); + next=GetNextImageInList(next); + for ( ; next != (Image *) NULL; next=GetNextImageInList(next)) + { + /* + Determine the bounds that was overlaid in the previous image. + */ + previous=GetPreviousImageInList(next); + bounds=previous->page; + bounds.width=previous->columns; + bounds.height=previous->rows; + if (bounds.x < 0) + { + bounds.width+=bounds.x; + bounds.x=0; + } + if ((ssize_t) (bounds.x+bounds.width) > (ssize_t) coalesce_image->columns) + bounds.width=coalesce_image->columns-bounds.x; + if (bounds.y < 0) + { + bounds.height+=bounds.y; + bounds.y=0; + } + if ((ssize_t) (bounds.y+bounds.height) > (ssize_t) coalesce_image->rows) + bounds.height=coalesce_image->rows-bounds.y; + /* + Replace the dispose image with the new coalesced image. + */ + if (GetPreviousImageInList(next)->dispose != PreviousDispose) + { + dispose_image=DestroyImage(dispose_image); + dispose_image=CloneImage(coalesce_image,0,0,MagickTrue,exception); + if (dispose_image == (Image *) NULL) + { + coalesce_image=DestroyImageList(coalesce_image); + return((Image *) NULL); + } + } + /* + Clear the overlaid area of the coalesced bounds for background disposal + */ + if (next->previous->dispose == BackgroundDispose) + ClearBounds(dispose_image,&bounds,exception); + /* + Next image is the dispose image, overlaid with next frame in sequence. + */ + coalesce_image->next=CloneImage(dispose_image,0,0,MagickTrue,exception); + coalesce_image->next->previous=coalesce_image; + previous=coalesce_image; + coalesce_image=GetNextImageInList(coalesce_image); + (void) CompositeImage(coalesce_image,next, + next->alpha_trait != UndefinedPixelTrait ? OverCompositeOp : CopyCompositeOp, + MagickTrue,next->page.x,next->page.y,exception); + (void) CloneImageProfiles(coalesce_image,next); + (void) CloneImageProperties(coalesce_image,next); + (void) CloneImageArtifacts(coalesce_image,next); + coalesce_image->page=previous->page; + /* + If a pixel goes opaque to transparent, use background dispose. + */ + if (IsBoundsCleared(previous,coalesce_image,&bounds,exception) != MagickFalse) + coalesce_image->dispose=BackgroundDispose; + else + coalesce_image->dispose=NoneDispose; + previous->dispose=coalesce_image->dispose; + } + dispose_image=DestroyImage(dispose_image); + return(GetFirstImageInList(coalesce_image)); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% D i s p o s e I m a g e s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% DisposeImages() returns the coalesced frames of a GIF animation as it would -% appear after the GIF dispose method of that frame has been applied. That is -% it returned the appearance of each frame before the next is overlaid. -% -% The format of the DisposeImages method is: -% -% Image *DisposeImages(Image *image,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o images: the image sequence. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % D i s p o s e I m a g e s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % DisposeImages() returns the coalesced frames of a GIF animation as it would + % appear after the GIF dispose method of that frame has been applied. That is + % it returned the appearance of each frame before the next is overlaid. + % + % The format of the DisposeImages method is: + % + % Image *DisposeImages(Image *image,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o images: the image sequence. + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport Image *DisposeImages(const Image *images,ExceptionInfo *exception) { - Image + Image *dispose_image, *dispose_images; - RectangleInfo - bounds; + RectangleInfo + bounds; - register Image + register Image *image, *next; - /* - Run the image through the animation sequence - */ - assert(images != (Image *) NULL); - assert(images->signature == MagickCoreSignature); - if (images->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - image=GetFirstImageInList(images); - dispose_image=CloneImage(image,image->page.width,image->page.height, - MagickTrue,exception); - if (dispose_image == (Image *) NULL) - return((Image *) NULL); - dispose_image->page=image->page; - dispose_image->page.x=0; - dispose_image->page.y=0; - dispose_image->dispose=NoneDispose; - dispose_image->background_color.alpha=(MagickRealType) TransparentAlpha; - (void) SetImageBackgroundColor(dispose_image,exception); - dispose_images=NewImageList(); - for (next=image; image != (Image *) NULL; image=GetNextImageInList(image)) - { - Image - *current_image; - /* - Overlay this frame's image over the previous disposal image. - */ - current_image=CloneImage(dispose_image,0,0,MagickTrue,exception); - if (current_image == (Image *) NULL) - { - dispose_images=DestroyImageList(dispose_images); - dispose_image=DestroyImage(dispose_image); + Run the image through the animation sequence + */ + assert(images != (Image *) NULL); + assert(images->signature == MagickCoreSignature); + if (images->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + image=GetFirstImageInList(images); + dispose_image=CloneImage(image,image->page.width,image->page.height, + MagickTrue,exception); + if (dispose_image == (Image *) NULL) return((Image *) NULL); - } - (void) CompositeImage(current_image,next, - next->alpha_trait != UndefinedPixelTrait ? OverCompositeOp : CopyCompositeOp, - MagickTrue,next->page.x,next->page.y,exception); - /* - Handle Background dispose: image is displayed for the delay period. - */ - if (next->dispose == BackgroundDispose) - { - bounds=next->page; - bounds.width=next->columns; - bounds.height=next->rows; - if (bounds.x < 0) - { - bounds.width+=bounds.x; - bounds.x=0; - } - if ((ssize_t) (bounds.x+bounds.width) > (ssize_t) current_image->columns) - bounds.width=current_image->columns-bounds.x; - if (bounds.y < 0) - { - bounds.height+=bounds.y; - bounds.y=0; - } - if ((ssize_t) (bounds.y+bounds.height) > (ssize_t) current_image->rows) - bounds.height=current_image->rows-bounds.y; - ClearBounds(current_image,&bounds,exception); - } - /* - Select the appropriate previous/disposed image. - */ - if (next->dispose == PreviousDispose) - current_image=DestroyImage(current_image); - else - { - dispose_image=DestroyImage(dispose_image); - dispose_image=current_image; - current_image=(Image *) NULL; - } - /* - Save the dispose image just calculated for return. - */ + dispose_image->page=image->page; + dispose_image->page.x=0; + dispose_image->page.y=0; + dispose_image->dispose=NoneDispose; + dispose_image->background_color.alpha=(MagickRealType) TransparentAlpha; + (void) SetImageBackgroundColor(dispose_image,exception); + dispose_images=NewImageList(); + for (next=image; image != (Image *) NULL; image=GetNextImageInList(image)) { - Image - *dispose; + Image + *current_image; - dispose=CloneImage(dispose_image,0,0,MagickTrue,exception); - if (dispose == (Image *) NULL) + /* + Overlay this frame's image over the previous disposal image. + */ + current_image=CloneImage(dispose_image,0,0,MagickTrue,exception); + if (current_image == (Image *) NULL) { - dispose_images=DestroyImageList(dispose_images); - dispose_image=DestroyImage(dispose_image); - return((Image *) NULL); + dispose_images=DestroyImageList(dispose_images); + dispose_image=DestroyImage(dispose_image); + return((Image *) NULL); + } + (void) CompositeImage(current_image,next, + next->alpha_trait != UndefinedPixelTrait ? OverCompositeOp : CopyCompositeOp, + MagickTrue,next->page.x,next->page.y,exception); + /* + Handle Background dispose: image is displayed for the delay period. + */ + if (next->dispose == BackgroundDispose) + { + bounds=next->page; + bounds.width=next->columns; + bounds.height=next->rows; + if (bounds.x < 0) + { + bounds.width+=bounds.x; + bounds.x=0; + } + if ((ssize_t) (bounds.x+bounds.width) > (ssize_t) current_image->columns) + bounds.width=current_image->columns-bounds.x; + if (bounds.y < 0) + { + bounds.height+=bounds.y; + bounds.y=0; + } + if ((ssize_t) (bounds.y+bounds.height) > (ssize_t) current_image->rows) + bounds.height=current_image->rows-bounds.y; + ClearBounds(current_image,&bounds,exception); + } + /* + Select the appropriate previous/disposed image. + */ + if (next->dispose == PreviousDispose) + current_image=DestroyImage(current_image); + else + { + dispose_image=DestroyImage(dispose_image); + dispose_image=current_image; + current_image=(Image *) NULL; + } + /* + Save the dispose image just calculated for return. + */ + { + Image + *dispose; + + dispose=CloneImage(dispose_image,0,0,MagickTrue,exception); + if (dispose == (Image *) NULL) + { + dispose_images=DestroyImageList(dispose_images); + dispose_image=DestroyImage(dispose_image); + return((Image *) NULL); + } + (void) CloneImageProfiles(dispose,next); + (void) CloneImageProperties(dispose,next); + (void) CloneImageArtifacts(dispose,next); + dispose->page.x=0; + dispose->page.y=0; + dispose->dispose=next->dispose; + AppendImageToList(&dispose_images,dispose); } - (void) CloneImageProfiles(dispose,next); - (void) CloneImageProperties(dispose,next); - (void) CloneImageArtifacts(dispose,next); - dispose->page.x=0; - dispose->page.y=0; - dispose->dispose=next->dispose; - AppendImageToList(&dispose_images,dispose); } - } - dispose_image=DestroyImage(dispose_image); - return(GetFirstImageInList(dispose_images)); + dispose_image=DestroyImage(dispose_image); + return(GetFirstImageInList(dispose_images)); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ C o m p a r e P i x e l s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% ComparePixels() Compare the two pixels and return true if the pixels -% differ according to the given LayerType comparision method. -% -% This currently only used internally by CompareImagesBounds(). It is -% doubtful that this sub-routine will be useful outside this module. -% -% The format of the ComparePixels method is: -% -% MagickBooleanType *ComparePixels(const LayerMethod method, -% const PixelInfo *p,const PixelInfo *q) -% -% A description of each parameter follows: -% -% o method: What differences to look for. Must be one of -% CompareAnyLayer, CompareClearLayer, CompareOverlayLayer. -% -% o p, q: the pixels to test for appropriate differences. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + + C o m p a r e P i x e l s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % ComparePixels() Compare the two pixels and return true if the pixels + % differ according to the given LayerType comparision method. + % + % This currently only used internally by CompareImagesBounds(). It is + % doubtful that this sub-routine will be useful outside this module. + % + % The format of the ComparePixels method is: + % + % MagickBooleanType *ComparePixels(const LayerMethod method, + % const PixelInfo *p,const PixelInfo *q) + % + % A description of each parameter follows: + % + % o method: What differences to look for. Must be one of + % CompareAnyLayer, CompareClearLayer, CompareOverlayLayer. + % + % o p, q: the pixels to test for appropriate differences. + % + */ static MagickBooleanType ComparePixels(const LayerMethod method, - const PixelInfo *p,const PixelInfo *q) + const PixelInfo *p,const PixelInfo *q) { - double - o1, - o2; + double + o1, + o2; - /* - Any change in pixel values - */ - if (method == CompareAnyLayer) - return((MagickBooleanType)(IsFuzzyEquivalencePixelInfo(p,q) == MagickFalse)); + /* + Any change in pixel values + */ + if (method == CompareAnyLayer) + return((MagickBooleanType)(IsFuzzyEquivalencePixelInfo(p,q) == MagickFalse)); - o1 = (p->alpha_trait != UndefinedPixelTrait) ? p->alpha : OpaqueAlpha; - o2 = (q->alpha_trait != UndefinedPixelTrait) ? q->alpha : OpaqueAlpha; - /* - Pixel goes from opaque to transprency. - */ - if (method == CompareClearLayer) - return((MagickBooleanType) ( (o1 >= ((double) QuantumRange/2.0)) && - (o2 < ((double) QuantumRange/2.0)) ) ); - /* - Overlay would change first pixel by second. - */ - if (method == CompareOverlayLayer) + o1 = (p->alpha_trait != UndefinedPixelTrait) ? p->alpha : OpaqueAlpha; + o2 = (q->alpha_trait != UndefinedPixelTrait) ? q->alpha : OpaqueAlpha; + /* + Pixel goes from opaque to transprency. + */ + if (method == CompareClearLayer) + return((MagickBooleanType) ((o1 >= ((double) QuantumRange/2.0)) && + (o2 < ((double) QuantumRange/2.0)))); + /* + Overlay would change first pixel by second. + */ + if (method == CompareOverlayLayer) { - if (o2 < ((double) QuantumRange/2.0)) - return MagickFalse; - return((MagickBooleanType) (IsFuzzyEquivalencePixelInfo(p,q) == MagickFalse)); + if (o2 < ((double) QuantumRange/2.0)) + return MagickFalse; + return((MagickBooleanType) (IsFuzzyEquivalencePixelInfo(p,q) == MagickFalse)); } - return(MagickFalse); + return(MagickFalse); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ C o m p a r e I m a g e B o u n d s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% CompareImagesBounds() Given two images return the smallest rectangular area -% by which the two images differ, accourding to the given 'Compare...' -% layer method. -% -% This currently only used internally in this module, but may eventually -% be used by other modules. -% -% The format of the CompareImagesBounds method is: -% -% RectangleInfo *CompareImagesBounds(const LayerMethod method, -% const Image *image1,const Image *image2,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o method: What differences to look for. Must be one of CompareAnyLayer, -% CompareClearLayer, CompareOverlayLayer. -% -% o image1, image2: the two images to compare. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + + C o m p a r e I m a g e B o u n d s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % CompareImagesBounds() Given two images return the smallest rectangular area + % by which the two images differ, accourding to the given 'Compare...' + % layer method. + % + % This currently only used internally in this module, but may eventually + % be used by other modules. + % + % The format of the CompareImagesBounds method is: + % + % RectangleInfo *CompareImagesBounds(const LayerMethod method, + % const Image *image1,const Image *image2,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o method: What differences to look for. Must be one of CompareAnyLayer, + % CompareClearLayer, CompareOverlayLayer. + % + % o image1, image2: the two images to compare. + % + % o exception: return any errors or warnings in this structure. + % + */ static RectangleInfo CompareImagesBounds(const Image *image1, - const Image *image2,const LayerMethod method,ExceptionInfo *exception) + const Image *image2,const LayerMethod method,ExceptionInfo *exception) { - RectangleInfo - bounds; + RectangleInfo + bounds; - PixelInfo - pixel1, - pixel2; + PixelInfo + pixel1, + pixel2; - register const Quantum + register const Quantum *p, *q; - register ssize_t - x; + register ssize_t + x; - ssize_t - y; + ssize_t + y; - /* - Set bounding box of the differences between images. - */ - GetPixelInfo(image1,&pixel1); - GetPixelInfo(image2,&pixel2); - for (x=0; x < (ssize_t) image1->columns; x++) - { - p=GetVirtualPixels(image1,x,0,1,image1->rows,exception); - q=GetVirtualPixels(image2,x,0,1,image2->rows,exception); - if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) - break; - for (y=0; y < (ssize_t) image1->rows; y++) - { - GetPixelInfoPixel(image1,p,&pixel1); - GetPixelInfoPixel(image2,q,&pixel2); - if (ComparePixels(method,&pixel1,&pixel2)) - break; - p+=GetPixelChannels(image1); - q+=GetPixelChannels(image2); - } - if (y < (ssize_t) image1->rows) - break; - } - if (x >= (ssize_t) image1->columns) - { - /* - Images are identical, return a null image. - */ - bounds.x=-1; - bounds.y=-1; - bounds.width=1; - bounds.height=1; - return(bounds); - } - bounds.x=x; - for (x=(ssize_t) image1->columns-1; x >= 0; x--) - { - p=GetVirtualPixels(image1,x,0,1,image1->rows,exception); - q=GetVirtualPixels(image2,x,0,1,image2->rows,exception); - if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) - break; - for (y=0; y < (ssize_t) image1->rows; y++) - { - GetPixelInfoPixel(image1,p,&pixel1); - GetPixelInfoPixel(image2,q,&pixel2); - if (ComparePixels(method,&pixel1,&pixel2)) - break; - p+=GetPixelChannels(image1); - q+=GetPixelChannels(image2); - } - if (y < (ssize_t) image1->rows) - break; - } - bounds.width=(size_t) (x-bounds.x+1); - for (y=0; y < (ssize_t) image1->rows; y++) - { - p=GetVirtualPixels(image1,0,y,image1->columns,1,exception); - q=GetVirtualPixels(image2,0,y,image2->columns,1,exception); - if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) - break; + /* + Set bounding box of the differences between images. + */ + GetPixelInfo(image1,&pixel1); + GetPixelInfo(image2,&pixel2); for (x=0; x < (ssize_t) image1->columns; x++) { - GetPixelInfoPixel(image1,p,&pixel1); - GetPixelInfoPixel(image2,q,&pixel2); - if (ComparePixels(method,&pixel1,&pixel2)) - break; - p+=GetPixelChannels(image1); - q+=GetPixelChannels(image2); + p=GetVirtualPixels(image1,x,0,1,image1->rows,exception); + q=GetVirtualPixels(image2,x,0,1,image2->rows,exception); + if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) + break; + for (y=0; y < (ssize_t) image1->rows; y++) + { + GetPixelInfoPixel(image1,p,&pixel1); + GetPixelInfoPixel(image2,q,&pixel2); + if (ComparePixels(method,&pixel1,&pixel2)) + break; + p+=GetPixelChannels(image1); + q+=GetPixelChannels(image2); + } + if (y < (ssize_t) image1->rows) + break; } - if (x < (ssize_t) image1->columns) - break; - } - bounds.y=y; - for (y=(ssize_t) image1->rows-1; y >= 0; y--) - { - p=GetVirtualPixels(image1,0,y,image1->columns,1,exception); - q=GetVirtualPixels(image2,0,y,image2->columns,1,exception); - if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) - break; - for (x=0; x < (ssize_t) image1->columns; x++) + if (x >= (ssize_t) image1->columns) { - GetPixelInfoPixel(image1,p,&pixel1); - GetPixelInfoPixel(image2,q,&pixel2); - if (ComparePixels(method,&pixel1,&pixel2)) - break; - p+=GetPixelChannels(image1); - q+=GetPixelChannels(image2); + /* + Images are identical, return a null image. + */ + bounds.x=-1; + bounds.y=-1; + bounds.width=1; + bounds.height=1; + return(bounds); } - if (x < (ssize_t) image1->columns) - break; - } - bounds.height=(size_t) (y-bounds.y+1); - return(bounds); + bounds.x=x; + for (x=(ssize_t) image1->columns-1; x >= 0; x--) + { + p=GetVirtualPixels(image1,x,0,1,image1->rows,exception); + q=GetVirtualPixels(image2,x,0,1,image2->rows,exception); + if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) + break; + for (y=0; y < (ssize_t) image1->rows; y++) + { + GetPixelInfoPixel(image1,p,&pixel1); + GetPixelInfoPixel(image2,q,&pixel2); + if (ComparePixels(method,&pixel1,&pixel2)) + break; + p+=GetPixelChannels(image1); + q+=GetPixelChannels(image2); + } + if (y < (ssize_t) image1->rows) + break; + } + bounds.width=(size_t) (x-bounds.x+1); + for (y=0; y < (ssize_t) image1->rows; y++) + { + p=GetVirtualPixels(image1,0,y,image1->columns,1,exception); + q=GetVirtualPixels(image2,0,y,image2->columns,1,exception); + if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) + break; + for (x=0; x < (ssize_t) image1->columns; x++) + { + GetPixelInfoPixel(image1,p,&pixel1); + GetPixelInfoPixel(image2,q,&pixel2); + if (ComparePixels(method,&pixel1,&pixel2)) + break; + p+=GetPixelChannels(image1); + q+=GetPixelChannels(image2); + } + if (x < (ssize_t) image1->columns) + break; + } + bounds.y=y; + for (y=(ssize_t) image1->rows-1; y >= 0; y--) + { + p=GetVirtualPixels(image1,0,y,image1->columns,1,exception); + q=GetVirtualPixels(image2,0,y,image2->columns,1,exception); + if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) + break; + for (x=0; x < (ssize_t) image1->columns; x++) + { + GetPixelInfoPixel(image1,p,&pixel1); + GetPixelInfoPixel(image2,q,&pixel2); + if (ComparePixels(method,&pixel1,&pixel2)) + break; + p+=GetPixelChannels(image1); + q+=GetPixelChannels(image2); + } + if (x < (ssize_t) image1->columns) + break; + } + bounds.height=(size_t) (y-bounds.y+1); + return(bounds); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% C o m p a r e I m a g e L a y e r s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% CompareImagesLayers() compares each image with the next in a sequence and -% returns the minimum bounding region of all the pixel differences (of the -% LayerMethod specified) it discovers. -% -% Images do NOT have to be the same size, though it is best that all the -% images are 'coalesced' (images are all the same size, on a flattened -% canvas, so as to represent exactly how an specific frame should look). -% -% No GIF dispose methods are applied, so GIF animations must be coalesced -% before applying this image operator to find differences to them. -% -% The format of the CompareImagesLayers method is: -% -% Image *CompareImagesLayers(const Image *images, -% const LayerMethod method,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image. -% -% o method: the layers type to compare images with. Must be one of... -% CompareAnyLayer, CompareClearLayer, CompareOverlayLayer. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % C o m p a r e I m a g e L a y e r s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % CompareImagesLayers() compares each image with the next in a sequence and + % returns the minimum bounding region of all the pixel differences (of the + % LayerMethod specified) it discovers. + % + % Images do NOT have to be the same size, though it is best that all the + % images are 'coalesced' (images are all the same size, on a flattened + % canvas, so as to represent exactly how an specific frame should look). + % + % No GIF dispose methods are applied, so GIF animations must be coalesced + % before applying this image operator to find differences to them. + % + % The format of the CompareImagesLayers method is: + % + % Image *CompareImagesLayers(const Image *images, + % const LayerMethod method,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image. + % + % o method: the layers type to compare images with. Must be one of... + % CompareAnyLayer, CompareClearLayer, CompareOverlayLayer. + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport Image *CompareImagesLayers(const Image *image, - const LayerMethod method,ExceptionInfo *exception) + const LayerMethod method,ExceptionInfo *exception) { - Image + Image *image_a, *image_b, *layers; - RectangleInfo + RectangleInfo *bounds; - register const Image + register const Image *next; - register ssize_t - i; + register ssize_t + i; - assert(image != (const Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - assert((method == CompareAnyLayer) || - (method == CompareClearLayer) || - (method == CompareOverlayLayer)); - /* - Allocate bounds memory. - */ - next=GetFirstImageInList(image); - bounds=(RectangleInfo *) AcquireQuantumMemory((size_t) - GetImageListLength(next),sizeof(*bounds)); - if (bounds == (RectangleInfo *) NULL) - ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); - /* - Set up first comparision images. - */ - image_a=CloneImage(next,next->page.width,next->page.height, - MagickTrue,exception); - if (image_a == (Image *) NULL) + assert(image != (const Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + assert((method == CompareAnyLayer) || + (method == CompareClearLayer) || + (method == CompareOverlayLayer)); + /* + Allocate bounds memory. + */ + next=GetFirstImageInList(image); + bounds=(RectangleInfo *) AcquireQuantumMemory((size_t) + GetImageListLength(next),sizeof(*bounds)); + if (bounds == (RectangleInfo *) NULL) + ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); + /* + Set up first comparision images. + */ + image_a=CloneImage(next,next->page.width,next->page.height, + MagickTrue,exception); + if (image_a == (Image *) NULL) { - bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); - return((Image *) NULL); - } - image_a->background_color.alpha=(MagickRealType) TransparentAlpha; - (void) SetImageBackgroundColor(image_a,exception); - image_a->page=next->page; - image_a->page.x=0; - image_a->page.y=0; - (void) CompositeImage(image_a,next,CopyCompositeOp,MagickTrue,next->page.x, - next->page.y,exception); - /* - Compute the bounding box of changes for the later images - */ - i=0; - next=GetNextImageInList(next); - for ( ; next != (const Image *) NULL; next=GetNextImageInList(next)) - { - image_b=CloneImage(image_a,0,0,MagickTrue,exception); - if (image_b == (Image *) NULL) - { - image_a=DestroyImage(image_a); bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); return((Image *) NULL); - } + } + image_a->background_color.alpha=(MagickRealType) TransparentAlpha; + (void) SetImageBackgroundColor(image_a,exception); + image_a->page=next->page; + image_a->page.x=0; + image_a->page.y=0; (void) CompositeImage(image_a,next,CopyCompositeOp,MagickTrue,next->page.x, - next->page.y,exception); - bounds[i]=CompareImagesBounds(image_b,image_a,method,exception); - image_b=DestroyImage(image_b); - i++; - } - image_a=DestroyImage(image_a); - /* - Clone first image in sequence. - */ - next=GetFirstImageInList(image); - layers=CloneImage(next,0,0,MagickTrue,exception); - if (layers == (Image *) NULL) + next->page.y,exception); + /* + Compute the bounding box of changes for the later images + */ + i=0; + next=GetNextImageInList(next); + for ( ; next != (const Image *) NULL; next=GetNextImageInList(next)) { - bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); - return((Image *) NULL); - } - /* - Deconstruct the image sequence. - */ - i=0; - next=GetNextImageInList(next); - for ( ; next != (const Image *) NULL; next=GetNextImageInList(next)) - { - if ((bounds[i].x == -1) && (bounds[i].y == -1) && - (bounds[i].width == 1) && (bounds[i].height == 1)) - { - /* - An empty frame is returned from CompareImageBounds(), which means the - current frame is identical to the previous frame. - */ + image_b=CloneImage(image_a,0,0,MagickTrue,exception); + if (image_b == (Image *) NULL) + { + image_a=DestroyImage(image_a); + bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); + return((Image *) NULL); + } + (void) CompositeImage(image_a,next,CopyCompositeOp,MagickTrue,next->page.x, + next->page.y,exception); + bounds[i]=CompareImagesBounds(image_b,image_a,method,exception); + image_b=DestroyImage(image_b); i++; - continue; - } - image_a=CloneImage(next,0,0,MagickTrue,exception); - if (image_a == (Image *) NULL) - break; - image_b=CropImage(image_a,&bounds[i],exception); - image_a=DestroyImage(image_a); - if (image_b == (Image *) NULL) - break; - AppendImageToList(&layers,image_b); - i++; - } - bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); - if (next != (Image *) NULL) - { - layers=DestroyImageList(layers); - return((Image *) NULL); } - return(GetFirstImageInList(layers)); + image_a=DestroyImage(image_a); + /* + Clone first image in sequence. + */ + next=GetFirstImageInList(image); + layers=CloneImage(next,0,0,MagickTrue,exception); + if (layers == (Image *) NULL) + { + bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); + return((Image *) NULL); + } + /* + Deconstruct the image sequence. + */ + i=0; + next=GetNextImageInList(next); + for ( ; next != (const Image *) NULL; next=GetNextImageInList(next)) + { + if ((bounds[i].x == -1) && (bounds[i].y == -1) && + (bounds[i].width == 1) && (bounds[i].height == 1)) + { + /* + An empty frame is returned from CompareImageBounds(), which means the + current frame is identical to the previous frame. + */ + i++; + continue; + } + image_a=CloneImage(next,0,0,MagickTrue,exception); + if (image_a == (Image *) NULL) + break; + image_b=CropImage(image_a,&bounds[i],exception); + image_a=DestroyImage(image_a); + if (image_b == (Image *) NULL) + break; + AppendImageToList(&layers,image_b); + i++; + } + bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); + if (next != (Image *) NULL) + { + layers=DestroyImageList(layers); + return((Image *) NULL); + } + return(GetFirstImageInList(layers)); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ O p t i m i z e L a y e r F r a m e s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% OptimizeLayerFrames() takes a coalesced GIF animation, and compares each -% frame against the three different 'disposal' forms of the previous frame. -% From this it then attempts to select the smallest cropped image and -% disposal method needed to reproduce the resulting image. -% -% Note that this not easy, and may require the expansion of the bounds -% of previous frame, simply clear pixels for the next animation frame to -% transparency according to the selected dispose method. -% -% The format of the OptimizeLayerFrames method is: -% -% Image *OptimizeLayerFrames(const Image *image, -% const LayerMethod method,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image. -% -% o method: the layers technique to optimize with. Must be one of... -% OptimizeImageLayer, or OptimizePlusLayer. The Plus form allows -% the addition of extra 'zero delay' frames to clear pixels from -% the previous frame, and the removal of frames that done change, -% merging the delay times together. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + + O p t i m i z e L a y e r F r a m e s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % OptimizeLayerFrames() takes a coalesced GIF animation, and compares each + % frame against the three different 'disposal' forms of the previous frame. + % From this it then attempts to select the smallest cropped image and + % disposal method needed to reproduce the resulting image. + % + % Note that this not easy, and may require the expansion of the bounds + % of previous frame, simply clear pixels for the next animation frame to + % transparency according to the selected dispose method. + % + % The format of the OptimizeLayerFrames method is: + % + % Image *OptimizeLayerFrames(const Image *image, + % const LayerMethod method,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image. + % + % o method: the layers technique to optimize with. Must be one of... + % OptimizeImageLayer, or OptimizePlusLayer. The Plus form allows + % the addition of extra 'zero delay' frames to clear pixels from + % the previous frame, and the removal of frames that done change, + % merging the delay times together. + % + % o exception: return any errors or warnings in this structure. + % + */ /* - Define a 'fake' dispose method where the frame is duplicated, (for - OptimizePlusLayer) with a extra zero time delay frame which does a - BackgroundDisposal to clear the pixels that need to be cleared. -*/ + Define a 'fake' dispose method where the frame is duplicated, (for + OptimizePlusLayer) with a extra zero time delay frame which does a + BackgroundDisposal to clear the pixels that need to be cleared. + */ #define DupDispose ((DisposeType)9) /* - Another 'fake' dispose method used to removed frames that don't change. -*/ + Another 'fake' dispose method used to removed frames that don't change. + */ #define DelDispose ((DisposeType)8) #define DEBUG_OPT_FRAME 0 static Image *OptimizeLayerFrames(const Image *image,const LayerMethod method, - ExceptionInfo *exception) + ExceptionInfo *exception) { - ExceptionInfo + ExceptionInfo *sans_exception; - Image + Image *prev_image, *dup_image, *bgnd_image, *optimized_image; - RectangleInfo - try_bounds, - bgnd_bounds, - dup_bounds, - *bounds; + RectangleInfo + try_bounds, + bgnd_bounds, + dup_bounds, + *bounds; - MagickBooleanType - add_frames, - try_cleared, - cleared; + MagickBooleanType + add_frames, + try_cleared, + cleared; - DisposeType + DisposeType *disposals; - register const Image + register const Image *curr; - register ssize_t - i; + register ssize_t + i; - assert(image != (const Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - assert(method == OptimizeLayer || - method == OptimizeImageLayer || - method == OptimizePlusLayer); - /* - Are we allowed to add/remove frames from animation? - */ - add_frames=method == OptimizePlusLayer ? MagickTrue : MagickFalse; - /* - Ensure all the images are the same size. - */ - curr=GetFirstImageInList(image); - for (; curr != (Image *) NULL; curr=GetNextImageInList(curr)) - { - if ((curr->columns != image->columns) || (curr->rows != image->rows)) - ThrowImageException(OptionError,"ImagesAreNotTheSameSize"); + assert(image != (const Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + assert(method == OptimizeLayer || + method == OptimizeImageLayer || + method == OptimizePlusLayer); + /* + Are we allowed to add/remove frames from animation? + */ + add_frames=method == OptimizePlusLayer ? MagickTrue : MagickFalse; + /* + Ensure all the images are the same size. + */ + curr=GetFirstImageInList(image); + for (; curr != (Image *) NULL; curr=GetNextImageInList(curr)) + { + if ((curr->columns != image->columns) || (curr->rows != image->rows)) + ThrowImageException(OptionError,"ImagesAreNotTheSameSize"); - if ((curr->page.x != 0) || (curr->page.y != 0) || - (curr->page.width != image->page.width) || - (curr->page.height != image->page.height)) - ThrowImageException(OptionError,"ImagePagesAreNotCoalesced"); - } - /* - Allocate memory (times 2 if we allow the use of frame duplications) - */ - curr=GetFirstImageInList(image); - bounds=(RectangleInfo *) AcquireQuantumMemory((size_t) - GetImageListLength(curr),(add_frames != MagickFalse ? 2UL : 1UL)* - sizeof(*bounds)); - if (bounds == (RectangleInfo *) NULL) - ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); - disposals=(DisposeType *) AcquireQuantumMemory((size_t) - GetImageListLength(image),(add_frames != MagickFalse ? 2UL : 1UL)* - sizeof(*disposals)); - if (disposals == (DisposeType *) NULL) - { - bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); - ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); + if ((curr->page.x != 0) || (curr->page.y != 0) || + (curr->page.width != image->page.width) || + (curr->page.height != image->page.height)) + ThrowImageException(OptionError,"ImagePagesAreNotCoalesced"); } - /* - Initialise Previous Image as fully transparent - */ - prev_image=CloneImage(curr,curr->columns,curr->rows,MagickTrue,exception); - if (prev_image == (Image *) NULL) + /* + Allocate memory (times 2 if we allow the use of frame duplications) + */ + curr=GetFirstImageInList(image); + bounds=(RectangleInfo *) AcquireQuantumMemory((size_t) + GetImageListLength(curr),(add_frames != MagickFalse ? 2UL : 1UL)* + sizeof(*bounds)); + if (bounds == (RectangleInfo *) NULL) + ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); + disposals=(DisposeType *) AcquireQuantumMemory((size_t) + GetImageListLength(image),(add_frames != MagickFalse ? 2UL : 1UL)* + sizeof(*disposals)); + if (disposals == (DisposeType *) NULL) { - bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); - disposals=(DisposeType *) RelinquishMagickMemory(disposals); - return((Image *) NULL); + bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); + ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); } - prev_image->page=curr->page; /* ERROR: <-- should not be need, but is! */ - prev_image->page.x=0; - prev_image->page.y=0; - prev_image->dispose=NoneDispose; - prev_image->background_color.alpha_trait=BlendPixelTrait; - prev_image->background_color.alpha=(MagickRealType) TransparentAlpha; - (void) SetImageBackgroundColor(prev_image,exception); - /* - Figure out the area of overlay of the first frame - No pixel could be cleared as all pixels are already cleared. - */ -#if DEBUG_OPT_FRAME - i=0; - (void) FormatLocaleFile(stderr,"frame %.20g :-\n",(double) i); -#endif - disposals[0]=NoneDispose; - bounds[0]=CompareImagesBounds(prev_image,curr,CompareAnyLayer,exception); -#if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, "overlay: %.20gx%.20g%+.20g%+.20g\n\n", - (double) bounds[i].width,(double) bounds[i].height, - (double) bounds[i].x,(double) bounds[i].y ); -#endif - /* - Compute the bounding box of changes for each pair of images. - */ - i=1; - bgnd_image=(Image *) NULL; - dup_image=(Image *) NULL; - dup_bounds.width=0; - dup_bounds.height=0; - dup_bounds.x=0; - dup_bounds.y=0; - curr=GetNextImageInList(curr); - for ( ; curr != (const Image *) NULL; curr=GetNextImageInList(curr)) - { + /* + Initialise Previous Image as fully transparent + */ + prev_image=CloneImage(curr,curr->columns,curr->rows,MagickTrue,exception); + if (prev_image == (Image *) NULL) + { + bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); + disposals=(DisposeType *) RelinquishMagickMemory(disposals); + return((Image *) NULL); + } + prev_image->page=curr->page; /* ERROR: <-- should not be need, but is! */ + prev_image->page.x=0; + prev_image->page.y=0; + prev_image->dispose=NoneDispose; + prev_image->background_color.alpha_trait=BlendPixelTrait; + prev_image->background_color.alpha=(MagickRealType) TransparentAlpha; + (void) SetImageBackgroundColor(prev_image,exception); + /* + Figure out the area of overlay of the first frame + No pixel could be cleared as all pixels are already cleared. + */ #if DEBUG_OPT_FRAME + i=0; (void) FormatLocaleFile(stderr,"frame %.20g :-\n",(double) i); +#endif + disposals[0]=NoneDispose; + bounds[0]=CompareImagesBounds(prev_image,curr,CompareAnyLayer,exception); +#if DEBUG_OPT_FRAME + (void) FormatLocaleFile(stderr, "overlay: %.20gx%.20g%+.20g%+.20g\n\n", + (double) bounds[i].width,(double) bounds[i].height, + (double) bounds[i].x,(double) bounds[i].y ); #endif /* - Assume none disposal is the best - */ - bounds[i]=CompareImagesBounds(curr->previous,curr,CompareAnyLayer,exception); - cleared=IsBoundsCleared(curr->previous,curr,&bounds[i],exception); - disposals[i-1]=NoneDispose; + Compute the bounding box of changes for each pair of images. + */ + i=1; + bgnd_image=(Image *) NULL; + dup_image=(Image *) NULL; + dup_bounds.width=0; + dup_bounds.height=0; + dup_bounds.x=0; + dup_bounds.y=0; + curr=GetNextImageInList(curr); + for ( ; curr != (const Image *) NULL; curr=GetNextImageInList(curr)) + { #if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, "overlay: %.20gx%.20g%+.20g%+.20g%s%s\n", - (double) bounds[i].width,(double) bounds[i].height, - (double) bounds[i].x,(double) bounds[i].y, - bounds[i].x < 0?" (unchanged)":"", - cleared?" (pixels cleared)":""); + (void) FormatLocaleFile(stderr,"frame %.20g :-\n",(double) i); #endif - if ( bounds[i].x < 0 ) { - /* - Image frame is exactly the same as the previous frame! - If not adding frames leave it to be cropped down to a null image. - Otherwise mark previous image for deleted, transfering its crop bounds - to the current image. - */ - if ( add_frames && i>=2 ) { - disposals[i-1]=DelDispose; - disposals[i]=NoneDispose; - bounds[i]=bounds[i-1]; - i++; - continue; - } - } - else - { /* - Compare a none disposal against a previous disposal - */ - try_bounds=CompareImagesBounds(prev_image,curr,CompareAnyLayer,exception); - try_cleared=IsBoundsCleared(prev_image,curr,&try_bounds,exception); + Assume none disposal is the best + */ + bounds[i]=CompareImagesBounds(curr->previous,curr,CompareAnyLayer,exception); + cleared=IsBoundsCleared(curr->previous,curr,&bounds[i],exception); + disposals[i-1]=NoneDispose; #if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, "test_prev: %.20gx%.20g%+.20g%+.20g%s\n", - (double) try_bounds.width,(double) try_bounds.height, - (double) try_bounds.x,(double) try_bounds.y, - try_cleared?" (pixels were cleared)":""); + (void) FormatLocaleFile(stderr, "overlay: %.20gx%.20g%+.20g%+.20g%s%s\n", + (double) bounds[i].width,(double) bounds[i].height, + (double) bounds[i].x,(double) bounds[i].y, + bounds[i].x < 0?" (unchanged)":"", + cleared?" (pixels cleared)":""); #endif - if ( (!try_cleared && cleared ) || + if (bounds[i].x < 0) { + /* + Image frame is exactly the same as the previous frame! + If not adding frames leave it to be cropped down to a null image. + Otherwise mark previous image for deleted, transfering its crop bounds + to the current image. + */ + if (add_frames && i>=2) { + disposals[i-1]=DelDispose; + disposals[i]=NoneDispose; + bounds[i]=bounds[i-1]; + i++; + continue; + } + } + else + { + /* + Compare a none disposal against a previous disposal + */ + try_bounds=CompareImagesBounds(prev_image,curr,CompareAnyLayer,exception); + try_cleared=IsBoundsCleared(prev_image,curr,&try_bounds,exception); +#if DEBUG_OPT_FRAME + (void) FormatLocaleFile(stderr, "test_prev: %.20gx%.20g%+.20g%+.20g%s\n", + (double) try_bounds.width,(double) try_bounds.height, + (double) try_bounds.x,(double) try_bounds.y, + try_cleared?" (pixels were cleared)":""); +#endif + if ((!try_cleared && cleared) || try_bounds.width * try_bounds.height - < bounds[i].width * bounds[i].height ) - { - cleared=try_cleared; - bounds[i]=try_bounds; - disposals[i-1]=PreviousDispose; + < bounds[i].width * bounds[i].height) + { + cleared=try_cleared; + bounds[i]=try_bounds; + disposals[i-1]=PreviousDispose; #if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr,"previous: accepted\n"); - } else { - (void) FormatLocaleFile(stderr,"previous: rejected\n"); + (void) FormatLocaleFile(stderr,"previous: accepted\n"); + } else { + (void) FormatLocaleFile(stderr,"previous: rejected\n"); #endif - } + } - /* - If we are allowed lets try a complex frame duplication. - It is useless if the previous image already clears pixels correctly. - This method will always clear all the pixels that need to be cleared. - */ - dup_bounds.width=dup_bounds.height=0; /* no dup, no pixel added */ - if ( add_frames ) - { - dup_image=CloneImage(curr->previous,0,0,MagickTrue,exception); - if (dup_image == (Image *) NULL) - { + /* + If we are allowed lets try a complex frame duplication. + It is useless if the previous image already clears pixels correctly. + This method will always clear all the pixels that need to be cleared. + */ + dup_bounds.width=dup_bounds.height=0; /* no dup, no pixel added */ + if (add_frames) + { + dup_image=CloneImage(curr->previous,0,0,MagickTrue,exception); + if (dup_image == (Image *) NULL) + { + bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); + disposals=(DisposeType *) RelinquishMagickMemory(disposals); + prev_image=DestroyImage(prev_image); + return((Image *) NULL); + } + dup_bounds=CompareImagesBounds(dup_image,curr,CompareClearLayer,exception); + ClearBounds(dup_image,&dup_bounds,exception); + try_bounds=CompareImagesBounds(dup_image,curr,CompareAnyLayer,exception); + if (cleared || + dup_bounds.width*dup_bounds.height + +try_bounds.width*try_bounds.height + < bounds[i].width * bounds[i].height) + { + cleared=MagickFalse; + bounds[i]=try_bounds; + disposals[i-1]=DupDispose; + /* to be finalised later, if found to be optimial */ + } + else + dup_bounds.width=dup_bounds.height=0; + } + /* + Now compare against a simple background disposal + */ + bgnd_image=CloneImage(curr->previous,0,0,MagickTrue,exception); + if (bgnd_image == (Image *) NULL) + { bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); disposals=(DisposeType *) RelinquishMagickMemory(disposals); prev_image=DestroyImage(prev_image); + if (dup_image != (Image *) NULL) + dup_image=DestroyImage(dup_image); return((Image *) NULL); - } - dup_bounds=CompareImagesBounds(dup_image,curr,CompareClearLayer,exception); - ClearBounds(dup_image,&dup_bounds,exception); - try_bounds=CompareImagesBounds(dup_image,curr,CompareAnyLayer,exception); - if ( cleared || - dup_bounds.width*dup_bounds.height - +try_bounds.width*try_bounds.height - < bounds[i].width * bounds[i].height ) - { - cleared=MagickFalse; - bounds[i]=try_bounds; - disposals[i-1]=DupDispose; - /* to be finalised later, if found to be optimial */ - } - else - dup_bounds.width=dup_bounds.height=0; - } - /* - Now compare against a simple background disposal - */ - bgnd_image=CloneImage(curr->previous,0,0,MagickTrue,exception); - if (bgnd_image == (Image *) NULL) - { - bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); - disposals=(DisposeType *) RelinquishMagickMemory(disposals); - prev_image=DestroyImage(prev_image); - if ( dup_image != (Image *) NULL) - dup_image=DestroyImage(dup_image); - return((Image *) NULL); - } - bgnd_bounds=bounds[i-1]; /* interum bounds of the previous image */ - ClearBounds(bgnd_image,&bgnd_bounds,exception); - try_bounds=CompareImagesBounds(bgnd_image,curr,CompareAnyLayer,exception); - try_cleared=IsBoundsCleared(bgnd_image,curr,&try_bounds,exception); -#if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, "background: %s\n", - try_cleared?"(pixels cleared)":""); -#endif - if ( try_cleared ) - { - /* - Straight background disposal failed to clear pixels needed! - Lets try expanding the disposal area of the previous frame, to - include the pixels that are cleared. This guaranteed - to work, though may not be the most optimized solution. - */ - try_bounds=CompareImagesBounds(curr->previous,curr,CompareClearLayer,exception); -#if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, "expand_clear: %.20gx%.20g%+.20g%+.20g%s\n", - (double) try_bounds.width,(double) try_bounds.height, - (double) try_bounds.x,(double) try_bounds.y, - try_bounds.x<0?" (no expand nessary)":""); -#endif - if ( bgnd_bounds.x < 0 ) - bgnd_bounds = try_bounds; - else - { -#if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, "expand_bgnd: %.20gx%.20g%+.20g%+.20g\n", - (double) bgnd_bounds.width,(double) bgnd_bounds.height, - (double) bgnd_bounds.x,(double) bgnd_bounds.y ); -#endif - if ( try_bounds.x < bgnd_bounds.x ) - { - bgnd_bounds.width+= bgnd_bounds.x-try_bounds.x; - if ( bgnd_bounds.width < try_bounds.width ) - bgnd_bounds.width = try_bounds.width; - bgnd_bounds.x = try_bounds.x; - } - else - { - try_bounds.width += try_bounds.x - bgnd_bounds.x; - if ( bgnd_bounds.width < try_bounds.width ) - bgnd_bounds.width = try_bounds.width; - } - if ( try_bounds.y < bgnd_bounds.y ) - { - bgnd_bounds.height += bgnd_bounds.y - try_bounds.y; - if ( bgnd_bounds.height < try_bounds.height ) - bgnd_bounds.height = try_bounds.height; - bgnd_bounds.y = try_bounds.y; - } - else - { - try_bounds.height += try_bounds.y - bgnd_bounds.y; - if ( bgnd_bounds.height < try_bounds.height ) - bgnd_bounds.height = try_bounds.height; - } -#if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, " to : %.20gx%.20g%+.20g%+.20g\n", - (double) bgnd_bounds.width,(double) bgnd_bounds.height, - (double) bgnd_bounds.x,(double) bgnd_bounds.y ); -#endif - } + } + bgnd_bounds=bounds[i-1]; /* interum bounds of the previous image */ ClearBounds(bgnd_image,&bgnd_bounds,exception); + try_bounds=CompareImagesBounds(bgnd_image,curr,CompareAnyLayer,exception); + try_cleared=IsBoundsCleared(bgnd_image,curr,&try_bounds,exception); +#if DEBUG_OPT_FRAME + (void) FormatLocaleFile(stderr, "background: %s\n", + try_cleared?"(pixels cleared)":""); +#endif + if (try_cleared) + { + /* + Straight background disposal failed to clear pixels needed! + Lets try expanding the disposal area of the previous frame, to + include the pixels that are cleared. This guaranteed + to work, though may not be the most optimized solution. + */ + try_bounds=CompareImagesBounds(curr->previous,curr,CompareClearLayer,exception); +#if DEBUG_OPT_FRAME + (void) FormatLocaleFile(stderr, "expand_clear: %.20gx%.20g%+.20g%+.20g%s\n", + (double) try_bounds.width,(double) try_bounds.height, + (double) try_bounds.x,(double) try_bounds.y, + try_bounds.x<0?" (no expand nessary)":""); +#endif + if (bgnd_bounds.x < 0) + bgnd_bounds = try_bounds; + else + { +#if DEBUG_OPT_FRAME + (void) FormatLocaleFile(stderr, "expand_bgnd: %.20gx%.20g%+.20g%+.20g\n", + (double) bgnd_bounds.width,(double) bgnd_bounds.height, + (double) bgnd_bounds.x,(double) bgnd_bounds.y ); +#endif + if (try_bounds.x < bgnd_bounds.x) + { + bgnd_bounds.width+= bgnd_bounds.x-try_bounds.x; + if (bgnd_bounds.width < try_bounds.width) + bgnd_bounds.width = try_bounds.width; + bgnd_bounds.x = try_bounds.x; + } + else + { + try_bounds.width += try_bounds.x - bgnd_bounds.x; + if (bgnd_bounds.width < try_bounds.width) + bgnd_bounds.width = try_bounds.width; + } + if (try_bounds.y < bgnd_bounds.y) + { + bgnd_bounds.height += bgnd_bounds.y - try_bounds.y; + if (bgnd_bounds.height < try_bounds.height) + bgnd_bounds.height = try_bounds.height; + bgnd_bounds.y = try_bounds.y; + } + else + { + try_bounds.height += try_bounds.y - bgnd_bounds.y; + if (bgnd_bounds.height < try_bounds.height) + bgnd_bounds.height = try_bounds.height; + } +#if DEBUG_OPT_FRAME + (void) FormatLocaleFile(stderr, " to : %.20gx%.20g%+.20g%+.20g\n", + (double) bgnd_bounds.width,(double) bgnd_bounds.height, + (double) bgnd_bounds.x,(double) bgnd_bounds.y ); +#endif + } + ClearBounds(bgnd_image,&bgnd_bounds,exception); #if DEBUG_OPT_FRAME /* Something strange is happening with a specific animation * CompareAnyLayers (normal method) and CompareClearLayers returns the whole @@ -1206,850 +1206,850 @@ static Image *OptimizeLayerFrames(const Image *image,const LayerMethod method, * to see, or writet he image at this point it is hard to tell what is wrong! * Only CompareOverlay seemed to return something sensible. */ - try_bounds=CompareImagesBounds(bgnd_image,curr,CompareClearLayer,exception); - (void) FormatLocaleFile(stderr, "expand_ctst: %.20gx%.20g%+.20g%+.20g\n", - (double) try_bounds.width,(double) try_bounds.height, - (double) try_bounds.x,(double) try_bounds.y ); - try_bounds=CompareImagesBounds(bgnd_image,curr,CompareAnyLayer,exception); - try_cleared=IsBoundsCleared(bgnd_image,curr,&try_bounds,exception); - (void) FormatLocaleFile(stderr, "expand_any : %.20gx%.20g%+.20g%+.20g%s\n", - (double) try_bounds.width,(double) try_bounds.height, - (double) try_bounds.x,(double) try_bounds.y, - try_cleared?" (pixels cleared)":""); + try_bounds=CompareImagesBounds(bgnd_image,curr,CompareClearLayer,exception); + (void) FormatLocaleFile(stderr, "expand_ctst: %.20gx%.20g%+.20g%+.20g\n", + (double) try_bounds.width,(double) try_bounds.height, + (double) try_bounds.x,(double) try_bounds.y ); + try_bounds=CompareImagesBounds(bgnd_image,curr,CompareAnyLayer,exception); + try_cleared=IsBoundsCleared(bgnd_image,curr,&try_bounds,exception); + (void) FormatLocaleFile(stderr, "expand_any : %.20gx%.20g%+.20g%+.20g%s\n", + (double) try_bounds.width,(double) try_bounds.height, + (double) try_bounds.x,(double) try_bounds.y, + try_cleared?" (pixels cleared)":""); #endif - try_bounds=CompareImagesBounds(bgnd_image,curr,CompareOverlayLayer,exception); + try_bounds=CompareImagesBounds(bgnd_image,curr,CompareOverlayLayer,exception); #if DEBUG_OPT_FRAME - try_cleared=IsBoundsCleared(bgnd_image,curr,&try_bounds,exception); - (void) FormatLocaleFile(stderr, "expand_test: %.20gx%.20g%+.20g%+.20g%s\n", - (double) try_bounds.width,(double) try_bounds.height, - (double) try_bounds.x,(double) try_bounds.y, - try_cleared?" (pixels cleared)":""); + try_cleared=IsBoundsCleared(bgnd_image,curr,&try_bounds,exception); + (void) FormatLocaleFile(stderr, "expand_test: %.20gx%.20g%+.20g%+.20g%s\n", + (double) try_bounds.width,(double) try_bounds.height, + (double) try_bounds.x,(double) try_bounds.y, + try_cleared?" (pixels cleared)":""); #endif - } - /* - Test if this background dispose is smaller than any of the - other methods we tryed before this (including duplicated frame) - */ - if ( cleared || - bgnd_bounds.width*bgnd_bounds.height + } + /* + Test if this background dispose is smaller than any of the + other methods we tryed before this (including duplicated frame) + */ + if (cleared || + bgnd_bounds.width*bgnd_bounds.height +try_bounds.width*try_bounds.height - < bounds[i-1].width*bounds[i-1].height - +dup_bounds.width*dup_bounds.height - +bounds[i].width*bounds[i].height ) - { - cleared=MagickFalse; - bounds[i-1]=bgnd_bounds; - bounds[i]=try_bounds; - if ( disposals[i-1] == DupDispose ) - dup_image=DestroyImage(dup_image); - disposals[i-1]=BackgroundDispose; + < bounds[i-1].width*bounds[i-1].height + +dup_bounds.width*dup_bounds.height + +bounds[i].width*bounds[i].height) + { + cleared=MagickFalse; + bounds[i-1]=bgnd_bounds; + bounds[i]=try_bounds; + if (disposals[i-1] == DupDispose) + dup_image=DestroyImage(dup_image); + disposals[i-1]=BackgroundDispose; #if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr,"expand_bgnd: accepted\n"); - } else { - (void) FormatLocaleFile(stderr,"expand_bgnd: reject\n"); + (void) FormatLocaleFile(stderr,"expand_bgnd: accepted\n"); + } else { + (void) FormatLocaleFile(stderr,"expand_bgnd: reject\n"); #endif - } - } - /* - Finalise choice of dispose, set new prev_image, - and junk any extra images as appropriate, - */ - if ( disposals[i-1] == DupDispose ) - { - if (bgnd_image != (Image *) NULL) - bgnd_image=DestroyImage(bgnd_image); - prev_image=DestroyImage(prev_image); - prev_image=dup_image, dup_image=(Image *) NULL; - bounds[i+1]=bounds[i]; - bounds[i]=dup_bounds; - disposals[i-1]=DupDispose; - disposals[i]=BackgroundDispose; - i++; - } - else - { - if ( dup_image != (Image *) NULL) - dup_image=DestroyImage(dup_image); - if ( disposals[i-1] != PreviousDispose ) - prev_image=DestroyImage(prev_image); - if ( disposals[i-1] == BackgroundDispose ) - prev_image=bgnd_image, bgnd_image=(Image *) NULL; - if (bgnd_image != (Image *) NULL) - bgnd_image=DestroyImage(bgnd_image); - if ( disposals[i-1] == NoneDispose ) - { - prev_image=ReferenceImage(curr->previous); - if (prev_image == (Image *) NULL) - { - bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); - disposals=(DisposeType *) RelinquishMagickMemory(disposals); - return((Image *) NULL); - } - } + } + } + /* + Finalise choice of dispose, set new prev_image, + and junk any extra images as appropriate, + */ + if (disposals[i-1] == DupDispose) + { + if (bgnd_image != (Image *) NULL) + bgnd_image=DestroyImage(bgnd_image); + prev_image=DestroyImage(prev_image); + prev_image=dup_image, dup_image=(Image *) NULL; + bounds[i+1]=bounds[i]; + bounds[i]=dup_bounds; + disposals[i-1]=DupDispose; + disposals[i]=BackgroundDispose; + i++; + } + else + { + if (dup_image != (Image *) NULL) + dup_image=DestroyImage(dup_image); + if (disposals[i-1] != PreviousDispose) + prev_image=DestroyImage(prev_image); + if (disposals[i-1] == BackgroundDispose) + prev_image=bgnd_image, bgnd_image=(Image *) NULL; + if (bgnd_image != (Image *) NULL) + bgnd_image=DestroyImage(bgnd_image); + if (disposals[i-1] == NoneDispose) + { + prev_image=ReferenceImage(curr->previous); + if (prev_image == (Image *) NULL) + { + bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); + disposals=(DisposeType *) RelinquishMagickMemory(disposals); + return((Image *) NULL); + } + } - } - assert(prev_image != (Image *) NULL); - disposals[i]=disposals[i-1]; + } + assert(prev_image != (Image *) NULL); + disposals[i]=disposals[i-1]; #if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, "final %.20g : %s %.20gx%.20g%+.20g%+.20g\n", - (double) i-1, - CommandOptionToMnemonic(MagickDisposeOptions,disposals[i-1]), - (double) bounds[i-1].width,(double) bounds[i-1].height, - (double) bounds[i-1].x,(double) bounds[i-1].y ); + (void) FormatLocaleFile(stderr, "final %.20g : %s %.20gx%.20g%+.20g%+.20g\n", + (double) i-1, + CommandOptionToMnemonic(MagickDisposeOptions,disposals[i-1]), + (double) bounds[i-1].width,(double) bounds[i-1].height, + (double) bounds[i-1].x,(double) bounds[i-1].y ); #endif #if DEBUG_OPT_FRAME - (void) FormatLocaleFile(stderr, "interum %.20g : %s %.20gx%.20g%+.20g%+.20g\n", - (double) i, - CommandOptionToMnemonic(MagickDisposeOptions,disposals[i]), - (double) bounds[i].width,(double) bounds[i].height, - (double) bounds[i].x,(double) bounds[i].y ); - (void) FormatLocaleFile(stderr,"\n"); + (void) FormatLocaleFile(stderr, "interum %.20g : %s %.20gx%.20g%+.20g%+.20g\n", + (double) i, + CommandOptionToMnemonic(MagickDisposeOptions,disposals[i]), + (double) bounds[i].width,(double) bounds[i].height, + (double) bounds[i].x,(double) bounds[i].y ); + (void) FormatLocaleFile(stderr,"\n"); #endif - i++; - } - prev_image=DestroyImage(prev_image); - /* - Optimize all images in sequence. - */ - sans_exception=AcquireExceptionInfo(); - i=0; - curr=GetFirstImageInList(image); - optimized_image=NewImageList(); - while ( curr != (const Image *) NULL ) - { - prev_image=CloneImage(curr,0,0,MagickTrue,exception); - if (prev_image == (Image *) NULL) - break; - if (prev_image->alpha_trait == UndefinedPixelTrait) - (void) SetImageAlphaChannel(prev_image,OpaqueAlphaChannel,exception); - if ( disposals[i] == DelDispose ) { - size_t time = 0; - while ( disposals[i] == DelDispose ) { - time += curr->delay*1000/curr->ticks_per_second; - curr=GetNextImageInList(curr); i++; - } - time += curr->delay*1000/curr->ticks_per_second; - prev_image->ticks_per_second = 100L; - prev_image->delay = time*prev_image->ticks_per_second/1000; } - bgnd_image=CropImage(prev_image,&bounds[i],sans_exception); prev_image=DestroyImage(prev_image); - if (bgnd_image == (Image *) NULL) - break; - bgnd_image->dispose=disposals[i]; - if ( disposals[i] == DupDispose ) { - bgnd_image->delay=0; - bgnd_image->dispose=NoneDispose; - } - else - curr=GetNextImageInList(curr); - AppendImageToList(&optimized_image,bgnd_image); - i++; - } - sans_exception=DestroyExceptionInfo(sans_exception); - bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); - disposals=(DisposeType *) RelinquishMagickMemory(disposals); - if (curr != (Image *) NULL) + /* + Optimize all images in sequence. + */ + sans_exception=AcquireExceptionInfo(); + i=0; + curr=GetFirstImageInList(image); + optimized_image=NewImageList(); + while (curr != (const Image *) NULL) { - optimized_image=DestroyImageList(optimized_image); - return((Image *) NULL); + prev_image=CloneImage(curr,0,0,MagickTrue,exception); + if (prev_image == (Image *) NULL) + break; + if (prev_image->alpha_trait == UndefinedPixelTrait) + (void) SetImageAlphaChannel(prev_image,OpaqueAlphaChannel,exception); + if (disposals[i] == DelDispose) { + size_t time = 0; + while (disposals[i] == DelDispose) { + time += curr->delay*1000/curr->ticks_per_second; + curr=GetNextImageInList(curr); + i++; + } + time += curr->delay*1000/curr->ticks_per_second; + prev_image->ticks_per_second = 100L; + prev_image->delay = time*prev_image->ticks_per_second/1000; + } + bgnd_image=CropImage(prev_image,&bounds[i],sans_exception); + prev_image=DestroyImage(prev_image); + if (bgnd_image == (Image *) NULL) + break; + bgnd_image->dispose=disposals[i]; + if (disposals[i] == DupDispose) { + bgnd_image->delay=0; + bgnd_image->dispose=NoneDispose; + } + else + curr=GetNextImageInList(curr); + AppendImageToList(&optimized_image,bgnd_image); + i++; } - return(GetFirstImageInList(optimized_image)); + sans_exception=DestroyExceptionInfo(sans_exception); + bounds=(RectangleInfo *) RelinquishMagickMemory(bounds); + disposals=(DisposeType *) RelinquishMagickMemory(disposals); + if (curr != (Image *) NULL) + { + optimized_image=DestroyImageList(optimized_image); + return((Image *) NULL); + } + return(GetFirstImageInList(optimized_image)); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% O p t i m i z e I m a g e L a y e r s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% OptimizeImageLayers() compares each image the GIF disposed forms of the -% previous image in the sequence. From this it attempts to select the -% smallest cropped image to replace each frame, while preserving the results -% of the GIF animation. -% -% The format of the OptimizeImageLayers method is: -% -% Image *OptimizeImageLayers(const Image *image, -% ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % O p t i m i z e I m a g e L a y e r s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % OptimizeImageLayers() compares each image the GIF disposed forms of the + % previous image in the sequence. From this it attempts to select the + % smallest cropped image to replace each frame, while preserving the results + % of the GIF animation. + % + % The format of the OptimizeImageLayers method is: + % + % Image *OptimizeImageLayers(const Image *image, + % ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image. + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport Image *OptimizeImageLayers(const Image *image, - ExceptionInfo *exception) + ExceptionInfo *exception) { - return(OptimizeLayerFrames(image,OptimizeImageLayer,exception)); + return(OptimizeLayerFrames(image,OptimizeImageLayer,exception)); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% O p t i m i z e P l u s I m a g e L a y e r s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% OptimizeImagePlusLayers() is exactly as OptimizeImageLayers(), but may -% also add or even remove extra frames in the animation, if it improves -% the total number of pixels in the resulting GIF animation. -% -% The format of the OptimizePlusImageLayers method is: -% -% Image *OptimizePlusImageLayers(const Image *image, -% ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % O p t i m i z e P l u s I m a g e L a y e r s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % OptimizeImagePlusLayers() is exactly as OptimizeImageLayers(), but may + % also add or even remove extra frames in the animation, if it improves + % the total number of pixels in the resulting GIF animation. + % + % The format of the OptimizePlusImageLayers method is: + % + % Image *OptimizePlusImageLayers(const Image *image, + % ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image. + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport Image *OptimizePlusImageLayers(const Image *image, - ExceptionInfo *exception) + ExceptionInfo *exception) { - return OptimizeLayerFrames(image,OptimizePlusLayer,exception); + return OptimizeLayerFrames(image,OptimizePlusLayer,exception); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% O p t i m i z e I m a g e T r a n s p a r e n c y % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% OptimizeImageTransparency() takes a frame optimized GIF animation, and -% compares the overlayed pixels against the disposal image resulting from all -% the previous frames in the animation. Any pixel that does not change the -% disposal image (and thus does not effect the outcome of an overlay) is made -% transparent. -% -% WARNING: This modifies the current images directly, rather than generate -% a new image sequence. -% -% The format of the OptimizeImageTransperency method is: -% -% void OptimizeImageTransperency(Image *image,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image sequence -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % O p t i m i z e I m a g e T r a n s p a r e n c y % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % OptimizeImageTransparency() takes a frame optimized GIF animation, and + % compares the overlayed pixels against the disposal image resulting from all + % the previous frames in the animation. Any pixel that does not change the + % disposal image (and thus does not effect the outcome of an overlay) is made + % transparent. + % + % WARNING: This modifies the current images directly, rather than generate + % a new image sequence. + % + % The format of the OptimizeImageTransperency method is: + % + % void OptimizeImageTransperency(Image *image,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image sequence + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport void OptimizeImageTransparency(const Image *image, - ExceptionInfo *exception) + ExceptionInfo *exception) { - Image + Image *dispose_image; - register Image + register Image *next; - /* - Run the image through the animation sequence - */ - assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - next=GetFirstImageInList(image); - dispose_image=CloneImage(next,next->page.width,next->page.height, - MagickTrue,exception); - if (dispose_image == (Image *) NULL) - return; - dispose_image->page=next->page; - dispose_image->page.x=0; - dispose_image->page.y=0; - dispose_image->dispose=NoneDispose; - dispose_image->background_color.alpha_trait=BlendPixelTrait; - dispose_image->background_color.alpha=(MagickRealType) TransparentAlpha; - (void) SetImageBackgroundColor(dispose_image,exception); - - while ( next != (Image *) NULL ) - { - Image - *current_image; - /* - Overlay this frame's image over the previous disposal image - */ - current_image=CloneImage(dispose_image,0,0,MagickTrue,exception); - if (current_image == (Image *) NULL) - { - dispose_image=DestroyImage(dispose_image); + Run the image through the animation sequence + */ + assert(image != (Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + next=GetFirstImageInList(image); + dispose_image=CloneImage(next,next->page.width,next->page.height, + MagickTrue,exception); + if (dispose_image == (Image *) NULL) return; - } - (void) CompositeImage(current_image,next,next->alpha_trait != UndefinedPixelTrait ? - OverCompositeOp : CopyCompositeOp,MagickTrue,next->page.x,next->page.y, - exception); - /* - At this point the image would be displayed, for the delay period - ** - Work out the disposal of the previous image - */ - if (next->dispose == BackgroundDispose) - { - RectangleInfo - bounds=next->page; + dispose_image->page=next->page; + dispose_image->page.x=0; + dispose_image->page.y=0; + dispose_image->dispose=NoneDispose; + dispose_image->background_color.alpha_trait=BlendPixelTrait; + dispose_image->background_color.alpha=(MagickRealType) TransparentAlpha; + (void) SetImageBackgroundColor(dispose_image,exception); - bounds.width=next->columns; - bounds.height=next->rows; - if (bounds.x < 0) - { - bounds.width+=bounds.x; - bounds.x=0; - } - if ((ssize_t) (bounds.x+bounds.width) > (ssize_t) current_image->columns) - bounds.width=current_image->columns-bounds.x; - if (bounds.y < 0) - { - bounds.height+=bounds.y; - bounds.y=0; - } - if ((ssize_t) (bounds.y+bounds.height) > (ssize_t) current_image->rows) - bounds.height=current_image->rows-bounds.y; - ClearBounds(current_image,&bounds,exception); - } - if (next->dispose != PreviousDispose) - { - dispose_image=DestroyImage(dispose_image); - dispose_image=current_image; - } - else - current_image=DestroyImage(current_image); + while (next != (Image *) NULL) + { + Image + *current_image; - /* - Optimize Transparency of the next frame (if present) - */ - next=GetNextImageInList(next); - if (next != (Image *) NULL) { - (void) CompositeImage(next,dispose_image,ChangeMaskCompositeOp, - MagickTrue,-(next->page.x),-(next->page.y),exception); + /* + Overlay this frame's image over the previous disposal image + */ + current_image=CloneImage(dispose_image,0,0,MagickTrue,exception); + if (current_image == (Image *) NULL) + { + dispose_image=DestroyImage(dispose_image); + return; + } + (void) CompositeImage(current_image,next,next->alpha_trait != UndefinedPixelTrait ? + OverCompositeOp : CopyCompositeOp,MagickTrue,next->page.x,next->page.y, + exception); + /* + At this point the image would be displayed, for the delay period + ** + Work out the disposal of the previous image + */ + if (next->dispose == BackgroundDispose) + { + RectangleInfo + bounds=next->page; + + bounds.width=next->columns; + bounds.height=next->rows; + if (bounds.x < 0) + { + bounds.width+=bounds.x; + bounds.x=0; + } + if ((ssize_t) (bounds.x+bounds.width) > (ssize_t) current_image->columns) + bounds.width=current_image->columns-bounds.x; + if (bounds.y < 0) + { + bounds.height+=bounds.y; + bounds.y=0; + } + if ((ssize_t) (bounds.y+bounds.height) > (ssize_t) current_image->rows) + bounds.height=current_image->rows-bounds.y; + ClearBounds(current_image,&bounds,exception); + } + if (next->dispose != PreviousDispose) + { + dispose_image=DestroyImage(dispose_image); + dispose_image=current_image; + } + else + current_image=DestroyImage(current_image); + + /* + Optimize Transparency of the next frame (if present) + */ + next=GetNextImageInList(next); + if (next != (Image *) NULL) { + (void) CompositeImage(next,dispose_image,ChangeMaskCompositeOp, + MagickTrue,-(next->page.x),-(next->page.y),exception); + } } - } - dispose_image=DestroyImage(dispose_image); - return; + dispose_image=DestroyImage(dispose_image); + return; } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% R e m o v e D u p l i c a t e L a y e r s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% RemoveDuplicateLayers() removes any image that is exactly the same as the -% next image in the given image list. Image size and virtual canvas offset -% must also match, though not the virtual canvas size itself. -% -% No check is made with regards to image disposal setting, though it is the -% dispose setting of later image that is kept. Also any time delays are also -% added together. As such coalesced image animations should still produce the -% same result, though with duplicte frames merged into a single frame. -% -% The format of the RemoveDuplicateLayers method is: -% -% void RemoveDuplicateLayers(Image **image,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o images: the image list -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % R e m o v e D u p l i c a t e L a y e r s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % RemoveDuplicateLayers() removes any image that is exactly the same as the + % next image in the given image list. Image size and virtual canvas offset + % must also match, though not the virtual canvas size itself. + % + % No check is made with regards to image disposal setting, though it is the + % dispose setting of later image that is kept. Also any time delays are also + % added together. As such coalesced image animations should still produce the + % same result, though with duplicte frames merged into a single frame. + % + % The format of the RemoveDuplicateLayers method is: + % + % void RemoveDuplicateLayers(Image **image,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o images: the image list + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport void RemoveDuplicateLayers(Image **images, - ExceptionInfo *exception) + ExceptionInfo *exception) { - register Image + register Image *curr, *next; - RectangleInfo - bounds; + RectangleInfo + bounds; - assert((*images) != (const Image *) NULL); - assert((*images)->signature == MagickCoreSignature); - if ((*images)->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*images)->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); + assert((*images) != (const Image *) NULL); + assert((*images)->signature == MagickCoreSignature); + if ((*images)->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*images)->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); - curr=GetFirstImageInList(*images); - for (; (next=GetNextImageInList(curr)) != (Image *) NULL; curr=next) - { - if ( curr->columns != next->columns || curr->rows != next->rows - || curr->page.x != next->page.x || curr->page.y != next->page.y ) - continue; - bounds=CompareImagesBounds(curr,next,CompareAnyLayer,exception); - if ( bounds.x < 0 ) { - /* - the two images are the same, merge time delays and delete one. - */ - size_t time; - time = curr->delay*1000/curr->ticks_per_second; - time += next->delay*1000/next->ticks_per_second; - next->ticks_per_second = 100L; - next->delay = time*curr->ticks_per_second/1000; - next->iterations = curr->iterations; - *images = curr; - (void) DeleteImageFromList(images); + curr=GetFirstImageInList(*images); + for (; (next=GetNextImageInList(curr)) != (Image *) NULL; curr=next) + { + if (curr->columns != next->columns || curr->rows != next->rows + || curr->page.x != next->page.x || curr->page.y != next->page.y) + continue; + bounds=CompareImagesBounds(curr,next,CompareAnyLayer,exception); + if (bounds.x < 0) { + /* + the two images are the same, merge time delays and delete one. + */ + size_t time; + time = curr->delay*1000/curr->ticks_per_second; + time += next->delay*1000/next->ticks_per_second; + next->ticks_per_second = 100L; + next->delay = time*curr->ticks_per_second/1000; + next->iterations = curr->iterations; + *images = curr; + (void) DeleteImageFromList(images); + } } - } - *images = GetFirstImageInList(*images); + *images = GetFirstImageInList(*images); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% R e m o v e Z e r o D e l a y L a y e r s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% RemoveZeroDelayLayers() removes any image that as a zero delay time. Such -% images generally represent intermediate or partial updates in GIF -% animations used for file optimization. They are not ment to be displayed -% to users of the animation. Viewable images in an animation should have a -% time delay of 3 or more centi-seconds (hundredths of a second). -% -% However if all the frames have a zero time delay, then either the animation -% is as yet incomplete, or it is not a GIF animation. This a non-sensible -% situation, so no image will be removed and a 'Zero Time Animation' warning -% (exception) given. -% -% No warning will be given if no image was removed because all images had an -% appropriate non-zero time delay set. -% -% Due to the special requirements of GIF disposal handling, GIF animations -% should be coalesced first, before calling this function, though that is not -% a requirement. -% -% The format of the RemoveZeroDelayLayers method is: -% -% void RemoveZeroDelayLayers(Image **image,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o images: the image list -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % R e m o v e Z e r o D e l a y L a y e r s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % RemoveZeroDelayLayers() removes any image that as a zero delay time. Such + % images generally represent intermediate or partial updates in GIF + % animations used for file optimization. They are not ment to be displayed + % to users of the animation. Viewable images in an animation should have a + % time delay of 3 or more centi-seconds (hundredths of a second). + % + % However if all the frames have a zero time delay, then either the animation + % is as yet incomplete, or it is not a GIF animation. This a non-sensible + % situation, so no image will be removed and a 'Zero Time Animation' warning + % (exception) given. + % + % No warning will be given if no image was removed because all images had an + % appropriate non-zero time delay set. + % + % Due to the special requirements of GIF disposal handling, GIF animations + % should be coalesced first, before calling this function, though that is not + % a requirement. + % + % The format of the RemoveZeroDelayLayers method is: + % + % void RemoveZeroDelayLayers(Image **image,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o images: the image list + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport void RemoveZeroDelayLayers(Image **images, - ExceptionInfo *exception) + ExceptionInfo *exception) { - Image + Image *i; - assert((*images) != (const Image *) NULL); - assert((*images)->signature == MagickCoreSignature); - if ((*images)->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*images)->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); + assert((*images) != (const Image *) NULL); + assert((*images)->signature == MagickCoreSignature); + if ((*images)->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*images)->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); - i=GetFirstImageInList(*images); - for ( ; i != (Image *) NULL; i=GetNextImageInList(i)) - if ( i->delay != 0L ) break; - if ( i == (Image *) NULL ) { - (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning, - "ZeroTimeAnimation","`%s'",GetFirstImageInList(*images)->filename); - return; - } - i=GetFirstImageInList(*images); - while ( i != (Image *) NULL ) - { - if ( i->delay == 0L ) { - (void) DeleteImageFromList(&i); - *images=i; + i=GetFirstImageInList(*images); + for ( ; i != (Image *) NULL; i=GetNextImageInList(i)) + if (i->delay != 0L) break; + if (i == (Image *) NULL) { + (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning, + "ZeroTimeAnimation","`%s'",GetFirstImageInList(*images)->filename); + return; } - else - i=GetNextImageInList(i); - } - *images=GetFirstImageInList(*images); + i=GetFirstImageInList(*images); + while (i != (Image *) NULL) + { + if (i->delay == 0L) { + (void) DeleteImageFromList(&i); + *images=i; + } + else + i=GetNextImageInList(i); + } + *images=GetFirstImageInList(*images); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% C o m p o s i t e L a y e r s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% CompositeLayers() compose the source image sequence over the destination -% image sequence, starting with the current image in both lists. -% -% Each layer from the two image lists are composted together until the end of -% one of the image lists is reached. The offset of each composition is also -% adjusted to match the virtual canvas offsets of each layer. As such the -% given offset is relative to the virtual canvas, and not the actual image. -% -% Composition uses given x and y offsets, as the 'origin' location of the -% source images virtual canvas (not the real image) allowing you to compose a -% list of 'layer images' into the destiantioni images. This makes it well -% sutiable for directly composing 'Clears Frame Animations' or 'Coaleased -% Animations' onto a static or other 'Coaleased Animation' destination image -% list. GIF disposal handling is not looked at. -% -% Special case:- If one of the image sequences is the last image (just a -% single image remaining), that image is repeatally composed with all the -% images in the other image list. Either the source or destination lists may -% be the single image, for this situation. -% -% In the case of a single destination image (or last image given), that image -% will ve cloned to match the number of images remaining in the source image -% list. -% -% This is equivelent to the "-layer Composite" Shell API operator. -% -% -% The format of the CompositeLayers method is: -% -% void CompositeLayers(Image *destination, const CompositeOperator -% compose, Image *source, const ssize_t x_offset, const ssize_t y_offset, -% ExceptionInfo *exception); -% -% A description of each parameter follows: -% -% o destination: the destination images and results -% -% o source: source image(s) for the layer composition -% -% o compose, x_offset, y_offset: arguments passed on to CompositeImages() -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % C o m p o s i t e L a y e r s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % CompositeLayers() compose the source image sequence over the destination + % image sequence, starting with the current image in both lists. + % + % Each layer from the two image lists are composted together until the end of + % one of the image lists is reached. The offset of each composition is also + % adjusted to match the virtual canvas offsets of each layer. As such the + % given offset is relative to the virtual canvas, and not the actual image. + % + % Composition uses given x and y offsets, as the 'origin' location of the + % source images virtual canvas (not the real image) allowing you to compose a + % list of 'layer images' into the destiantioni images. This makes it well + % sutiable for directly composing 'Clears Frame Animations' or 'Coaleased + % Animations' onto a static or other 'Coaleased Animation' destination image + % list. GIF disposal handling is not looked at. + % + % Special case:- If one of the image sequences is the last image (just a + % single image remaining), that image is repeatally composed with all the + % images in the other image list. Either the source or destination lists may + % be the single image, for this situation. + % + % In the case of a single destination image (or last image given), that image + % will ve cloned to match the number of images remaining in the source image + % list. + % + % This is equivelent to the "-layer Composite" Shell API operator. + % + % + % The format of the CompositeLayers method is: + % + % void CompositeLayers(Image *destination, const CompositeOperator + % compose, Image *source, const ssize_t x_offset, const ssize_t y_offset, + % ExceptionInfo *exception); + % + % A description of each parameter follows: + % + % o destination: the destination images and results + % + % o source: source image(s) for the layer composition + % + % o compose, x_offset, y_offset: arguments passed on to CompositeImages() + % + % o exception: return any errors or warnings in this structure. + % + */ static inline void CompositeCanvas(Image *destination, - const CompositeOperator compose,Image *source,ssize_t x_offset, - ssize_t y_offset,ExceptionInfo *exception) + const CompositeOperator compose,Image *source,ssize_t x_offset, + ssize_t y_offset,ExceptionInfo *exception) { - const char + const char *value; - x_offset+=source->page.x-destination->page.x; - y_offset+=source->page.y-destination->page.y; - value=GetImageArtifact(source,"compose:outside-overlay"); - (void) CompositeImage(destination,source,compose, - (value != (const char *) NULL) && (IsStringTrue(value) != MagickFalse) ? - MagickFalse : MagickTrue,x_offset,y_offset,exception); + x_offset+=source->page.x-destination->page.x; + y_offset+=source->page.y-destination->page.y; + value=GetImageArtifact(source,"compose:outside-overlay"); + (void) CompositeImage(destination,source,compose, + (value != (const char *) NULL) && (IsStringTrue(value) != MagickFalse) ? + MagickFalse : MagickTrue,x_offset,y_offset,exception); } MagickExport void CompositeLayers(Image *destination, - const CompositeOperator compose, Image *source,const ssize_t x_offset, - const ssize_t y_offset,ExceptionInfo *exception) + const CompositeOperator compose, Image *source,const ssize_t x_offset, + const ssize_t y_offset,ExceptionInfo *exception) { - assert(destination != (Image *) NULL); - assert(destination->signature == MagickCoreSignature); - assert(source != (Image *) NULL); - assert(source->signature == MagickCoreSignature); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - if (source->debug != MagickFalse || destination->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s - %s", - source->filename,destination->filename); + assert(destination != (Image *) NULL); + assert(destination->signature == MagickCoreSignature); + assert(source != (Image *) NULL); + assert(source->signature == MagickCoreSignature); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + if (source->debug != MagickFalse || destination->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s - %s", + source->filename,destination->filename); - /* - Overlay single source image over destation image/list - */ - if ( source->next == (Image *) NULL ) - while ( destination != (Image *) NULL ) + /* + Overlay single source image over destation image/list + */ + if (source->next == (Image *) NULL) + while (destination != (Image *) NULL) + { + CompositeCanvas(destination, compose, source, x_offset, y_offset, + exception); + destination=GetNextImageInList(destination); + } + + /* + Overlay source image list over single destination. + Multiple clones of destination image are created to match source list. + Original Destination image becomes first image of generated list. + As such the image list pointer does not require any change in caller. + Some animation attributes however also needs coping in this case. + */ + else if (destination->next == (Image *) NULL) { - CompositeCanvas(destination, compose, source, x_offset, y_offset, - exception); - destination=GetNextImageInList(destination); + Image *dest = CloneImage(destination,0,0,MagickTrue,exception); + + CompositeCanvas(destination, compose, source, x_offset, y_offset, + exception); + /* copy source image attributes ? */ + if (source->next != (Image *) NULL) + { + destination->delay = source->delay; + destination->iterations = source->iterations; + } + source=GetNextImageInList(source); + + while (source != (Image *) NULL) + { + AppendImageToList(&destination, + CloneImage(dest,0,0,MagickTrue,exception)); + destination=GetLastImageInList(destination); + + CompositeCanvas(destination, compose, source, x_offset, y_offset, + exception); + destination->delay = source->delay; + destination->iterations = source->iterations; + source=GetNextImageInList(source); + } + dest=DestroyImage(dest); } - /* - Overlay source image list over single destination. - Multiple clones of destination image are created to match source list. - Original Destination image becomes first image of generated list. - As such the image list pointer does not require any change in caller. - Some animation attributes however also needs coping in this case. - */ - else if ( destination->next == (Image *) NULL ) - { - Image *dest = CloneImage(destination,0,0,MagickTrue,exception); - - CompositeCanvas(destination, compose, source, x_offset, y_offset, - exception); - /* copy source image attributes ? */ - if ( source->next != (Image *) NULL ) - { - destination->delay = source->delay; - destination->iterations = source->iterations; - } - source=GetNextImageInList(source); - - while ( source != (Image *) NULL ) - { - AppendImageToList(&destination, - CloneImage(dest,0,0,MagickTrue,exception)); - destination=GetLastImageInList(destination); - - CompositeCanvas(destination, compose, source, x_offset, y_offset, - exception); - destination->delay = source->delay; - destination->iterations = source->iterations; - source=GetNextImageInList(source); - } - dest=DestroyImage(dest); - } - - /* - Overlay a source image list over a destination image list - until either list runs out of images. (Does not repeat) - */ - else - while ( source != (Image *) NULL && destination != (Image *) NULL ) - { - CompositeCanvas(destination, compose, source, x_offset, y_offset, - exception); - source=GetNextImageInList(source); - destination=GetNextImageInList(destination); - } + /* + Overlay a source image list over a destination image list + until either list runs out of images. (Does not repeat) + */ + else + while (source != (Image *) NULL && destination != (Image *) NULL) + { + CompositeCanvas(destination, compose, source, x_offset, y_offset, + exception); + source=GetNextImageInList(source); + destination=GetNextImageInList(destination); + } } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% M e r g e I m a g e L a y e r s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% MergeImageLayers() composes all the image layers from the current given -% image onward to produce a single image of the merged layers. -% -% The inital canvas's size depends on the given LayerMethod, and is -% initialized using the first images background color. The images -% are then compositied onto that image in sequence using the given -% composition that has been assigned to each individual image. -% -% The format of the MergeImageLayers is: -% -% Image *MergeImageLayers(Image *image,const LayerMethod method, -% ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image list to be composited together -% -% o method: the method of selecting the size of the initial canvas. -% -% MergeLayer: Merge all layers onto a canvas just large enough -% to hold all the actual images. The virtual canvas of the -% first image is preserved but otherwise ignored. -% -% FlattenLayer: Use the virtual canvas size of first image. -% Images which fall outside this canvas is clipped. -% This can be used to 'fill out' a given virtual canvas. -% -% MosaicLayer: Start with the virtual canvas of the first image, -% enlarging left and right edges to contain all images. -% Images with negative offsets will be clipped. -% -% TrimBoundsLayer: Determine the overall bounds of all the image -% layers just as in "MergeLayer", then adjust the the canvas -% and offsets to be relative to those bounds, without overlaying -% the images. -% -% WARNING: a new image is not returned, the original image -% sequence page data is modified instead. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % M e r g e I m a g e L a y e r s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % MergeImageLayers() composes all the image layers from the current given + % image onward to produce a single image of the merged layers. + % + % The inital canvas's size depends on the given LayerMethod, and is + % initialized using the first images background color. The images + % are then compositied onto that image in sequence using the given + % composition that has been assigned to each individual image. + % + % The format of the MergeImageLayers is: + % + % Image *MergeImageLayers(Image *image,const LayerMethod method, + % ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image list to be composited together + % + % o method: the method of selecting the size of the initial canvas. + % + % MergeLayer: Merge all layers onto a canvas just large enough + % to hold all the actual images. The virtual canvas of the + % first image is preserved but otherwise ignored. + % + % FlattenLayer: Use the virtual canvas size of first image. + % Images which fall outside this canvas is clipped. + % This can be used to 'fill out' a given virtual canvas. + % + % MosaicLayer: Start with the virtual canvas of the first image, + % enlarging left and right edges to contain all images. + % Images with negative offsets will be clipped. + % + % TrimBoundsLayer: Determine the overall bounds of all the image + % layers just as in "MergeLayer", then adjust the the canvas + % and offsets to be relative to those bounds, without overlaying + % the images. + % + % WARNING: a new image is not returned, the original image + % sequence page data is modified instead. + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport Image *MergeImageLayers(Image *image,const LayerMethod method, - ExceptionInfo *exception) + ExceptionInfo *exception) { #define MergeLayersTag "Merge/Layers" - Image + Image *canvas; - MagickBooleanType - proceed; + MagickBooleanType + proceed; - RectangleInfo - page; + RectangleInfo + page; - register const Image + register const Image *next; - size_t - number_images, - height, - width; + size_t + number_images, + height, + width; - ssize_t - scene; + ssize_t + scene; - assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - /* - Determine canvas image size, and its virtual canvas size and offset - */ - page=image->page; - width=image->columns; - height=image->rows; - switch (method) - { + assert(image != (Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + /* + Determine canvas image size, and its virtual canvas size and offset + */ + page=image->page; + width=image->columns; + height=image->rows; + switch (method) + { case TrimBoundsLayer: case MergeLayer: default: { - next=GetNextImageInList(image); - for ( ; next != (Image *) NULL; next=GetNextImageInList(next)) - { - if (page.x > next->page.x) - { - width+=page.x-next->page.x; - page.x=next->page.x; - } - if (page.y > next->page.y) - { - height+=page.y-next->page.y; - page.y=next->page.y; - } - if ((ssize_t) width < (next->page.x+(ssize_t) next->columns-page.x)) - width=(size_t) next->page.x+(ssize_t) next->columns-page.x; - if ((ssize_t) height < (next->page.y+(ssize_t) next->rows-page.y)) - height=(size_t) next->page.y+(ssize_t) next->rows-page.y; - } - break; + next=GetNextImageInList(image); + for ( ; next != (Image *) NULL; next=GetNextImageInList(next)) + { + if (page.x > next->page.x) + { + width+=page.x-next->page.x; + page.x=next->page.x; + } + if (page.y > next->page.y) + { + height+=page.y-next->page.y; + page.y=next->page.y; + } + if ((ssize_t) width < (next->page.x+(ssize_t) next->columns-page.x)) + width=(size_t) next->page.x+(ssize_t) next->columns-page.x; + if ((ssize_t) height < (next->page.y+(ssize_t) next->rows-page.y)) + height=(size_t) next->page.y+(ssize_t) next->rows-page.y; + } + break; } case FlattenLayer: { - if (page.width > 0) - width=page.width; - if (page.height > 0) - height=page.height; - page.x=0; - page.y=0; - break; + if (page.width > 0) + width=page.width; + if (page.height > 0) + height=page.height; + page.x=0; + page.y=0; + break; } case MosaicLayer: { - if (page.width > 0) - width=page.width; - if (page.height > 0) - height=page.height; - for (next=image; next != (Image *) NULL; next=GetNextImageInList(next)) - { - if (method == MosaicLayer) - { - page.x=next->page.x; - page.y=next->page.y; - if ((ssize_t) width < (next->page.x+(ssize_t) next->columns)) - width=(size_t) next->page.x+next->columns; - if ((ssize_t) height < (next->page.y+(ssize_t) next->rows)) - height=(size_t) next->page.y+next->rows; - } - } - page.width=width; - page.height=height; - page.x=0; - page.y=0; + if (page.width > 0) + width=page.width; + if (page.height > 0) + height=page.height; + for (next=image; next != (Image *) NULL; next=GetNextImageInList(next)) + { + if (method == MosaicLayer) + { + page.x=next->page.x; + page.y=next->page.y; + if ((ssize_t) width < (next->page.x+(ssize_t) next->columns)) + width=(size_t) next->page.x+next->columns; + if ((ssize_t) height < (next->page.y+(ssize_t) next->rows)) + height=(size_t) next->page.y+next->rows; + } + } + page.width=width; + page.height=height; + page.x=0; + page.y=0; } break; - } - /* - Set virtual canvas size if not defined. - */ - if (page.width == 0) - page.width=page.x < 0 ? width : width+page.x; - if (page.height == 0) - page.height=page.y < 0 ? height : height+page.y; - /* - Handle "TrimBoundsLayer" method separately to normal 'layer merge'. - */ - if (method == TrimBoundsLayer) + } + /* + Set virtual canvas size if not defined. + */ + if (page.width == 0) + page.width=page.x < 0 ? width : width+page.x; + if (page.height == 0) + page.height=page.y < 0 ? height : height+page.y; + /* + Handle "TrimBoundsLayer" method separately to normal 'layer merge'. + */ + if (method == TrimBoundsLayer) { - number_images=GetImageListLength(image); - for (scene=0; scene < (ssize_t) number_images; scene++) - { - image->page.x-=page.x; - image->page.y-=page.y; - image->page.width=width; - image->page.height=height; + number_images=GetImageListLength(image); + for (scene=0; scene < (ssize_t) number_images; scene++) + { + image->page.x-=page.x; + image->page.y-=page.y; + image->page.width=width; + image->page.height=height; + proceed=SetImageProgress(image,MergeLayersTag,(MagickOffsetType) scene, + number_images); + if (proceed == MagickFalse) + break; + image=GetNextImageInList(image); + if (image == (Image *) NULL) + break; + } + return((Image *) NULL); + } + /* + Create canvas size of width and height, and background color. + */ + canvas=CloneImage(image,width,height,MagickTrue,exception); + if (canvas == (Image *) NULL) + return((Image *) NULL); + (void) SetImageBackgroundColor(canvas,exception); + canvas->page=page; + canvas->dispose=UndefinedDispose; + /* + Compose images onto canvas, with progress monitor + */ + number_images=GetImageListLength(image); + for (scene=0; scene < (ssize_t) number_images; scene++) + { + (void) CompositeImage(canvas,image,image->compose,MagickTrue,image->page.x- + canvas->page.x,image->page.y-canvas->page.y,exception); proceed=SetImageProgress(image,MergeLayersTag,(MagickOffsetType) scene, - number_images); + number_images); if (proceed == MagickFalse) - break; + break; image=GetNextImageInList(image); if (image == (Image *) NULL) - break; - } - return((Image *) NULL); + break; } - /* - Create canvas size of width and height, and background color. - */ - canvas=CloneImage(image,width,height,MagickTrue,exception); - if (canvas == (Image *) NULL) - return((Image *) NULL); - (void) SetImageBackgroundColor(canvas,exception); - canvas->page=page; - canvas->dispose=UndefinedDispose; - /* - Compose images onto canvas, with progress monitor - */ - number_images=GetImageListLength(image); - for (scene=0; scene < (ssize_t) number_images; scene++) - { - (void) CompositeImage(canvas,image,image->compose,MagickTrue,image->page.x- - canvas->page.x,image->page.y-canvas->page.y,exception); - proceed=SetImageProgress(image,MergeLayersTag,(MagickOffsetType) scene, - number_images); - if (proceed == MagickFalse) - break; - image=GetNextImageInList(image); - if (image == (Image *) NULL) - break; - } - return(canvas); + return(canvas); } diff --git a/test/bug-hunting/cve/CVE-2019-14249/dwarf_elf_load_headers.c b/test/bug-hunting/cve/CVE-2019-14249/dwarf_elf_load_headers.c index bca948e8c..12e360d52 100644 --- a/test/bug-hunting/cve/CVE-2019-14249/dwarf_elf_load_headers.c +++ b/test/bug-hunting/cve/CVE-2019-14249/dwarf_elf_load_headers.c @@ -1,9 +1,9 @@ /* -Copyright 2018 David Anderson. All rights reserved. + Copyright 2018 David Anderson. All rights reserved. -Redistribution and use in source and binary forms, with -or without modification, are permitted provided that the -following conditions are met: + Redistribution and use in source and binary forms, with + or without modification, are permitted provided that the + following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following @@ -14,20 +14,20 @@ following conditions are met: disclaimer in the documentation and/or other materials provided with the distribution. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ /* This reads elf headers and creates generic-elf structures containing the Elf headers. */ @@ -83,7 +83,7 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. do { \ unsigned tbyte = sizeof(t) - sizeof(s); \ t = 0; \ - func(((char *)&t)+tbyte ,&s[0],sizeof(s)); \ + func(((char *)&t)+tbyte,&s[0],sizeof(s)); \ } while (0) #else /* LITTLE ENDIAN */ #define ASNAR(func,t,s) \ @@ -130,7 +130,7 @@ is_empty_section(Dwarf_Unsigned type) #if 0 int dwarf_construct_elf_access_path(const char *path, - dwarf_elf_object_access_internals_t **mp,int *errcode) + dwarf_elf_object_access_internals_t **mp,int *errcode) { int fd = -1; int res = 0; @@ -142,7 +142,7 @@ dwarf_construct_elf_access_path(const char *path, return DW_DLV_ERROR; } res = dwarf_construct_elf_access(fd, - path,&mymp,errcode); + path,&mymp,errcode); if (res != DW_DLV_OK) { close(fd); return res; @@ -156,18 +156,18 @@ dwarf_construct_elf_access_path(const char *path, /* Here path is not essential. Pass in with "" if unknown. */ int dwarf_construct_elf_access(int fd, - const char *path, - dwarf_elf_object_access_internals_t **mp,int *errcode) + const char *path, + dwarf_elf_object_access_internals_t **mp,int *errcode) { unsigned ftype = 0; unsigned endian = 0; unsigned offsetsize = 0; Dwarf_Unsigned filesize = 0; dwarf_elf_object_access_internals_t *mfp = 0; - int res = 0; + int res = 0; res = dwarf_object_detector_fd(fd, - &ftype,&endian,&offsetsize, &filesize, errcode); + &ftype,&endian,&offsetsize, &filesize, errcode); if (res != DW_DLV_OK) { return res; } @@ -199,7 +199,7 @@ dwarf_construct_elf_access(int fd, the caller to avoid use of the pointer. */ int dwarf_destruct_elf_access(dwarf_elf_object_access_internals_t* ep, - UNUSEDARG int *errcode) + UNUSEDARG int *errcode) { struct generic_shdr *shp = 0; Dwarf_Unsigned shcount = 0; @@ -208,7 +208,7 @@ dwarf_destruct_elf_access(dwarf_elf_object_access_internals_t* ep, free(ep->f_ehdr); shp = ep->f_shdr; shcount = ep->f_loc_shdr.g_count; - for(i = 0; i < shcount; ++i,++shp) { + for (i = 0; i < shcount; ++i,++shp) { free(shp->gh_rels); shp->gh_rels = 0; free(shp->gh_content); @@ -241,8 +241,8 @@ dwarf_destruct_elf_access(dwarf_elf_object_access_internals_t* ep, static int generic_ehdr_from_32(dwarf_elf_object_access_internals_t *ep, - struct generic_ehdr *ehdr, dw_elf32_ehdr *e, - UNUSEDARG int *errcode) + struct generic_ehdr *ehdr, dw_elf32_ehdr *e, + UNUSEDARG int *errcode) { int i = 0; @@ -274,8 +274,8 @@ generic_ehdr_from_32(dwarf_elf_object_access_internals_t *ep, static int generic_ehdr_from_64(dwarf_elf_object_access_internals_t* ep, - struct generic_ehdr *ehdr, dw_elf64_ehdr *e, - UNUSEDARG int *errcode) + struct generic_ehdr *ehdr, dw_elf64_ehdr *e, + UNUSEDARG int *errcode) { int i = 0; @@ -309,12 +309,12 @@ generic_ehdr_from_64(dwarf_elf_object_access_internals_t* ep, #if 0 /* not used */ static int generic_phdr_from_phdr32(dwarf_elf_object_access_internals_t* ep, - struct generic_phdr **phdr_out, - Dwarf_Unsigned * count_out, - Dwarf_Unsigned offset, - Dwarf_Unsigned entsize, - Dwarf_Unsigned count, - int *errcode) + struct generic_phdr **phdr_out, + Dwarf_Unsigned * count_out, + Dwarf_Unsigned offset, + Dwarf_Unsigned entsize, + Dwarf_Unsigned count, + int *errcode) { dw_elf32_phdr *pph =0; dw_elf32_phdr *orig_pph =0; @@ -324,13 +324,13 @@ generic_phdr_from_phdr32(dwarf_elf_object_access_internals_t* ep, int res = 0; *count_out = 0; - pph = (dw_elf32_phdr *)calloc(count , entsize); - if(pph == 0) { + pph = (dw_elf32_phdr *)calloc(count, entsize); + if (pph == 0) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } gphdr = (struct generic_phdr *)calloc(count,sizeof(*gphdr)); - if(gphdr == 0) { + if (gphdr == 0) { free(pph); *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; @@ -339,14 +339,14 @@ generic_phdr_from_phdr32(dwarf_elf_object_access_internals_t* ep, orig_pph = pph; orig_gphdr = gphdr; res = RRMOA(ep->f_fd,pph,offset,count*entsize, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(pph); free(gphdr); return res; } - for( i = 0; i < count; - ++i, pph++,gphdr++) { + for (i = 0; i < count; + ++i, pph++,gphdr++) { ASNAR(ep->f_copy_word,gphdr->gp_type,pph->p_type); ASNAR(ep->f_copy_word,gphdr->gp_offset,pph->p_offset); ASNAR(ep->f_copy_word,gphdr->gp_vaddr,pph->p_vaddr); @@ -370,12 +370,12 @@ generic_phdr_from_phdr32(dwarf_elf_object_access_internals_t* ep, static int generic_phdr_from_phdr64(dwarf_elf_object_access_internals_t* ep, - struct generic_phdr **phdr_out, - Dwarf_Unsigned * count_out, - Dwarf_Unsigned offset, - Dwarf_Unsigned entsize, - Dwarf_Unsigned count, - int *errcode) + struct generic_phdr **phdr_out, + Dwarf_Unsigned * count_out, + Dwarf_Unsigned offset, + Dwarf_Unsigned entsize, + Dwarf_Unsigned count, + int *errcode) { dw_elf64_phdr *pph =0; dw_elf64_phdr *orig_pph =0; @@ -385,13 +385,13 @@ generic_phdr_from_phdr64(dwarf_elf_object_access_internals_t* ep, Dwarf_Unsigned i = 0; *count_out = 0; - pph = (dw_elf64_phdr *)calloc(count , entsize); - if(pph == 0) { + pph = (dw_elf64_phdr *)calloc(count, entsize); + if (pph == 0) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } gphdr = (struct generic_phdr *)calloc(count,sizeof(*gphdr)); - if(gphdr == 0) { + if (gphdr == 0) { free(pph); *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; @@ -400,14 +400,14 @@ generic_phdr_from_phdr64(dwarf_elf_object_access_internals_t* ep, orig_pph = pph; orig_gphdr = gphdr; res = RRMOA(ep->f_fd,pph,offset,count*entsize, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(pph); free(gphdr); return res; } - for( i = 0; i < count; - ++i, pph++,gphdr++) { + for (i = 0; i < count; + ++i, pph++,gphdr++) { ASNAR(ep->f_copy_word,gphdr->gp_type,pph->p_type); ASNAR(ep->f_copy_word,gphdr->gp_offset,pph->p_offset); ASNAR(ep->f_copy_word,gphdr->gp_vaddr,pph->p_vaddr); @@ -432,11 +432,11 @@ generic_phdr_from_phdr64(dwarf_elf_object_access_internals_t* ep, static int generic_shdr_from_shdr32(dwarf_elf_object_access_internals_t *ep, - Dwarf_Unsigned * count_out, - Dwarf_Unsigned offset, - Dwarf_Unsigned entsize, - Dwarf_Unsigned count, - int *errcode) + Dwarf_Unsigned * count_out, + Dwarf_Unsigned offset, + Dwarf_Unsigned entsize, + Dwarf_Unsigned count, + int *errcode) { dw_elf32_shdr *psh =0; dw_elf32_shdr *orig_psh =0; @@ -446,13 +446,13 @@ generic_shdr_from_shdr32(dwarf_elf_object_access_internals_t *ep, int res = 0; *count_out = 0; - psh = (dw_elf32_shdr *)calloc(count , entsize); - if(!psh) { + psh = (dw_elf32_shdr *)calloc(count, entsize); + if (!psh) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } gshdr = (struct generic_shdr *)calloc(count,sizeof(*gshdr)); - if(!gshdr) { + if (!gshdr) { free(psh); *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; @@ -461,14 +461,14 @@ generic_shdr_from_shdr32(dwarf_elf_object_access_internals_t *ep, orig_psh = psh; orig_gshdr = gshdr; res = RRMOA(ep->f_fd,psh,offset,count*entsize, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(psh); free(gshdr); return res; } - for(i = 0; i < count; - ++i, psh++,gshdr++) { + for (i = 0; i < count; + ++i, psh++,gshdr++) { gshdr->gh_secnum = i; ASNAR(ep->f_copy_word,gshdr->gh_name,psh->sh_name); ASNAR(ep->f_copy_word,gshdr->gh_type,psh->sh_type); @@ -480,7 +480,7 @@ generic_shdr_from_shdr32(dwarf_elf_object_access_internals_t *ep, ASNAR(ep->f_copy_word,gshdr->gh_info,psh->sh_info); ASNAR(ep->f_copy_word,gshdr->gh_addralign,psh->sh_addralign); ASNAR(ep->f_copy_word,gshdr->gh_entsize,psh->sh_entsize); - if (gshdr->gh_type == SHT_REL || gshdr->gh_type == SHT_RELA){ + if (gshdr->gh_type == SHT_REL || gshdr->gh_type == SHT_RELA) { gshdr->gh_reloc_target_secnum = gshdr->gh_info; } } @@ -497,11 +497,11 @@ generic_shdr_from_shdr32(dwarf_elf_object_access_internals_t *ep, static int generic_shdr_from_shdr64(dwarf_elf_object_access_internals_t *ep, - Dwarf_Unsigned * count_out, - Dwarf_Unsigned offset, - Dwarf_Unsigned entsize, - Dwarf_Unsigned count, - int *errcode) + Dwarf_Unsigned * count_out, + Dwarf_Unsigned offset, + Dwarf_Unsigned entsize, + Dwarf_Unsigned count, + int *errcode) { dw_elf64_shdr *psh =0; dw_elf64_shdr *orig_psh =0; @@ -511,13 +511,13 @@ generic_shdr_from_shdr64(dwarf_elf_object_access_internals_t *ep, int res = 0; *count_out = 0; - psh = (dw_elf64_shdr *)calloc(count , entsize); - if(!psh) { + psh = (dw_elf64_shdr *)calloc(count, entsize); + if (!psh) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } gshdr = (struct generic_shdr *)calloc(count,sizeof(*gshdr)); - if(gshdr == 0) { + if (gshdr == 0) { free(psh); *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; @@ -526,14 +526,14 @@ generic_shdr_from_shdr64(dwarf_elf_object_access_internals_t *ep, orig_psh = psh; orig_gshdr = gshdr; res = RRMOA(ep->f_fd,psh,offset,count*entsize, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(psh); free(gshdr); return res; } - for( i = 0; i < count; - ++i, psh++,gshdr++) { + for (i = 0; i < count; + ++i, psh++,gshdr++) { gshdr->gh_secnum = i; ASNAR(ep->f_copy_word,gshdr->gh_name,psh->sh_name); ASNAR(ep->f_copy_word,gshdr->gh_type,psh->sh_type); @@ -545,7 +545,7 @@ generic_shdr_from_shdr64(dwarf_elf_object_access_internals_t *ep, ASNAR(ep->f_copy_word,gshdr->gh_info,psh->sh_info); ASNAR(ep->f_copy_word,gshdr->gh_addralign,psh->sh_addralign); ASNAR(ep->f_copy_word,gshdr->gh_entsize,psh->sh_entsize); - if (gshdr->gh_type == SHT_REL || gshdr->gh_type == SHT_RELA){ + if (gshdr->gh_type == SHT_REL || gshdr->gh_type == SHT_RELA) { gshdr->gh_reloc_target_secnum = gshdr->gh_info; } } @@ -580,7 +580,7 @@ dwarf_generic_elf_load_symbols32( ecount = (long)(size/sizeof(dw_elf32_sym)); size2 = ecount * sizeof(dw_elf32_sym); - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } @@ -596,15 +596,15 @@ dwarf_generic_elf_load_symbols32( return DW_DLV_ERROR; } res = RRMOA(ep->f_fd,psym,offset,size, - ep->f_filesize,errcode); - if(res!= DW_DLV_OK) { + ep->f_filesize,errcode); + if (res!= DW_DLV_OK) { free(psym); free(gsym); return res; } orig_psym = psym; orig_gsym = gsym; - for ( i = 0; i < ecount; ++i,++psym,++gsym) { + for (i = 0; i < ecount; ++i,++psym,++gsym) { Dwarf_Unsigned bind = 0; Dwarf_Unsigned type = 0; @@ -644,7 +644,7 @@ dwarf_generic_elf_load_symbols64( ecount = (long)(size/sizeof(dw_elf64_sym)); size2 = ecount * sizeof(dw_elf64_sym); - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } @@ -660,8 +660,8 @@ dwarf_generic_elf_load_symbols64( return DW_DLV_ERROR; } res = RRMOA(ep->f_fd,psym,offset,size, - ep->f_filesize,errcode); - if(res!= DW_DLV_OK) { + ep->f_filesize,errcode); + if (res!= DW_DLV_OK) { free(psym); free(gsym); *errcode = DW_DLE_ALLOC_FAIL; @@ -669,7 +669,7 @@ dwarf_generic_elf_load_symbols64( } orig_psym = psym; orig_gsym = gsym; - for ( i = 0; i < ecount; ++i,++psym,++gsym) { + for (i = 0; i < ecount; ++i,++psym,++gsym) { Dwarf_Unsigned bind = 0; Dwarf_Unsigned type = 0; @@ -702,19 +702,19 @@ dwarf_generic_elf_load_symbols( struct generic_symentry *gsym = 0; Dwarf_Unsigned count = 0; - if(!secnum) { + if (!secnum) { return DW_DLV_NO_ENTRY; } if (ep->f_offsetsize == 32) { res = dwarf_generic_elf_load_symbols32(ep, - &gsym, - psh->gh_offset,psh->gh_size, - &count,errcode); + &gsym, + psh->gh_offset,psh->gh_size, + &count,errcode); } else if (ep->f_offsetsize == 64) { res = dwarf_generic_elf_load_symbols64(ep, - &gsym, - psh->gh_offset,psh->gh_size, - &count,errcode); + &gsym, + psh->gh_offset,psh->gh_size, + &count,errcode); } else { *errcode = DW_DLE_OFFSET_SIZE; return DW_DLV_ERROR; @@ -736,15 +736,15 @@ dwarf_load_elf_dynsym_symbols( Dwarf_Unsigned secnum = ep->f_dynsym_sect_index; struct generic_shdr * psh = 0; - if(!secnum) { + if (!secnum) { return DW_DLV_NO_ENTRY; } psh = ep->f_shdr + secnum; res = dwarf_generic_elf_load_symbols(ep, - secnum, - psh, - &gsym, - &count,errcode); + secnum, + psh, + &gsym, + &count,errcode); if (res == DW_DLV_OK) { ep->f_dynsym = gsym; ep->f_loc_dynsym.g_count = count; @@ -763,15 +763,15 @@ _dwarf_load_elf_symtab_symbols( Dwarf_Unsigned secnum = ep->f_symtab_sect_index; struct generic_shdr * psh = 0; - if(!secnum) { + if (!secnum) { return DW_DLV_NO_ENTRY; } psh = ep->f_shdr + secnum; res = dwarf_generic_elf_load_symbols(ep, - secnum, - psh, - &gsym, - &count,errcode); + secnum, + psh, + &gsym, + &count,errcode); if (res == DW_DLV_OK) { ep->f_symtab = gsym; ep->f_loc_symtab.g_count = count; @@ -794,11 +794,11 @@ generic_rel_from_rela32( ecount = size/sizeof(dw_elf32_rela); size2 = ecount * sizeof(dw_elf32_rela); - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; - return DW_DLV_ERROR; + return DW_DLV_ERROR; } - for ( i = 0; i < ecount; ++i,++relp,++grel) { + for (i = 0; i < ecount; ++i,++relp,++grel) { ASNAR(ep->f_copy_word,grel->gr_offset,relp->r_offset); ASNAR(ep->f_copy_word,grel->gr_info,relp->r_info); /* addend signed */ @@ -828,16 +828,16 @@ generic_rel_from_rela64( ecount = size/sizeof(dw_elf64_rela); size2 = ecount * sizeof(dw_elf64_rela); - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; - return DW_DLV_ERROR; + return DW_DLV_ERROR; } - for ( i = 0; i < ecount; ++i,++relp,++grel) { + for (i = 0; i < ecount; ++i,++relp,++grel) { ASNAR(ep->f_copy_word,grel->gr_offset,relp->r_offset); ASNAR(ep->f_copy_word,grel->gr_info,relp->r_info); ASNAR(ep->f_copy_word,grel->gr_addend,relp->r_addend); SIGN_EXTEND(grel->gr_addend,sizeof(relp->r_addend)); - if (ismips64 && objlittleendian ) { + if (ismips64 && objlittleendian) { char realsym[4]; memcpy(realsym,&relp->r_info,sizeof(realsym)); @@ -876,11 +876,11 @@ generic_rel_from_rel32( ecount = size/sizeof(dw_elf32_rel); size2 = ecount * sizeof(dw_elf32_rel); - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; - return DW_DLV_ERROR; + return DW_DLV_ERROR; } - for ( i = 0; i < ecount; ++i,++relp,++grel) { + for (i = 0; i < ecount; ++i,++relp,++grel) { grel->gr_isrela = 0; ASNAR(ep->f_copy_word,grel->gr_offset,relp->r_offset); ASNAR(ep->f_copy_word,grel->gr_info,relp->r_info); @@ -911,16 +911,16 @@ generic_rel_from_rel64( ecount = size/sizeof(dw_elf64_rel); size2 = ecount * sizeof(dw_elf64_rel); - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } - for ( i = 0; i < ecount; ++i,++relp,++grel) { + for (i = 0; i < ecount; ++i,++relp,++grel) { grel->gr_isrela = 0; ASNAR(ep->f_copy_word,grel->gr_offset,relp->r_offset); ASNAR(ep->f_copy_word,grel->gr_info,relp->r_info); grel->gr_addend = 0; /* Unused for plain .rel */ - if (ismips64 && objlittleendian ) { + if (ismips64 && objlittleendian) { char realsym[4]; memcpy(realsym,&relp->r_info,sizeof(realsym)); @@ -956,33 +956,33 @@ dwarf_load_elf_dynstr( Dwarf_Unsigned strsectindex =0; Dwarf_Unsigned strsectlength = 0; - if (!ep->f_dynsym_sect_strings_sect_index) { - return DW_DLV_NO_ENTRY; - } - strsectindex = ep->f_dynsym_sect_strings_sect_index; - strsectlength = ep->f_dynsym_sect_strings_max; - strpsh = ep->f_shdr + strsectindex; - /* Alloc an extra byte as a guaranteed NUL byte - at the end of the strings in case the section - is corrupted and lacks a NUL at end. */ - ep->f_dynsym_sect_strings = calloc(1,strsectlength+1); - if(!ep->f_dynsym_sect_strings) { - ep->f_dynsym_sect_strings = 0; - ep->f_dynsym_sect_strings_max = 0; - ep->f_dynsym_sect_strings_sect_index = 0; - *errcode = DW_DLE_ALLOC_FAIL; - return DW_DLV_ERROR; - } - res = RRMOA(ep->f_fd,ep->f_dynsym_sect_strings, - strpsh->gh_offset, - strsectlength, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { - ep->f_dynsym_sect_strings = 0; - ep->f_dynsym_sect_strings_max = 0; - ep->f_dynsym_sect_strings_sect_index = 0; - return res; - } + if (!ep->f_dynsym_sect_strings_sect_index) { + return DW_DLV_NO_ENTRY; + } + strsectindex = ep->f_dynsym_sect_strings_sect_index; + strsectlength = ep->f_dynsym_sect_strings_max; + strpsh = ep->f_shdr + strsectindex; + /* Alloc an extra byte as a guaranteed NUL byte + at the end of the strings in case the section + is corrupted and lacks a NUL at end. */ + ep->f_dynsym_sect_strings = calloc(1,strsectlength+1); + if (!ep->f_dynsym_sect_strings) { + ep->f_dynsym_sect_strings = 0; + ep->f_dynsym_sect_strings_max = 0; + ep->f_dynsym_sect_strings_sect_index = 0; + *errcode = DW_DLE_ALLOC_FAIL; + return DW_DLV_ERROR; + } + res = RRMOA(ep->f_fd,ep->f_dynsym_sect_strings, + strpsh->gh_offset, + strsectlength, + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { + ep->f_dynsym_sect_strings = 0; + ep->f_dynsym_sect_strings_max = 0; + ep->f_dynsym_sect_strings_sect_index = 0; + return res; + } return DW_DLV_OK; } #endif /* 0 */ @@ -1006,7 +1006,7 @@ _dwarf_load_elf_symstr( at the end of the strings in case the section is corrupted and lacks a NUL at end. */ ep->f_symtab_sect_strings = calloc(1,strsectlength+1); - if(!ep->f_symtab_sect_strings) { + if (!ep->f_symtab_sect_strings) { ep->f_symtab_sect_strings = 0; ep->f_symtab_sect_strings_max = 0; ep->f_symtab_sect_strings_sect_index = 0; @@ -1014,10 +1014,10 @@ _dwarf_load_elf_symstr( return DW_DLV_ERROR; } res = RRMOA(ep->f_fd,ep->f_symtab_sect_strings, - strpsh->gh_offset, - strsectlength, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + strpsh->gh_offset, + strsectlength, + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(ep->f_symtab_sect_strings); ep->f_symtab_sect_strings = 0; ep->f_symtab_sect_strings_max = 0; @@ -1045,15 +1045,15 @@ _dwarf_elf_load_sectstrings( } psh = ep->f_shdr + stringsection; secoffset = psh->gh_offset; - if(is_empty_section(psh->gh_type)) { + if (is_empty_section(psh->gh_type)) { *errcode = DW_DLE_ELF_STRING_SECTION_MISSING; return DW_DLV_ERROR; } - if(psh->gh_size > ep->f_elf_shstrings_max) { + if (psh->gh_size > ep->f_elf_shstrings_max) { free(ep->f_elf_shstrings_data); ep->f_elf_shstrings_data = (char *)malloc(psh->gh_size); ep->f_elf_shstrings_max = psh->gh_size; - if(!ep->f_elf_shstrings_data) { + if (!ep->f_elf_shstrings_data) { ep->f_elf_shstrings_max = 0; *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; @@ -1061,8 +1061,8 @@ _dwarf_elf_load_sectstrings( } ep->f_elf_shstrings_length = psh->gh_size; res = RRMOA(ep->f_fd,ep->f_elf_shstrings_data,secoffset, - psh->gh_size, - ep->f_filesize,errcode); + psh->gh_size, + ep->f_filesize,errcode); return res; } @@ -1076,22 +1076,22 @@ elf_load_sectheaders32( int res = 0; - if(count == 0) { + if (count == 0) { return DW_DLV_NO_ENTRY; } - if(entsize < sizeof(dw_elf32_shdr)) { + if (entsize < sizeof(dw_elf32_shdr)) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } - if ((offset > ep->f_filesize)|| - (entsize > 200)|| + if ((offset > ep->f_filesize) || + (entsize > 200) || (count > ep->f_filesize) || ((count *entsize +offset) > ep->f_filesize)) { - *errcode = DW_DLE_FILE_OFFSET_BAD; - return DW_DLV_ERROR; + *errcode = DW_DLE_FILE_OFFSET_BAD; + return DW_DLV_ERROR; } res = generic_shdr_from_shdr32(ep,&generic_count, - offset,entsize,count,errcode); + offset,entsize,count,errcode); if (res != DW_DLV_OK) { return res; } @@ -1112,22 +1112,22 @@ elf_load_sectheaders64( int res = 0; - if(count == 0) { + if (count == 0) { return DW_DLV_NO_ENTRY; } - if(entsize < sizeof(dw_elf64_shdr)) { + if (entsize < sizeof(dw_elf64_shdr)) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } - if ((offset > ep->f_filesize)|| - (entsize > 200)|| + if ((offset > ep->f_filesize) || + (entsize > 200) || (count > ep->f_filesize) || ((count *entsize +offset) > ep->f_filesize)) { - *errcode = DW_DLE_FILE_OFFSET_BAD; - return DW_DLV_ERROR; + *errcode = DW_DLE_FILE_OFFSET_BAD; + return DW_DLV_ERROR; } res = generic_shdr_from_shdr64(ep,&generic_count, - offset,entsize,count,errcode); + offset,entsize,count,errcode); if (res != DW_DLV_OK) { return res; } @@ -1158,30 +1158,30 @@ _dwarf_elf_load_rela_32( offset = gsh->gh_offset; size = gsh->gh_size; - if(size == 0) { + if (size == 0) { return DW_DLV_NO_ENTRY; } - if ((offset > ep->f_filesize)|| + if ((offset > ep->f_filesize) || (size > ep->f_filesize) || ((size +offset) > ep->f_filesize)) { - *errcode = DW_DLE_FILE_OFFSET_BAD; - return DW_DLV_ERROR; + *errcode = DW_DLE_FILE_OFFSET_BAD; + return DW_DLV_ERROR; } count = (long)(size/object_reclen); size2 = count * object_reclen; - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } relp = (dw_elf32_rela *)malloc(size); - if(!relp) { + if (!relp) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } res = RRMOA(ep->f_fd,relp,offset,size, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(relp); return res; } @@ -1225,30 +1225,30 @@ _dwarf_elf_load_rel_32( offset = gsh->gh_offset; size = gsh->gh_size; - if(size == 0) { + if (size == 0) { return DW_DLV_NO_ENTRY; } - if ((offset > ep->f_filesize)|| + if ((offset > ep->f_filesize) || (size > ep->f_filesize) || ((size +offset) > ep->f_filesize)) { - *errcode = DW_DLE_FILE_OFFSET_BAD; - return DW_DLV_ERROR; + *errcode = DW_DLE_FILE_OFFSET_BAD; + return DW_DLV_ERROR; } count = size/object_reclen; size2 = count * object_reclen; - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } relp = (dw_elf32_rel *)malloc(size); - if(!relp) { + if (!relp) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } res = RRMOA(ep->f_fd,relp,offset,size, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(relp); return res; } @@ -1291,31 +1291,31 @@ _dwarf_elf_load_rel_64( offset = gsh->gh_offset; size = gsh->gh_size; - if(size == 0) { + if (size == 0) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } - if ((offset > ep->f_filesize)|| + if ((offset > ep->f_filesize) || (size > ep->f_filesize) || ((size +offset) > ep->f_filesize)) { - *errcode = DW_DLE_FILE_OFFSET_BAD; - return DW_DLV_ERROR; + *errcode = DW_DLE_FILE_OFFSET_BAD; + return DW_DLV_ERROR; } count = size/object_reclen; size2 = count * object_reclen; - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } relp = (dw_elf64_rel *)malloc(size); - if(!relp) { + if (!relp) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } res = RRMOA(ep->f_fd,relp,offset,size, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(relp); return res; } @@ -1360,31 +1360,31 @@ _dwarf_elf_load_rela_64( offset = gsh->gh_offset; size = gsh->gh_size; - if(size == 0) { + if (size == 0) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } - if ((offset > ep->f_filesize)|| + if ((offset > ep->f_filesize) || (size > ep->f_filesize) || ((size +offset) > ep->f_filesize)) { - *errcode = DW_DLE_FILE_OFFSET_BAD; - return DW_DLV_ERROR; + *errcode = DW_DLE_FILE_OFFSET_BAD; + return DW_DLV_ERROR; } count = (long)(size/object_reclen); size2 = count * object_reclen; - if(size != size2) { + if (size != size2) { *errcode = DW_DLE_SECTION_SIZE_ERROR; return DW_DLV_ERROR; } /* Here want native rela size from the file */ relp = (dw_elf64_rela *)malloc(size); - if(!relp) { + if (!relp) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } res = RRMOA(ep->f_fd,relp,offset,size, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(relp); return res; } @@ -1422,7 +1422,7 @@ this_is_a_section_dwarf_related( unsigned oksecnum = 0; struct generic_shdr *gstarg = 0; - if (gshdr->gh_type != SHT_RELA ) { + if (gshdr->gh_type != SHT_RELA) { *oksecnum_out = 0; return DW_DLV_OK; } @@ -1483,10 +1483,10 @@ _dwarf_load_elf_rela( Others get ignored. */ if (offsetsize == 32) { res = _dwarf_elf_load_rela_32(ep, - gshdr,&grp,&count_read,errcode); + gshdr,&grp,&count_read,errcode); } else if (offsetsize == 64) { res = _dwarf_elf_load_rela_64(ep, - gshdr,&grp,&count_read,errcode); + gshdr,&grp,&count_read,errcode); } else { *errcode = DW_DLE_OFFSET_SIZE; return DW_DLV_ERROR; @@ -1530,10 +1530,10 @@ _dwarf_load_elf_rel( } if (offsetsize == 32) { res = _dwarf_elf_load_rel_32(ep, - gshdr,&grp,&count_read,errcode); + gshdr,&grp,&count_read,errcode); } else if (offsetsize == 64) { res = _dwarf_elf_load_rel_64(ep, - gshdr,&grp,&count_read,errcode); + gshdr,&grp,&count_read,errcode); } else { *errcode = DW_DLE_OFFSET_SIZE; return DW_DLV_ERROR; @@ -1552,9 +1552,9 @@ _dwarf_load_elf_rel( static int validate_section_name_string(Dwarf_Unsigned section_length, - Dwarf_Unsigned string_loc_index, - const char * strings_start, - int * errcode) + Dwarf_Unsigned string_loc_index, + const char * strings_start, + int * errcode) { const char *endpoint = strings_start + section_length; const char *cur = 0; @@ -1564,7 +1564,7 @@ validate_section_name_string(Dwarf_Unsigned section_length, return DW_DLV_ERROR; } cur = string_loc_index+strings_start; - for( ; cur < endpoint;++cur) { + for ( ; cur < endpoint; ++cur) { if (!*cur) { return DW_DLV_OK; } @@ -1586,14 +1586,14 @@ _dwarf_elf_load_sect_namestring( stringsecbase = ep->f_elf_shstrings_data; gshdr = ep->f_shdr; generic_count = ep->f_loc_shdr.g_count; - for(i = 0; i < generic_count; i++, ++gshdr) { + for (i = 0; i < generic_count; i++, ++gshdr) { const char *namestr = ""; int res = 0; res = validate_section_name_string(ep->f_elf_shstrings_length, - gshdr->gh_name, stringsecbase, - errcode); + gshdr->gh_name, stringsecbase, + errcode); if (res != DW_DLV_OK) { gshdr->gh_namestring = namestr; return res; @@ -1613,12 +1613,12 @@ elf_load_elf_header32( struct generic_ehdr *ehdr = 0; res = RRMOA(ep->f_fd,&ehdr32,0,sizeof(ehdr32), - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { return res; } ehdr = (struct generic_ehdr *)calloc(1, - sizeof(struct generic_ehdr)); + sizeof(struct generic_ehdr)); if (!ehdr) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; @@ -1635,12 +1635,12 @@ elf_load_elf_header64( struct generic_ehdr *ehdr = 0; res = RRMOA(ep->f_fd,&ehdr64,0,sizeof(ehdr64), - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { return res; } ehdr = (struct generic_ehdr *)calloc(1, - sizeof(struct generic_ehdr)); + sizeof(struct generic_ehdr)); if (!ehdr) { *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; @@ -1772,7 +1772,7 @@ string_endswith(const char *n,const char *q) unsigned long qlen = strlen(q); const char *startpt = 0; - if ( len < qlen) { + if (len < qlen) { return FALSE; } startpt = n + (len-qlen); @@ -1790,7 +1790,7 @@ elf_sht_groupsec(Dwarf_Unsigned type, const char *sname) { /* ARM compilers name SHT group "__ARM_grp" not .group */ - if ((type == SHT_GROUP) || (!strcmp(sname,".group"))){ + if ((type == SHT_GROUP) || (!strcmp(sname,".group"))) { return TRUE; } return FALSE; @@ -1849,8 +1849,8 @@ read_gs_section_group( return DW_DLV_ERROR; } res = RRMOA(ep->f_fd,data,psh->gh_offset,seclen, - ep->f_filesize,errcode); - if(res != DW_DLV_OK) { + ep->f_filesize,errcode); + if (res != DW_DLV_OK) { free(data); return res; } @@ -1873,7 +1873,7 @@ read_gs_section_group( } grouparray[0] = 1; dp = dp + DWARF_32BIT_SIZE; - for( i = 1; i < count; ++i,dp += DWARF_32BIT_SIZE) { + for (i = 1; i < count; ++i,dp += DWARF_32BIT_SIZE) { Dwarf_Unsigned gseca = 0; Dwarf_Unsigned gsecb = 0; struct generic_shdr* targpsh = 0; @@ -1996,7 +1996,7 @@ _dwarf_elf_setup_all_section_groups( continue; } /* Not a section group */ - if(string_endswith(name,".dwo")) { + if (string_endswith(name,".dwo")) { if (psh->gh_section_group_number) { /* multi-assignment to groups. Oops. */ *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR; @@ -2006,7 +2006,7 @@ _dwarf_elf_setup_all_section_groups( psh->gh_section_group_number = DW_GROUPNUMBER_DWO; ep->f_dwo_group_section_count++; } else if (_dwarf_load_elf_section_is_dwarf(name)) { - if(!psh->gh_section_group_number) { + if (!psh->gh_section_group_number) { psh->gh_section_group_number = DW_GROUPNUMBER_BASE; } psh->gh_is_dwarf = TRUE; @@ -2062,13 +2062,13 @@ _dwarf_elf_find_sym_sections( #if 0 res = validate_links(ep,ep->f_dynsym_sect_index, - ep->f_dynsym_sect_strings_sect_index,errcode); + ep->f_dynsym_sect_strings_sect_index,errcode); if (res!= DW_DLV_OK) { return res; } #endif /* 0 */ res = validate_links(ep,ep->f_symtab_sect_index, - ep->f_symtab_sect_strings_sect_index,errcode); + ep->f_symtab_sect_strings_sect_index,errcode); if (res!= DW_DLV_OK) { return res; } @@ -2084,12 +2084,12 @@ _dwarf_load_elf_sectheaders( if (ep->f_offsetsize == 32) { res = elf_load_sectheaders32(ep,ep->f_ehdr->ge_shoff, - ep->f_ehdr->ge_shentsize, - ep->f_ehdr->ge_shnum,errcode); - } else if (ep->f_offsetsize == 64) { + ep->f_ehdr->ge_shentsize, + ep->f_ehdr->ge_shnum,errcode); + } else if (ep->f_offsetsize == 64) { res = elf_load_sectheaders64(ep,ep->f_ehdr->ge_shoff, - ep->f_ehdr->ge_shentsize, - ep->f_ehdr->ge_shnum,errcode); + ep->f_ehdr->ge_shentsize, + ep->f_ehdr->ge_shnum,errcode); } else { *errcode = DW_DLE_OFFSET_SIZE; return DW_DLV_ERROR; @@ -2098,7 +2098,7 @@ _dwarf_load_elf_sectheaders( return res; } res = _dwarf_elf_load_sectstrings(ep, - ep->f_ehdr->ge_shstrndx,errcode); + ep->f_ehdr->ge_shstrndx,errcode); if (res != DW_DLV_OK) { return res; } diff --git a/test/bug-hunting/cve/CVE-2019-14284/floppy.c b/test/bug-hunting/cve/CVE-2019-14284/floppy.c index 9fb9b312a..b3241d81f 100644 --- a/test/bug-hunting/cve/CVE-2019-14284/floppy.c +++ b/test/bug-hunting/cve/CVE-2019-14284/floppy.c @@ -151,16 +151,16 @@ #define DEBUGT 2 -#define DPRINT(format, args...) \ - pr_info("floppy%d: " format, current_drive, ##args) +#define DPRINT(format, args ...) \ + pr_info("floppy%d: " format, current_drive, ## args) -#define DCL_DEBUG /* debug disk change line */ +#define DCL_DEBUG /* debug disk change line */ #ifdef DCL_DEBUG -#define debug_dcl(test, fmt, args...) \ - do { if ((test) & FD_DEBUG) DPRINT(fmt, ##args); } while (0) +#define debug_dcl(test, fmt, args ...) \ + do { if ((test) & FD_DEBUG) DPRINT(fmt, ## args); } while (0) #else -#define debug_dcl(test, fmt, args...) \ - do { if (0) DPRINT(fmt, ##args); } while (0) +#define debug_dcl(test, fmt, args ...) \ + do { if (0) DPRINT(fmt, ## args); } while (0) #endif /* do print messages for unexpected interrupts */ @@ -183,7 +183,7 @@ static int print_unex = 1; #include #include #include -#include /* CMOS defines */ +#include /* CMOS defines */ #include #include #include @@ -235,7 +235,7 @@ static unsigned short virtual_dma_port = 0x3f0; irqreturn_t floppy_interrupt(int irq, void *dev_id); static int set_dor(int fdc, char mask, char data); -#define K_64 0x10000 /* 64KB */ +#define K_64 0x10000 /* 64KB */ /* the following is the mask of allowed drives. By default units 2 and * 3 of both floppy controllers are disabled, because switching on the @@ -255,7 +255,7 @@ static int irqdma_allocated; #include #include -#include /* for the compatibility eject ioctl */ +#include /* for the compatibility eject ioctl */ #include static LIST_HEAD(floppy_reqs); @@ -283,14 +283,14 @@ static int set_next_request(void); static inline void fallback_on_nodma_alloc(char **addr, size_t l) { #ifdef FLOPPY_CAN_FALLBACK_ON_NODMA - if (*addr) - return; /* we have the memory */ - if (can_use_virtual_dma != 2) - return; /* no fallback allowed */ - pr_info("DMA memory shortage. Temporarily falling back on virtual DMA\n"); - *addr = (char *)nodma_mem_alloc(l); + if (*addr) + return; /* we have the memory */ + if (can_use_virtual_dma != 2) + return; /* no fallback allowed */ + pr_info("DMA memory shortage. Temporarily falling back on virtual DMA\n"); + *addr = (char *)nodma_mem_alloc(l); #else - return; + return; #endif } @@ -299,43 +299,43 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) static unsigned long fake_change; static bool initialized; -#define ITYPE(x) (((x) >> 2) & 0x1f) -#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) -#define UNIT(x) ((x) & 0x03) /* drive on fdc */ -#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ - /* reverse mapping from unit and fdc to drive */ +#define ITYPE(x) (((x) >> 2) & 0x1f) +#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) +#define UNIT(x) ((x) & 0x03) /* drive on fdc */ +#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ +/* reverse mapping from unit and fdc to drive */ #define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2)) -#define DP (&drive_params[current_drive]) -#define DRS (&drive_state[current_drive]) -#define DRWE (&write_errors[current_drive]) -#define FDCS (&fdc_state[fdc]) +#define DP (&drive_params[current_drive]) +#define DRS (&drive_state[current_drive]) +#define DRWE (&write_errors[current_drive]) +#define FDCS (&fdc_state[fdc]) -#define UDP (&drive_params[drive]) -#define UDRS (&drive_state[drive]) -#define UDRWE (&write_errors[drive]) -#define UFDCS (&fdc_state[FDC(drive)]) +#define UDP (&drive_params[drive]) +#define UDRS (&drive_state[drive]) +#define UDRWE (&write_errors[drive]) +#define UFDCS (&fdc_state[FDC(drive)]) #define PH_HEAD(floppy, head) (((((floppy)->stretch & 2) >> 1) ^ head) << 2) -#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) +#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) /* read/write */ -#define COMMAND (raw_cmd->cmd[0]) -#define DR_SELECT (raw_cmd->cmd[1]) -#define TRACK (raw_cmd->cmd[2]) -#define HEAD (raw_cmd->cmd[3]) -#define SECTOR (raw_cmd->cmd[4]) -#define SIZECODE (raw_cmd->cmd[5]) -#define SECT_PER_TRACK (raw_cmd->cmd[6]) -#define GAP (raw_cmd->cmd[7]) -#define SIZECODE2 (raw_cmd->cmd[8]) +#define COMMAND (raw_cmd->cmd[0]) +#define DR_SELECT (raw_cmd->cmd[1]) +#define TRACK (raw_cmd->cmd[2]) +#define HEAD (raw_cmd->cmd[3]) +#define SECTOR (raw_cmd->cmd[4]) +#define SIZECODE (raw_cmd->cmd[5]) +#define SECT_PER_TRACK (raw_cmd->cmd[6]) +#define GAP (raw_cmd->cmd[7]) +#define SIZECODE2 (raw_cmd->cmd[8]) #define NR_RW 9 /* format */ -#define F_SIZECODE (raw_cmd->cmd[2]) +#define F_SIZECODE (raw_cmd->cmd[2]) #define F_SECT_PER_TRACK (raw_cmd->cmd[3]) -#define F_GAP (raw_cmd->cmd[4]) -#define F_FILL (raw_cmd->cmd[5]) +#define F_GAP (raw_cmd->cmd[4]) +#define F_FILL (raw_cmd->cmd[5]) #define NR_F 6 /* @@ -343,71 +343,71 @@ static bool initialized; * This default is used whenever the current disk size is unknown. * [Now it is rather a minimum] */ -#define MAX_DISK_SIZE 4 /* 3984 */ +#define MAX_DISK_SIZE 4 /* 3984 */ /* * globals used by 'result()' */ #define MAX_REPLIES 16 static unsigned char reply_buffer[MAX_REPLIES]; -static int inr; /* size of reply buffer, when called from interrupt */ -#define ST0 (reply_buffer[0]) -#define ST1 (reply_buffer[1]) -#define ST2 (reply_buffer[2]) -#define ST3 (reply_buffer[0]) /* result of GETSTATUS */ -#define R_TRACK (reply_buffer[3]) -#define R_HEAD (reply_buffer[4]) -#define R_SECTOR (reply_buffer[5]) -#define R_SIZECODE (reply_buffer[6]) +static int inr; /* size of reply buffer, when called from interrupt */ +#define ST0 (reply_buffer[0]) +#define ST1 (reply_buffer[1]) +#define ST2 (reply_buffer[2]) +#define ST3 (reply_buffer[0]) /* result of GETSTATUS */ +#define R_TRACK (reply_buffer[3]) +#define R_HEAD (reply_buffer[4]) +#define R_SECTOR (reply_buffer[5]) +#define R_SIZECODE (reply_buffer[6]) -#define SEL_DLY (2 * HZ / 100) +#define SEL_DLY (2 * HZ / 100) /* * this struct defines the different floppy drive types. */ static struct { - struct floppy_drive_params params; - const char *name; /* name printed while booting */ + struct floppy_drive_params params; + const char *name; /* name printed while booting */ } default_drive_params[] = { /* NOTE: the time values in jiffies should be in msec! - CMOS drive type - | Maximum data rate supported by drive type - | | Head load time, msec - | | | Head unload time, msec (not used) - | | | | Step rate interval, usec - | | | | | Time needed for spinup time (jiffies) - | | | | | | Timeout for spinning down (jiffies) - | | | | | | | Spindown offset (where disk stops) - | | | | | | | | Select delay - | | | | | | | | | RPS - | | | | | | | | | | Max number of tracks - | | | | | | | | | | | Interrupt timeout - | | | | | | | | | | | | Max nonintlv. sectors - | | | | | | | | | | | | | -Max Errors- flags */ -{{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0, + CMOS drive type + | Maximum data rate supported by drive type + | | Head load time, msec + | | | Head unload time, msec (not used) + | | | | Step rate interval, usec + | | | | | Time needed for spinup time (jiffies) + | | | | | | Timeout for spinning down (jiffies) + | | | | | | | Spindown offset (where disk stops) + | | | | | | | | Select delay + | | | | | | | | | RPS + | | | | | | | | | | Max number of tracks + | | | | | | | | | | | Interrupt timeout + | | | | | | | | | | | | Max nonintlv. sectors + | | | | | | | | | | | | | -Max Errors- flags */ + {{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0, 0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" }, -{{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0, + {{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0, 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/ -{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0, + {{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0, 0, { 2, 5, 6,23,10,20,12, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/ -{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, + {{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, 0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/ -{{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, + {{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, 0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/ -{{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, + {{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/ -{{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, + {{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/ /* | --autodetected formats--- | | | * read_track | | Name printed when booting - * | Native format - * Frequency of disk change checks */ + * | Native format + * Frequency of disk change checks */ }; static struct floppy_drive_params drive_params[N_DRIVE]; @@ -442,51 +442,51 @@ static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; * Other parameters should be self-explanatory (see also setfdprm(8)). */ /* - Size - | Sectors per track - | | Head - | | | Tracks - | | | | Stretch - | | | | | Gap 1 size - | | | | | | Data rate, | 0x40 for perp - | | | | | | | Spec1 (stepping rate, head unload - | | | | | | | | /fmt gap (gap2) */ + Size + | Sectors per track + | | Head + | | | Tracks + | | | | Stretch + | | | | | Gap 1 size + | | | | | | Data rate, | 0x40 for perp + | | | | | | | Spec1 (stepping rate, head unload + | | | | | | | | /fmt gap (gap2) */ static struct floppy_struct floppy_type[32] = { - { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */ - { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */ - { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */ - { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */ - { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */ - { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */ - { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */ - { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */ - { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */ - { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" }, /* 9 3.12MB 3.5" */ + { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */ + { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */ + { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */ + { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */ + { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */ + { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */ + { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */ + { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */ + { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */ + { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" }, /* 9 3.12MB 3.5" */ - { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */ - { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */ - { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */ - { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */ - { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */ - { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */ - { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */ - { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */ - { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */ - { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */ + { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */ + { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */ + { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */ + { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */ + { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */ + { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */ + { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */ + { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */ + { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */ + { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */ - { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */ - { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */ - { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */ - { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */ - { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */ - { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */ - { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */ - { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */ - { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */ - { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */ + { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */ + { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */ + { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */ + { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */ + { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */ + { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */ + { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */ + { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */ + { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */ + { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */ - { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */ - { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ + { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */ + { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ }; #define SECTSIZE (_FD_SECTSIZE(*floppy)) @@ -512,9 +512,9 @@ static char floppy_device_name[] = "floppy"; static int probing; /* Synchronization of FDC access. */ -#define FD_COMMAND_NONE -1 -#define FD_COMMAND_ERROR 2 -#define FD_COMMAND_OKAY 3 +#define FD_COMMAND_NONE -1 +#define FD_COMMAND_ERROR 2 +#define FD_COMMAND_OKAY 3 static volatile int command_status = FD_COMMAND_NONE; static unsigned long fdc_busy; @@ -545,13 +545,13 @@ static int max_buffer_sectors; static int *errors; typedef void (*done_f)(int); static const struct cont_t { - void (*interrupt)(void); - /* this is called after the interrupt of the - * main command */ - void (*redo)(void); /* this is called to retry the operation */ - void (*error)(void); /* this is called to tally an error */ - done_f done; /* this is called to say if the operation has - * succeeded/failed */ + void (*interrupt)(void); + /* this is called after the interrupt of the + * main command */ + void (*redo)(void); /* this is called to retry the operation */ + void (*error)(void); /* this is called to tally an error */ + done_f done; /* this is called to say if the operation has + * succeeded/failed */ } *cont; static void floppy_ready(void); @@ -579,9 +579,9 @@ static void reset_fdc(void); * information to interrupts. They are the data used for the current * request. */ -#define NO_TRACK -1 -#define NEED_1_RECAL -2 -#define NEED_2_RECAL -3 +#define NO_TRACK -1 +#define NEED_1_RECAL -2 +#define NEED_2_RECAL -3 static atomic_t usage_count = ATOMIC_INIT(0); @@ -593,26 +593,26 @@ static int buffer_max = -1; /* fdc related variables, should end up in a struct */ static struct floppy_fdc_state fdc_state[N_FDC]; -static int fdc; /* current fdc */ +static int fdc; /* current fdc */ static struct workqueue_struct *floppy_wq; static struct floppy_struct *_floppy = floppy_type; static unsigned char current_drive; static long current_count_sectors; -static unsigned char fsector_t; /* sector in track */ -static unsigned char in_sector_offset; /* offset within physical sector, - * expressed in units of 512 bytes */ +static unsigned char fsector_t; /* sector in track */ +static unsigned char in_sector_offset; /* offset within physical sector, + * expressed in units of 512 bytes */ static inline bool drive_no_geom(int drive) { - return !current_type[drive] && !ITYPE(UDRS->fd_device); + return !current_type[drive] && !ITYPE(UDRS->fd_device); } #ifndef fd_eject static inline int fd_eject(int drive) { - return -EINVAL; + return -EINVAL; } #endif @@ -625,17 +625,17 @@ static long unsigned debugtimer; static inline void set_debugt(void) { - debugtimer = jiffies; + debugtimer = jiffies; } static inline void debugt(const char *func, const char *msg) { - if (DP->flags & DEBUGT) - pr_info("%s:%s dtime=%lu\n", func, msg, jiffies - debugtimer); + if (DP->flags & DEBUGT) + pr_info("%s:%s dtime=%lu\n", func, msg, jiffies - debugtimer); } #else -static inline void set_debugt(void) { } -static inline void debugt(const char *func, const char *msg) { } +static inline void set_debugt(void) {} +static inline void debugt(const char *func, const char *msg) {} #endif /* DEBUGT */ @@ -644,11 +644,11 @@ static const char *timeout_message; static void is_alive(const char *func, const char *message) { - /* this routine checks whether the floppy driver is "alive" */ - if (test_bit(0, &fdc_busy) && command_status < 2 && - !delayed_work_pending(&fd_timeout)) { - DPRINT("%s: timeout handler died. %s\n", func, message); - } + /* this routine checks whether the floppy driver is "alive" */ + if (test_bit(0, &fdc_busy) && command_status < 2 && + !delayed_work_pending(&fd_timeout)) { + DPRINT("%s: timeout handler died. %s\n", func, message); + } } static void (*do_floppy)(void) = NULL; @@ -662,9 +662,9 @@ static int resultsize; static unsigned long lastredo; static struct output_log { - unsigned char data; - unsigned char status; - unsigned long jiffies; + unsigned char data; + unsigned char status; + unsigned long jiffies; } output_log[OLOGSIZE]; static int output_log_pos; @@ -674,30 +674,30 @@ static int output_log_pos; static void __reschedule_timeout(int drive, const char *message) { - unsigned long delay; + unsigned long delay; - if (drive == current_reqD) - drive = current_drive; + if (drive == current_reqD) + drive = current_drive; - if (drive < 0 || drive >= N_DRIVE) { - delay = 20UL * HZ; - drive = 0; - } else - delay = UDP->timeout; + if (drive < 0 || drive >= N_DRIVE) { + delay = 20UL * HZ; + drive = 0; + } else + delay = UDP->timeout; - mod_delayed_work(floppy_wq, &fd_timeout, delay); - if (UDP->flags & FD_DEBUG) - DPRINT("reschedule timeout %s\n", message); - timeout_message = message; + mod_delayed_work(floppy_wq, &fd_timeout, delay); + if (UDP->flags & FD_DEBUG) + DPRINT("reschedule timeout %s\n", message); + timeout_message = message; } static void reschedule_timeout(int drive, const char *message) { - unsigned long flags; + unsigned long flags; - spin_lock_irqsave(&floppy_lock, flags); - __reschedule_timeout(drive, message); - spin_unlock_irqrestore(&floppy_lock, flags); + spin_lock_irqsave(&floppy_lock, flags); + __reschedule_timeout(drive, message); + spin_unlock_irqrestore(&floppy_lock, flags); } #define INFBOUND(a, b) (a) = max_t(int, a, b) @@ -738,99 +738,99 @@ static void reschedule_timeout(int drive, const char *message) static int disk_change(int drive) { - int fdc = FDC(drive); + int fdc = FDC(drive); - if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) - DPRINT("WARNING disk change called early\n"); - if (!(FDCS->dor & (0x10 << UNIT(drive))) || - (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) { - DPRINT("probing disk change on unselected drive\n"); - DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive), - (unsigned int)FDCS->dor); - } + if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) + DPRINT("WARNING disk change called early\n"); + if (!(FDCS->dor & (0x10 << UNIT(drive))) || + (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) { + DPRINT("probing disk change on unselected drive\n"); + DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive), + (unsigned int)FDCS->dor); + } - debug_dcl(UDP->flags, - "checking disk change line for drive %d\n", drive); - debug_dcl(UDP->flags, "jiffies=%lu\n", jiffies); - debug_dcl(UDP->flags, "disk change line=%x\n", fd_inb(FD_DIR) & 0x80); - debug_dcl(UDP->flags, "flags=%lx\n", UDRS->flags); + debug_dcl(UDP->flags, + "checking disk change line for drive %d\n", drive); + debug_dcl(UDP->flags, "jiffies=%lu\n", jiffies); + debug_dcl(UDP->flags, "disk change line=%x\n", fd_inb(FD_DIR) & 0x80); + debug_dcl(UDP->flags, "flags=%lx\n", UDRS->flags); - if (UDP->flags & FD_BROKEN_DCL) - return test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); - if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) { - set_bit(FD_VERIFY_BIT, &UDRS->flags); - /* verify write protection */ + if (UDP->flags & FD_BROKEN_DCL) + return test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) { + set_bit(FD_VERIFY_BIT, &UDRS->flags); + /* verify write protection */ - if (UDRS->maxblock) /* mark it changed */ - set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + if (UDRS->maxblock) /* mark it changed */ + set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); - /* invalidate its geometry */ - if (UDRS->keep_data >= 0) { - if ((UDP->flags & FTD_MSG) && - current_type[drive] != NULL) - DPRINT("Disk type is undefined after disk change\n"); - current_type[drive] = NULL; - floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1; - } + /* invalidate its geometry */ + if (UDRS->keep_data >= 0) { + if ((UDP->flags & FTD_MSG) && + current_type[drive] != NULL) + DPRINT("Disk type is undefined after disk change\n"); + current_type[drive] = NULL; + floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1; + } - return 1; - } else { - UDRS->last_checked = jiffies; - clear_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags); - } - return 0; + return 1; + } else { + UDRS->last_checked = jiffies; + clear_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags); + } + return 0; } static inline int is_selected(int dor, int unit) { - return ((dor & (0x10 << unit)) && (dor & 3) == unit); + return ((dor & (0x10 << unit)) && (dor & 3) == unit); } static bool is_ready_state(int status) { - int state = status & (STATUS_READY | STATUS_DIR | STATUS_DMA); - return state == STATUS_READY; + int state = status & (STATUS_READY | STATUS_DIR | STATUS_DMA); + return state == STATUS_READY; } static int set_dor(int fdc, char mask, char data) { - unsigned char unit; - unsigned char drive; - unsigned char newdor; - unsigned char olddor; + unsigned char unit; + unsigned char drive; + unsigned char newdor; + unsigned char olddor; - if (FDCS->address == -1) - return -1; + if (FDCS->address == -1) + return -1; - olddor = FDCS->dor; - newdor = (olddor & mask) | data; - if (newdor != olddor) { - unit = olddor & 0x3; - if (is_selected(olddor, unit) && !is_selected(newdor, unit)) { - drive = REVDRIVE(fdc, unit); - debug_dcl(UDP->flags, - "calling disk change from set_dor\n"); - disk_change(drive); - } - FDCS->dor = newdor; - fd_outb(newdor, FD_DOR); + olddor = FDCS->dor; + newdor = (olddor & mask) | data; + if (newdor != olddor) { + unit = olddor & 0x3; + if (is_selected(olddor, unit) && !is_selected(newdor, unit)) { + drive = REVDRIVE(fdc, unit); + debug_dcl(UDP->flags, + "calling disk change from set_dor\n"); + disk_change(drive); + } + FDCS->dor = newdor; + fd_outb(newdor, FD_DOR); - unit = newdor & 0x3; - if (!is_selected(olddor, unit) && is_selected(newdor, unit)) { - drive = REVDRIVE(fdc, unit); - UDRS->select_date = jiffies; - } - } - return olddor; + unit = newdor & 0x3; + if (!is_selected(olddor, unit) && is_selected(newdor, unit)) { + drive = REVDRIVE(fdc, unit); + UDRS->select_date = jiffies; + } + } + return olddor; } static void twaddle(void) { - if (DP->select_delay) - return; - fd_outb(FDCS->dor & ~(0x10 << UNIT(current_drive)), FD_DOR); - fd_outb(FDCS->dor, FD_DOR); - DRS->select_date = jiffies; + if (DP->select_delay) + return; + fd_outb(FDCS->dor & ~(0x10 << UNIT(current_drive)), FD_DOR); + fd_outb(FDCS->dor, FD_DOR); + DRS->select_date = jiffies; } /* @@ -839,103 +839,103 @@ static void twaddle(void) */ static void reset_fdc_info(int mode) { - int drive; + int drive; - FDCS->spec1 = FDCS->spec2 = -1; - FDCS->need_configure = 1; - FDCS->perp_mode = 1; - FDCS->rawcmd = 0; - for (drive = 0; drive < N_DRIVE; drive++) - if (FDC(drive) == fdc && (mode || UDRS->track != NEED_1_RECAL)) - UDRS->track = NEED_2_RECAL; + FDCS->spec1 = FDCS->spec2 = -1; + FDCS->need_configure = 1; + FDCS->perp_mode = 1; + FDCS->rawcmd = 0; + for (drive = 0; drive < N_DRIVE; drive++) + if (FDC(drive) == fdc && (mode || UDRS->track != NEED_1_RECAL)) + UDRS->track = NEED_2_RECAL; } /* selects the fdc and drive, and enables the fdc's input/dma. */ static void set_fdc(int drive) { - if (drive >= 0 && drive < N_DRIVE) { - fdc = FDC(drive); - current_drive = drive; - } - if (fdc != 1 && fdc != 0) { - pr_info("bad fdc value\n"); - return; - } - set_dor(fdc, ~0, 8); + if (drive >= 0 && drive < N_DRIVE) { + fdc = FDC(drive); + current_drive = drive; + } + if (fdc != 1 && fdc != 0) { + pr_info("bad fdc value\n"); + return; + } + set_dor(fdc, ~0, 8); #if N_FDC > 1 - set_dor(1 - fdc, ~8, 0); + set_dor(1 - fdc, ~8, 0); #endif - if (FDCS->rawcmd == 2) - reset_fdc_info(1); - if (fd_inb(FD_STATUS) != STATUS_READY) - FDCS->reset = 1; + if (FDCS->rawcmd == 2) + reset_fdc_info(1); + if (fd_inb(FD_STATUS) != STATUS_READY) + FDCS->reset = 1; } /* locks the driver */ static int lock_fdc(int drive) { - if (WARN(atomic_read(&usage_count) == 0, - "Trying to lock fdc while usage count=0\n")) - return -1; + if (WARN(atomic_read(&usage_count) == 0, + "Trying to lock fdc while usage count=0\n")) + return -1; - if (wait_event_interruptible(fdc_wait, !test_and_set_bit(0, &fdc_busy))) - return -EINTR; + if (wait_event_interruptible(fdc_wait, !test_and_set_bit(0, &fdc_busy))) + return -EINTR; - command_status = FD_COMMAND_NONE; + command_status = FD_COMMAND_NONE; - reschedule_timeout(drive, "lock fdc"); - set_fdc(drive); - return 0; + reschedule_timeout(drive, "lock fdc"); + set_fdc(drive); + return 0; } /* unlocks the driver */ static void unlock_fdc(void) { - if (!test_bit(0, &fdc_busy)) - DPRINT("FDC access conflict!\n"); + if (!test_bit(0, &fdc_busy)) + DPRINT("FDC access conflict!\n"); - raw_cmd = NULL; - command_status = FD_COMMAND_NONE; - cancel_delayed_work(&fd_timeout); - do_floppy = NULL; - cont = NULL; - clear_bit(0, &fdc_busy); - wake_up(&fdc_wait); + raw_cmd = NULL; + command_status = FD_COMMAND_NONE; + cancel_delayed_work(&fd_timeout); + do_floppy = NULL; + cont = NULL; + clear_bit(0, &fdc_busy); + wake_up(&fdc_wait); } /* switches the motor off after a given timeout */ static void motor_off_callback(struct timer_list *t) { - unsigned long nr = t - motor_off_timer; - unsigned char mask = ~(0x10 << UNIT(nr)); + unsigned long nr = t - motor_off_timer; + unsigned char mask = ~(0x10 << UNIT(nr)); - if (WARN_ON_ONCE(nr >= N_DRIVE)) - return; + if (WARN_ON_ONCE(nr >= N_DRIVE)) + return; - set_dor(FDC(nr), mask, 0); + set_dor(FDC(nr), mask, 0); } /* schedules motor off */ static void floppy_off(unsigned int drive) { - unsigned long volatile delta; - int fdc = FDC(drive); + unsigned long volatile delta; + int fdc = FDC(drive); - if (!(FDCS->dor & (0x10 << UNIT(drive)))) - return; + if (!(FDCS->dor & (0x10 << UNIT(drive)))) + return; - del_timer(motor_off_timer + drive); + del_timer(motor_off_timer + drive); - /* make spindle stop in a position which minimizes spinup time - * next time */ - if (UDP->rps) { - delta = jiffies - UDRS->first_read_date + HZ - - UDP->spindown_offset; - delta = ((delta * UDP->rps) % HZ) / UDP->rps; - motor_off_timer[drive].expires = - jiffies + UDP->spindown - delta; - } - add_timer(motor_off_timer + drive); + /* make spindle stop in a position which minimizes spinup time + * next time */ + if (UDP->rps) { + delta = jiffies - UDRS->first_read_date + HZ - + UDP->spindown_offset; + delta = ((delta * UDP->rps) % HZ) / UDP->rps; + motor_off_timer[drive].expires = + jiffies + UDP->spindown - delta; + } + add_timer(motor_off_timer + drive); } /* @@ -945,152 +945,151 @@ static void floppy_off(unsigned int drive) */ static void scandrives(void) { - int i; - int drive; - int saved_drive; + int i; + int drive; + int saved_drive; - if (DP->select_delay) - return; + if (DP->select_delay) + return; - saved_drive = current_drive; - for (i = 0; i < N_DRIVE; i++) { - drive = (saved_drive + i + 1) % N_DRIVE; - if (UDRS->fd_ref == 0 || UDP->select_delay != 0) - continue; /* skip closed drives */ - set_fdc(drive); - if (!(set_dor(fdc, ~3, UNIT(drive) | (0x10 << UNIT(drive))) & - (0x10 << UNIT(drive)))) - /* switch the motor off again, if it was off to - * begin with */ - set_dor(fdc, ~(0x10 << UNIT(drive)), 0); - } - set_fdc(saved_drive); + saved_drive = current_drive; + for (i = 0; i < N_DRIVE; i++) { + drive = (saved_drive + i + 1) % N_DRIVE; + if (UDRS->fd_ref == 0 || UDP->select_delay != 0) + continue; /* skip closed drives */ + set_fdc(drive); + if (!(set_dor(fdc, ~3, UNIT(drive) | (0x10 << UNIT(drive))) & + (0x10 << UNIT(drive)))) + /* switch the motor off again, if it was off to + * begin with */ + set_dor(fdc, ~(0x10 << UNIT(drive)), 0); + } + set_fdc(saved_drive); } static void empty(void) -{ -} +{} static void (*floppy_work_fn)(void); static void floppy_work_workfn(struct work_struct *work) { - floppy_work_fn(); + floppy_work_fn(); } static DECLARE_WORK(floppy_work, floppy_work_workfn); static void schedule_bh(void (*handler)(void)) { - WARN_ON(work_pending(&floppy_work)); + WARN_ON(work_pending(&floppy_work)); - floppy_work_fn = handler; - queue_work(floppy_wq, &floppy_work); + floppy_work_fn = handler; + queue_work(floppy_wq, &floppy_work); } static void (*fd_timer_fn)(void) = NULL; static void fd_timer_workfn(struct work_struct *work) { - fd_timer_fn(); + fd_timer_fn(); } static DECLARE_DELAYED_WORK(fd_timer, fd_timer_workfn); static void cancel_activity(void) { - do_floppy = NULL; - cancel_delayed_work_sync(&fd_timer); - cancel_work_sync(&floppy_work); + do_floppy = NULL; + cancel_delayed_work_sync(&fd_timer); + cancel_work_sync(&floppy_work); } /* this function makes sure that the disk stays in the drive during the * transfer */ static void fd_watchdog(void) { - debug_dcl(DP->flags, "calling disk change from watchdog\n"); + debug_dcl(DP->flags, "calling disk change from watchdog\n"); - if (disk_change(current_drive)) { - DPRINT("disk removed during i/o\n"); - cancel_activity(); - cont->done(0); - reset_fdc(); - } else { - cancel_delayed_work(&fd_timer); - fd_timer_fn = fd_watchdog; - queue_delayed_work(floppy_wq, &fd_timer, HZ / 10); - } + if (disk_change(current_drive)) { + DPRINT("disk removed during i/o\n"); + cancel_activity(); + cont->done(0); + reset_fdc(); + } else { + cancel_delayed_work(&fd_timer); + fd_timer_fn = fd_watchdog; + queue_delayed_work(floppy_wq, &fd_timer, HZ / 10); + } } static void main_command_interrupt(void) { - cancel_delayed_work(&fd_timer); - cont->interrupt(); + cancel_delayed_work(&fd_timer); + cont->interrupt(); } /* waits for a delay (spinup or select) to pass */ static int fd_wait_for_completion(unsigned long expires, - void (*function)(void)) + void (*function)(void)) { - if (FDCS->reset) { - reset_fdc(); /* do the reset during sleep to win time - * if we don't need to sleep, it's a good - * occasion anyways */ - return 1; - } + if (FDCS->reset) { + reset_fdc(); /* do the reset during sleep to win time + * if we don't need to sleep, it's a good + * occasion anyways */ + return 1; + } - if (time_before(jiffies, expires)) { - cancel_delayed_work(&fd_timer); - fd_timer_fn = function; - queue_delayed_work(floppy_wq, &fd_timer, expires - jiffies); - return 1; - } - return 0; + if (time_before(jiffies, expires)) { + cancel_delayed_work(&fd_timer); + fd_timer_fn = function; + queue_delayed_work(floppy_wq, &fd_timer, expires - jiffies); + return 1; + } + return 0; } static void setup_DMA(void) { - unsigned long f; + unsigned long f; - if (raw_cmd->length == 0) { - int i; + if (raw_cmd->length == 0) { + int i; - pr_info("zero dma transfer size:"); - for (i = 0; i < raw_cmd->cmd_count; i++) - pr_cont("%x,", raw_cmd->cmd[i]); - pr_cont("\n"); - cont->done(0); - FDCS->reset = 1; - return; - } - if (((unsigned long)raw_cmd->kernel_data) % 512) { - pr_info("non aligned address: %p\n", raw_cmd->kernel_data); - cont->done(0); - FDCS->reset = 1; - return; - } - f = claim_dma_lock(); - fd_disable_dma(); + pr_info("zero dma transfer size:"); + for (i = 0; i < raw_cmd->cmd_count; i++) + pr_cont("%x,", raw_cmd->cmd[i]); + pr_cont("\n"); + cont->done(0); + FDCS->reset = 1; + return; + } + if (((unsigned long)raw_cmd->kernel_data) % 512) { + pr_info("non aligned address: %p\n", raw_cmd->kernel_data); + cont->done(0); + FDCS->reset = 1; + return; + } + f = claim_dma_lock(); + fd_disable_dma(); #ifdef fd_dma_setup - if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, - (raw_cmd->flags & FD_RAW_READ) ? - DMA_MODE_READ : DMA_MODE_WRITE, FDCS->address) < 0) { - release_dma_lock(f); - cont->done(0); - FDCS->reset = 1; - return; - } - release_dma_lock(f); + if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, + (raw_cmd->flags & FD_RAW_READ) ? + DMA_MODE_READ : DMA_MODE_WRITE, FDCS->address) < 0) { + release_dma_lock(f); + cont->done(0); + FDCS->reset = 1; + return; + } + release_dma_lock(f); #else - fd_clear_dma_ff(); - fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length); - fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ) ? - DMA_MODE_READ : DMA_MODE_WRITE); - fd_set_dma_addr(raw_cmd->kernel_data); - fd_set_dma_count(raw_cmd->length); - virtual_dma_port = FDCS->address; - fd_enable_dma(); - release_dma_lock(f); + fd_clear_dma_ff(); + fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length); + fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ) ? + DMA_MODE_READ : DMA_MODE_WRITE); + fd_set_dma_addr(raw_cmd->kernel_data); + fd_set_dma_count(raw_cmd->length); + virtual_dma_port = FDCS->address; + fd_enable_dma(); + release_dma_lock(f); #endif } @@ -1099,92 +1098,92 @@ static void show_floppy(void); /* waits until the fdc becomes ready */ static int wait_til_ready(void) { - int status; - int counter; + int status; + int counter; - if (FDCS->reset) - return -1; - for (counter = 0; counter < 10000; counter++) { - status = fd_inb(FD_STATUS); - if (status & STATUS_READY) - return status; - } - if (initialized) { - DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc); - show_floppy(); - } - FDCS->reset = 1; - return -1; + if (FDCS->reset) + return -1; + for (counter = 0; counter < 10000; counter++) { + status = fd_inb(FD_STATUS); + if (status & STATUS_READY) + return status; + } + if (initialized) { + DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc); + show_floppy(); + } + FDCS->reset = 1; + return -1; } /* sends a command byte to the fdc */ static int output_byte(char byte) { - int status = wait_til_ready(); + int status = wait_til_ready(); - if (status < 0) - return -1; + if (status < 0) + return -1; - if (is_ready_state(status)) { - fd_outb(byte, FD_DATA); - output_log[output_log_pos].data = byte; - output_log[output_log_pos].status = status; - output_log[output_log_pos].jiffies = jiffies; - output_log_pos = (output_log_pos + 1) % OLOGSIZE; - return 0; - } - FDCS->reset = 1; - if (initialized) { - DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n", - byte, fdc, status); - show_floppy(); - } - return -1; + if (is_ready_state(status)) { + fd_outb(byte, FD_DATA); + output_log[output_log_pos].data = byte; + output_log[output_log_pos].status = status; + output_log[output_log_pos].jiffies = jiffies; + output_log_pos = (output_log_pos + 1) % OLOGSIZE; + return 0; + } + FDCS->reset = 1; + if (initialized) { + DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n", + byte, fdc, status); + show_floppy(); + } + return -1; } /* gets the response from the fdc */ static int result(void) { - int i; - int status = 0; + int i; + int status = 0; - for (i = 0; i < MAX_REPLIES; i++) { - status = wait_til_ready(); - if (status < 0) - break; - status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA; - if ((status & ~STATUS_BUSY) == STATUS_READY) { - resultjiffies = jiffies; - resultsize = i; - return i; - } - if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY)) - reply_buffer[i] = fd_inb(FD_DATA); - else - break; - } - if (initialized) { - DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n", - fdc, status, i); - show_floppy(); - } - FDCS->reset = 1; - return -1; + for (i = 0; i < MAX_REPLIES; i++) { + status = wait_til_ready(); + if (status < 0) + break; + status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA; + if ((status & ~STATUS_BUSY) == STATUS_READY) { + resultjiffies = jiffies; + resultsize = i; + return i; + } + if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY)) + reply_buffer[i] = fd_inb(FD_DATA); + else + break; + } + if (initialized) { + DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n", + fdc, status, i); + show_floppy(); + } + FDCS->reset = 1; + return -1; } #define MORE_OUTPUT -2 /* does the fdc need more output? */ static int need_more_output(void) { - int status = wait_til_ready(); + int status = wait_til_ready(); - if (status < 0) - return -1; + if (status < 0) + return -1; - if (is_ready_state(status)) - return MORE_OUTPUT; + if (is_ready_state(status)) + return MORE_OUTPUT; - return result(); + return result(); } /* Set perpendicular mode as required, based on data rate, if supported. @@ -1192,55 +1191,55 @@ static int need_more_output(void) */ static void perpendicular_mode(void) { - unsigned char perp_mode; + unsigned char perp_mode; - if (raw_cmd->rate & 0x40) { - switch (raw_cmd->rate & 3) { - case 0: - perp_mode = 2; - break; - case 3: - perp_mode = 3; - break; - default: - DPRINT("Invalid data rate for perpendicular mode!\n"); - cont->done(0); - FDCS->reset = 1; - /* - * convenient way to return to - * redo without too much hassle - * (deep stack et al.) - */ - return; - } - } else - perp_mode = 0; + if (raw_cmd->rate & 0x40) { + switch (raw_cmd->rate & 3) { + case 0: + perp_mode = 2; + break; + case 3: + perp_mode = 3; + break; + default: + DPRINT("Invalid data rate for perpendicular mode!\n"); + cont->done(0); + FDCS->reset = 1; + /* + * convenient way to return to + * redo without too much hassle + * (deep stack et al.) + */ + return; + } + } else + perp_mode = 0; - if (FDCS->perp_mode == perp_mode) - return; - if (FDCS->version >= FDC_82077_ORIG) { - output_byte(FD_PERPENDICULAR); - output_byte(perp_mode); - FDCS->perp_mode = perp_mode; - } else if (perp_mode) { - DPRINT("perpendicular mode not supported by this FDC.\n"); - } -} /* perpendicular_mode */ + if (FDCS->perp_mode == perp_mode) + return; + if (FDCS->version >= FDC_82077_ORIG) { + output_byte(FD_PERPENDICULAR); + output_byte(perp_mode); + FDCS->perp_mode = perp_mode; + } else if (perp_mode) { + DPRINT("perpendicular mode not supported by this FDC.\n"); + } +} /* perpendicular_mode */ static int fifo_depth = 0xa; static int no_fifo; static int fdc_configure(void) { - /* Turn on FIFO */ - output_byte(FD_CONFIGURE); - if (need_more_output() != MORE_OUTPUT) - return 0; - output_byte(0); - output_byte(0x10 | (no_fifo & 0x20) | (fifo_depth & 0xf)); - output_byte(0); /* pre-compensation from track - 0 upwards */ - return 1; + /* Turn on FIFO */ + output_byte(FD_CONFIGURE); + if (need_more_output() != MORE_OUTPUT) + return 0; + output_byte(0); + output_byte(0x10 | (no_fifo & 0x20) | (fifo_depth & 0xf)); + output_byte(0); /* pre-compensation from track + 0 upwards */ + return 1; } #define NOMINAL_DTR 500 @@ -1266,79 +1265,79 @@ static int fdc_configure(void) */ static void fdc_specify(void) { - unsigned char spec1; - unsigned char spec2; - unsigned long srt; - unsigned long hlt; - unsigned long hut; - unsigned long dtr = NOMINAL_DTR; - unsigned long scale_dtr = NOMINAL_DTR; - int hlt_max_code = 0x7f; - int hut_max_code = 0xf; + unsigned char spec1; + unsigned char spec2; + unsigned long srt; + unsigned long hlt; + unsigned long hut; + unsigned long dtr = NOMINAL_DTR; + unsigned long scale_dtr = NOMINAL_DTR; + int hlt_max_code = 0x7f; + int hut_max_code = 0xf; - if (FDCS->need_configure && FDCS->version >= FDC_82072A) { - fdc_configure(); - FDCS->need_configure = 0; - } + if (FDCS->need_configure && FDCS->version >= FDC_82072A) { + fdc_configure(); + FDCS->need_configure = 0; + } - switch (raw_cmd->rate & 0x03) { - case 3: - dtr = 1000; - break; - case 1: - dtr = 300; - if (FDCS->version >= FDC_82078) { - /* chose the default rate table, not the one - * where 1 = 2 Mbps */ - output_byte(FD_DRIVESPEC); - if (need_more_output() == MORE_OUTPUT) { - output_byte(UNIT(current_drive)); - output_byte(0xc0); - } - } - break; - case 2: - dtr = 250; - break; - } + switch (raw_cmd->rate & 0x03) { + case 3: + dtr = 1000; + break; + case 1: + dtr = 300; + if (FDCS->version >= FDC_82078) { + /* chose the default rate table, not the one + * where 1 = 2 Mbps */ + output_byte(FD_DRIVESPEC); + if (need_more_output() == MORE_OUTPUT) { + output_byte(UNIT(current_drive)); + output_byte(0xc0); + } + } + break; + case 2: + dtr = 250; + break; + } - if (FDCS->version >= FDC_82072) { - scale_dtr = dtr; - hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */ - hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */ - } + if (FDCS->version >= FDC_82072) { + scale_dtr = dtr; + hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */ + hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */ + } - /* Convert step rate from microseconds to milliseconds and 4 bits */ - srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR); - if (slow_floppy) - srt = srt / 4; + /* Convert step rate from microseconds to milliseconds and 4 bits */ + srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR); + if (slow_floppy) + srt = srt / 4; - SUPBOUND(srt, 0xf); - INFBOUND(srt, 0); + SUPBOUND(srt, 0xf); + INFBOUND(srt, 0); - hlt = DIV_ROUND_UP(DP->hlt * scale_dtr / 2, NOMINAL_DTR); - if (hlt < 0x01) - hlt = 0x01; - else if (hlt > 0x7f) - hlt = hlt_max_code; + hlt = DIV_ROUND_UP(DP->hlt * scale_dtr / 2, NOMINAL_DTR); + if (hlt < 0x01) + hlt = 0x01; + else if (hlt > 0x7f) + hlt = hlt_max_code; - hut = DIV_ROUND_UP(DP->hut * scale_dtr / 16, NOMINAL_DTR); - if (hut < 0x1) - hut = 0x1; - else if (hut > 0xf) - hut = hut_max_code; + hut = DIV_ROUND_UP(DP->hut * scale_dtr / 16, NOMINAL_DTR); + if (hut < 0x1) + hut = 0x1; + else if (hut > 0xf) + hut = hut_max_code; - spec1 = (srt << 4) | hut; - spec2 = (hlt << 1) | (use_virtual_dma & 1); + spec1 = (srt << 4) | hut; + spec2 = (hlt << 1) | (use_virtual_dma & 1); - /* If these parameters did not change, just return with success */ - if (FDCS->spec1 != spec1 || FDCS->spec2 != spec2) { - /* Go ahead and set spec1 and spec2 */ - output_byte(FD_SPECIFY); - output_byte(FDCS->spec1 = spec1); - output_byte(FDCS->spec2 = spec2); - } -} /* fdc_specify */ + /* If these parameters did not change, just return with success */ + if (FDCS->spec1 != spec1 || FDCS->spec2 != spec2) { + /* Go ahead and set spec1 and spec2 */ + output_byte(FD_SPECIFY); + output_byte(FDCS->spec1 = spec1); + output_byte(FDCS->spec2 = spec2); + } +} /* fdc_specify */ /* Set the FDC's data transfer rate on behalf of the specified drive. * NOTE: with 82072/82077 FDCs, changing the data rate requires a reissue @@ -1346,56 +1345,56 @@ static void fdc_specify(void) */ static int fdc_dtr(void) { - /* If data rate not already set to desired value, set it. */ - if ((raw_cmd->rate & 3) == FDCS->dtr) - return 0; + /* If data rate not already set to desired value, set it. */ + if ((raw_cmd->rate & 3) == FDCS->dtr) + return 0; - /* Set dtr */ - fd_outb(raw_cmd->rate & 3, FD_DCR); + /* Set dtr */ + fd_outb(raw_cmd->rate & 3, FD_DCR); - /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB) - * need a stabilization period of several milliseconds to be - * enforced after data rate changes before R/W operations. - * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) - */ - FDCS->dtr = raw_cmd->rate & 3; - return fd_wait_for_completion(jiffies + 2UL * HZ / 100, floppy_ready); -} /* fdc_dtr */ + /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB) + * need a stabilization period of several milliseconds to be + * enforced after data rate changes before R/W operations. + * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) + */ + FDCS->dtr = raw_cmd->rate & 3; + return fd_wait_for_completion(jiffies + 2UL * HZ / 100, floppy_ready); +} /* fdc_dtr */ static void tell_sector(void) { - pr_cont(": track %d, head %d, sector %d, size %d", - R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE); -} /* tell_sector */ + pr_cont(": track %d, head %d, sector %d, size %d", + R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE); +} /* tell_sector */ static void print_errors(void) { - DPRINT(""); - if (ST0 & ST0_ECE) { - pr_cont("Recalibrate failed!"); - } else if (ST2 & ST2_CRC) { - pr_cont("data CRC error"); - tell_sector(); - } else if (ST1 & ST1_CRC) { - pr_cont("CRC error"); - tell_sector(); - } else if ((ST1 & (ST1_MAM | ST1_ND)) || - (ST2 & ST2_MAM)) { - if (!probing) { - pr_cont("sector not found"); - tell_sector(); - } else - pr_cont("probe failed..."); - } else if (ST2 & ST2_WC) { /* seek error */ - pr_cont("wrong cylinder"); - } else if (ST2 & ST2_BC) { /* cylinder marked as bad */ - pr_cont("bad cylinder"); - } else { - pr_cont("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", - ST0, ST1, ST2); - tell_sector(); - } - pr_cont("\n"); + DPRINT(""); + if (ST0 & ST0_ECE) { + pr_cont("Recalibrate failed!"); + } else if (ST2 & ST2_CRC) { + pr_cont("data CRC error"); + tell_sector(); + } else if (ST1 & ST1_CRC) { + pr_cont("CRC error"); + tell_sector(); + } else if ((ST1 & (ST1_MAM | ST1_ND)) || + (ST2 & ST2_MAM)) { + if (!probing) { + pr_cont("sector not found"); + tell_sector(); + } else + pr_cont("probe failed..."); + } else if (ST2 & ST2_WC) { /* seek error */ + pr_cont("wrong cylinder"); + } else if (ST2 & ST2_BC) { /* cylinder marked as bad */ + pr_cont("bad cylinder"); + } else { + pr_cont("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", + ST0, ST1, ST2); + tell_sector(); + } + pr_cont("\n"); } /* @@ -1407,49 +1406,49 @@ static void print_errors(void) */ static int interpret_errors(void) { - char bad; + char bad; - if (inr != 7) { - DPRINT("-- FDC reply error\n"); - FDCS->reset = 1; - return 1; - } + if (inr != 7) { + DPRINT("-- FDC reply error\n"); + FDCS->reset = 1; + return 1; + } - /* check IC to find cause of interrupt */ - switch (ST0 & ST0_INTR) { - case 0x40: /* error occurred during command execution */ - if (ST1 & ST1_EOC) - return 0; /* occurs with pseudo-DMA */ - bad = 1; - if (ST1 & ST1_WP) { - DPRINT("Drive is write protected\n"); - clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); - cont->done(0); - bad = 2; - } else if (ST1 & ST1_ND) { - set_bit(FD_NEED_TWADDLE_BIT, &DRS->flags); - } else if (ST1 & ST1_OR) { - if (DP->flags & FTD_MSG) - DPRINT("Over/Underrun - retrying\n"); - bad = 0; - } else if (*errors >= DP->max_errors.reporting) { - print_errors(); - } - if (ST2 & ST2_WC || ST2 & ST2_BC) - /* wrong cylinder => recal */ - DRS->track = NEED_2_RECAL; - return bad; - case 0x80: /* invalid command given */ - DPRINT("Invalid FDC command given!\n"); - cont->done(0); - return 2; - case 0xc0: - DPRINT("Abnormal termination caused by polling\n"); - cont->error(); - return 2; - default: /* (0) Normal command termination */ - return 0; - } + /* check IC to find cause of interrupt */ + switch (ST0 & ST0_INTR) { + case 0x40: /* error occurred during command execution */ + if (ST1 & ST1_EOC) + return 0; /* occurs with pseudo-DMA */ + bad = 1; + if (ST1 & ST1_WP) { + DPRINT("Drive is write protected\n"); + clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); + cont->done(0); + bad = 2; + } else if (ST1 & ST1_ND) { + set_bit(FD_NEED_TWADDLE_BIT, &DRS->flags); + } else if (ST1 & ST1_OR) { + if (DP->flags & FTD_MSG) + DPRINT("Over/Underrun - retrying\n"); + bad = 0; + } else if (*errors >= DP->max_errors.reporting) { + print_errors(); + } + if (ST2 & ST2_WC || ST2 & ST2_BC) + /* wrong cylinder => recal */ + DRS->track = NEED_2_RECAL; + return bad; + case 0x80: /* invalid command given */ + DPRINT("Invalid FDC command given!\n"); + cont->done(0); + return 2; + case 0xc0: + DPRINT("Abnormal termination caused by polling\n"); + cont->error(); + return 2; + default: /* (0) Normal command termination */ + return 0; + } } /* @@ -1459,55 +1458,55 @@ static int interpret_errors(void) */ static void setup_rw_floppy(void) { - int i; - int r; - int flags; - unsigned long ready_date; - void (*function)(void); + int i; + int r; + int flags; + unsigned long ready_date; + void (*function)(void); - flags = raw_cmd->flags; - if (flags & (FD_RAW_READ | FD_RAW_WRITE)) - flags |= FD_RAW_INTR; + flags = raw_cmd->flags; + if (flags & (FD_RAW_READ | FD_RAW_WRITE)) + flags |= FD_RAW_INTR; - if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)) { - ready_date = DRS->spinup_date + DP->spinup; - /* If spinup will take a long time, rerun scandrives - * again just before spinup completion. Beware that - * after scandrives, we must again wait for selection. - */ - if (time_after(ready_date, jiffies + DP->select_delay)) { - ready_date -= DP->select_delay; - function = floppy_start; - } else - function = setup_rw_floppy; + if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)) { + ready_date = DRS->spinup_date + DP->spinup; + /* If spinup will take a long time, rerun scandrives + * again just before spinup completion. Beware that + * after scandrives, we must again wait for selection. + */ + if (time_after(ready_date, jiffies + DP->select_delay)) { + ready_date -= DP->select_delay; + function = floppy_start; + } else + function = setup_rw_floppy; - /* wait until the floppy is spinning fast enough */ - if (fd_wait_for_completion(ready_date, function)) - return; - } - if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE)) - setup_DMA(); + /* wait until the floppy is spinning fast enough */ + if (fd_wait_for_completion(ready_date, function)) + return; + } + if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE)) + setup_DMA(); - if (flags & FD_RAW_INTR) - do_floppy = main_command_interrupt; + if (flags & FD_RAW_INTR) + do_floppy = main_command_interrupt; - r = 0; - for (i = 0; i < raw_cmd->cmd_count; i++) - r |= output_byte(raw_cmd->cmd[i]); + r = 0; + for (i = 0; i < raw_cmd->cmd_count; i++) + r |= output_byte(raw_cmd->cmd[i]); - debugt(__func__, "rw_command"); + debugt(__func__, "rw_command"); - if (r) { - cont->error(); - reset_fdc(); - return; - } + if (r) { + cont->error(); + reset_fdc(); + return; + } - if (!(flags & FD_RAW_INTR)) { - inr = result(); - cont->interrupt(); - } else if (flags & FD_RAW_NEED_DISK) - fd_watchdog(); + if (!(flags & FD_RAW_INTR)) { + inr = result(); + cont->interrupt(); + } else if (flags & FD_RAW_NEED_DISK) + fd_watchdog(); } static int blind_seek; @@ -1518,231 +1517,231 @@ static int blind_seek; */ static void seek_interrupt(void) { - debugt(__func__, ""); - if (inr != 2 || (ST0 & 0xF8) != 0x20) { - DPRINT("seek failed\n"); - DRS->track = NEED_2_RECAL; - cont->error(); - cont->redo(); - return; - } - if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) { - debug_dcl(DP->flags, - "clearing NEWCHANGE flag because of effective seek\n"); - debug_dcl(DP->flags, "jiffies=%lu\n", jiffies); - clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); - /* effective seek */ - DRS->select_date = jiffies; - } - DRS->track = ST1; - floppy_ready(); + debugt(__func__, ""); + if (inr != 2 || (ST0 & 0xF8) != 0x20) { + DPRINT("seek failed\n"); + DRS->track = NEED_2_RECAL; + cont->error(); + cont->redo(); + return; + } + if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) { + debug_dcl(DP->flags, + "clearing NEWCHANGE flag because of effective seek\n"); + debug_dcl(DP->flags, "jiffies=%lu\n", jiffies); + clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); + /* effective seek */ + DRS->select_date = jiffies; + } + DRS->track = ST1; + floppy_ready(); } static void check_wp(void) { - if (test_bit(FD_VERIFY_BIT, &DRS->flags)) { - /* check write protection */ - output_byte(FD_GETSTATUS); - output_byte(UNIT(current_drive)); - if (result() != 1) { - FDCS->reset = 1; - return; - } - clear_bit(FD_VERIFY_BIT, &DRS->flags); - clear_bit(FD_NEED_TWADDLE_BIT, &DRS->flags); - debug_dcl(DP->flags, - "checking whether disk is write protected\n"); - debug_dcl(DP->flags, "wp=%x\n", ST3 & 0x40); - if (!(ST3 & 0x40)) - set_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); - else - clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); - } + if (test_bit(FD_VERIFY_BIT, &DRS->flags)) { + /* check write protection */ + output_byte(FD_GETSTATUS); + output_byte(UNIT(current_drive)); + if (result() != 1) { + FDCS->reset = 1; + return; + } + clear_bit(FD_VERIFY_BIT, &DRS->flags); + clear_bit(FD_NEED_TWADDLE_BIT, &DRS->flags); + debug_dcl(DP->flags, + "checking whether disk is write protected\n"); + debug_dcl(DP->flags, "wp=%x\n", ST3 & 0x40); + if (!(ST3 & 0x40)) + set_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); + else + clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); + } } static void seek_floppy(void) { - int track; + int track; - blind_seek = 0; + blind_seek = 0; - debug_dcl(DP->flags, "calling disk change from %s\n", __func__); + debug_dcl(DP->flags, "calling disk change from %s\n", __func__); - if (!test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) && - disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) { - /* the media changed flag should be cleared after the seek. - * If it isn't, this means that there is really no disk in - * the drive. - */ - set_bit(FD_DISK_CHANGED_BIT, &DRS->flags); - cont->done(0); - cont->redo(); - return; - } - if (DRS->track <= NEED_1_RECAL) { - recalibrate_floppy(); - return; - } else if (test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) && - (raw_cmd->flags & FD_RAW_NEED_DISK) && - (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) { - /* we seek to clear the media-changed condition. Does anybody - * know a more elegant way, which works on all drives? */ - if (raw_cmd->track) - track = raw_cmd->track - 1; - else { - if (DP->flags & FD_SILENT_DCL_CLEAR) { - set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0); - blind_seek = 1; - raw_cmd->flags |= FD_RAW_NEED_SEEK; - } - track = 1; - } - } else { - check_wp(); - if (raw_cmd->track != DRS->track && - (raw_cmd->flags & FD_RAW_NEED_SEEK)) - track = raw_cmd->track; - else { - setup_rw_floppy(); - return; - } - } + if (!test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) && + disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) { + /* the media changed flag should be cleared after the seek. + * If it isn't, this means that there is really no disk in + * the drive. + */ + set_bit(FD_DISK_CHANGED_BIT, &DRS->flags); + cont->done(0); + cont->redo(); + return; + } + if (DRS->track <= NEED_1_RECAL) { + recalibrate_floppy(); + return; + } else if (test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) && + (raw_cmd->flags & FD_RAW_NEED_DISK) && + (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) { + /* we seek to clear the media-changed condition. Does anybody + * know a more elegant way, which works on all drives? */ + if (raw_cmd->track) + track = raw_cmd->track - 1; + else { + if (DP->flags & FD_SILENT_DCL_CLEAR) { + set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0); + blind_seek = 1; + raw_cmd->flags |= FD_RAW_NEED_SEEK; + } + track = 1; + } + } else { + check_wp(); + if (raw_cmd->track != DRS->track && + (raw_cmd->flags & FD_RAW_NEED_SEEK)) + track = raw_cmd->track; + else { + setup_rw_floppy(); + return; + } + } - do_floppy = seek_interrupt; - output_byte(FD_SEEK); - output_byte(UNIT(current_drive)); - if (output_byte(track) < 0) { - reset_fdc(); - return; - } - debugt(__func__, ""); + do_floppy = seek_interrupt; + output_byte(FD_SEEK); + output_byte(UNIT(current_drive)); + if (output_byte(track) < 0) { + reset_fdc(); + return; + } + debugt(__func__, ""); } static void recal_interrupt(void) { - debugt(__func__, ""); - if (inr != 2) - FDCS->reset = 1; - else if (ST0 & ST0_ECE) { - switch (DRS->track) { - case NEED_1_RECAL: - debugt(__func__, "need 1 recal"); - /* after a second recalibrate, we still haven't - * reached track 0. Probably no drive. Raise an - * error, as failing immediately might upset - * computers possessed by the Devil :-) */ - cont->error(); - cont->redo(); - return; - case NEED_2_RECAL: - debugt(__func__, "need 2 recal"); - /* If we already did a recalibrate, - * and we are not at track 0, this - * means we have moved. (The only way - * not to move at recalibration is to - * be already at track 0.) Clear the - * new change flag */ - debug_dcl(DP->flags, - "clearing NEWCHANGE flag because of second recalibrate\n"); + debugt(__func__, ""); + if (inr != 2) + FDCS->reset = 1; + else if (ST0 & ST0_ECE) { + switch (DRS->track) { + case NEED_1_RECAL: + debugt(__func__, "need 1 recal"); + /* after a second recalibrate, we still haven't + * reached track 0. Probably no drive. Raise an + * error, as failing immediately might upset + * computers possessed by the Devil :-) */ + cont->error(); + cont->redo(); + return; + case NEED_2_RECAL: + debugt(__func__, "need 2 recal"); + /* If we already did a recalibrate, + * and we are not at track 0, this + * means we have moved. (The only way + * not to move at recalibration is to + * be already at track 0.) Clear the + * new change flag */ + debug_dcl(DP->flags, + "clearing NEWCHANGE flag because of second recalibrate\n"); - clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); - DRS->select_date = jiffies; - /* fall through */ - default: - debugt(__func__, "default"); - /* Recalibrate moves the head by at - * most 80 steps. If after one - * recalibrate we don't have reached - * track 0, this might mean that we - * started beyond track 80. Try - * again. */ - DRS->track = NEED_1_RECAL; - break; - } - } else - DRS->track = ST1; - floppy_ready(); + clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); + DRS->select_date = jiffies; + /* fall through */ + default: + debugt(__func__, "default"); + /* Recalibrate moves the head by at + * most 80 steps. If after one + * recalibrate we don't have reached + * track 0, this might mean that we + * started beyond track 80. Try + * again. */ + DRS->track = NEED_1_RECAL; + break; + } + } else + DRS->track = ST1; + floppy_ready(); } static void print_result(char *message, int inr) { - int i; + int i; - DPRINT("%s ", message); - if (inr >= 0) - for (i = 0; i < inr; i++) - pr_cont("repl[%d]=%x ", i, reply_buffer[i]); - pr_cont("\n"); + DPRINT("%s ", message); + if (inr >= 0) + for (i = 0; i < inr; i++) + pr_cont("repl[%d]=%x ", i, reply_buffer[i]); + pr_cont("\n"); } /* interrupt handler. Note that this can be called externally on the Sparc */ irqreturn_t floppy_interrupt(int irq, void *dev_id) { - int do_print; - unsigned long f; - void (*handler)(void) = do_floppy; + int do_print; + unsigned long f; + void (*handler)(void) = do_floppy; - lasthandler = handler; - interruptjiffies = jiffies; + lasthandler = handler; + interruptjiffies = jiffies; - f = claim_dma_lock(); - fd_disable_dma(); - release_dma_lock(f); + f = claim_dma_lock(); + fd_disable_dma(); + release_dma_lock(f); - do_floppy = NULL; - if (fdc >= N_FDC || FDCS->address == -1) { - /* we don't even know which FDC is the culprit */ - pr_info("DOR0=%x\n", fdc_state[0].dor); - pr_info("floppy interrupt on bizarre fdc %d\n", fdc); - pr_info("handler=%ps\n", handler); - is_alive(__func__, "bizarre fdc"); - return IRQ_NONE; - } + do_floppy = NULL; + if (fdc >= N_FDC || FDCS->address == -1) { + /* we don't even know which FDC is the culprit */ + pr_info("DOR0=%x\n", fdc_state[0].dor); + pr_info("floppy interrupt on bizarre fdc %d\n", fdc); + pr_info("handler=%ps\n", handler); + is_alive(__func__, "bizarre fdc"); + return IRQ_NONE; + } - FDCS->reset = 0; - /* We have to clear the reset flag here, because apparently on boxes - * with level triggered interrupts (PS/2, Sparc, ...), it is needed to - * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the - * emission of the SENSEI's. - * It is OK to emit floppy commands because we are in an interrupt - * handler here, and thus we have to fear no interference of other - * activity. - */ + FDCS->reset = 0; + /* We have to clear the reset flag here, because apparently on boxes + * with level triggered interrupts (PS/2, Sparc, ...), it is needed to + * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the + * emission of the SENSEI's. + * It is OK to emit floppy commands because we are in an interrupt + * handler here, and thus we have to fear no interference of other + * activity. + */ - do_print = !handler && print_unex && initialized; + do_print = !handler && print_unex && initialized; - inr = result(); - if (do_print) - print_result("unexpected interrupt", inr); - if (inr == 0) { - int max_sensei = 4; - do { - output_byte(FD_SENSEI); - inr = result(); - if (do_print) - print_result("sensei", inr); - max_sensei--; - } while ((ST0 & 0x83) != UNIT(current_drive) && - inr == 2 && max_sensei); - } - if (!handler) { - FDCS->reset = 1; - return IRQ_NONE; - } - schedule_bh(handler); - is_alive(__func__, "normal interrupt end"); + inr = result(); + if (do_print) + print_result("unexpected interrupt", inr); + if (inr == 0) { + int max_sensei = 4; + do { + output_byte(FD_SENSEI); + inr = result(); + if (do_print) + print_result("sensei", inr); + max_sensei--; + } while ((ST0 & 0x83) != UNIT(current_drive) && + inr == 2 && max_sensei); + } + if (!handler) { + FDCS->reset = 1; + return IRQ_NONE; + } + schedule_bh(handler); + is_alive(__func__, "normal interrupt end"); - /* FIXME! Was it really for us? */ - return IRQ_HANDLED; + /* FIXME! Was it really for us? */ + return IRQ_HANDLED; } static void recalibrate_floppy(void) { - debugt(__func__, ""); - do_floppy = recal_interrupt; - output_byte(FD_RECALIBRATE); - if (output_byte(UNIT(current_drive)) < 0) - reset_fdc(); + debugt(__func__, ""); + do_floppy = recal_interrupt; + output_byte(FD_RECALIBRATE); + if (output_byte(UNIT(current_drive)) < 0) + reset_fdc(); } /* @@ -1750,13 +1749,13 @@ static void recalibrate_floppy(void) */ static void reset_interrupt(void) { - debugt(__func__, ""); - result(); /* get the status ready for set_fdc */ - if (FDCS->reset) { - pr_info("reset set in interrupt, calling %ps\n", cont->error); - cont->error(); /* a reset just after a reset. BAD! */ - } - cont->redo(); + debugt(__func__, ""); + result(); /* get the status ready for set_fdc */ + if (FDCS->reset) { + pr_info("reset set in interrupt, calling %ps\n", cont->error); + cont->error(); /* a reset just after a reset. BAD! */ + } + cont->redo(); } /* @@ -1765,173 +1764,173 @@ static void reset_interrupt(void) */ static void reset_fdc(void) { - unsigned long flags; + unsigned long flags; - do_floppy = reset_interrupt; - FDCS->reset = 0; - reset_fdc_info(0); + do_floppy = reset_interrupt; + FDCS->reset = 0; + reset_fdc_info(0); - /* Pseudo-DMA may intercept 'reset finished' interrupt. */ - /* Irrelevant for systems with true DMA (i386). */ + /* Pseudo-DMA may intercept 'reset finished' interrupt. */ + /* Irrelevant for systems with true DMA (i386). */ - flags = claim_dma_lock(); - fd_disable_dma(); - release_dma_lock(flags); + flags = claim_dma_lock(); + fd_disable_dma(); + release_dma_lock(flags); - if (FDCS->version >= FDC_82072A) - fd_outb(0x80 | (FDCS->dtr & 3), FD_STATUS); - else { - fd_outb(FDCS->dor & ~0x04, FD_DOR); - udelay(FD_RESET_DELAY); - fd_outb(FDCS->dor, FD_DOR); - } + if (FDCS->version >= FDC_82072A) + fd_outb(0x80 | (FDCS->dtr & 3), FD_STATUS); + else { + fd_outb(FDCS->dor & ~0x04, FD_DOR); + udelay(FD_RESET_DELAY); + fd_outb(FDCS->dor, FD_DOR); + } } static void show_floppy(void) { - int i; + int i; - pr_info("\n"); - pr_info("floppy driver state\n"); - pr_info("-------------------\n"); - pr_info("now=%lu last interrupt=%lu diff=%lu last called handler=%ps\n", - jiffies, interruptjiffies, jiffies - interruptjiffies, - lasthandler); + pr_info("\n"); + pr_info("floppy driver state\n"); + pr_info("-------------------\n"); + pr_info("now=%lu last interrupt=%lu diff=%lu last called handler=%ps\n", + jiffies, interruptjiffies, jiffies - interruptjiffies, + lasthandler); - pr_info("timeout_message=%s\n", timeout_message); - pr_info("last output bytes:\n"); - for (i = 0; i < OLOGSIZE; i++) - pr_info("%2x %2x %lu\n", - output_log[(i + output_log_pos) % OLOGSIZE].data, - output_log[(i + output_log_pos) % OLOGSIZE].status, - output_log[(i + output_log_pos) % OLOGSIZE].jiffies); - pr_info("last result at %lu\n", resultjiffies); - pr_info("last redo_fd_request at %lu\n", lastredo); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, - reply_buffer, resultsize, true); + pr_info("timeout_message=%s\n", timeout_message); + pr_info("last output bytes:\n"); + for (i = 0; i < OLOGSIZE; i++) + pr_info("%2x %2x %lu\n", + output_log[(i + output_log_pos) % OLOGSIZE].data, + output_log[(i + output_log_pos) % OLOGSIZE].status, + output_log[(i + output_log_pos) % OLOGSIZE].jiffies); + pr_info("last result at %lu\n", resultjiffies); + pr_info("last redo_fd_request at %lu\n", lastredo); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, + reply_buffer, resultsize, true); - pr_info("status=%x\n", fd_inb(FD_STATUS)); - pr_info("fdc_busy=%lu\n", fdc_busy); - if (do_floppy) - pr_info("do_floppy=%ps\n", do_floppy); - if (work_pending(&floppy_work)) - pr_info("floppy_work.func=%ps\n", floppy_work.func); - if (delayed_work_pending(&fd_timer)) - pr_info("delayed work.function=%p expires=%ld\n", - fd_timer.work.func, - fd_timer.timer.expires - jiffies); - if (delayed_work_pending(&fd_timeout)) - pr_info("timer_function=%p expires=%ld\n", - fd_timeout.work.func, - fd_timeout.timer.expires - jiffies); + pr_info("status=%x\n", fd_inb(FD_STATUS)); + pr_info("fdc_busy=%lu\n", fdc_busy); + if (do_floppy) + pr_info("do_floppy=%ps\n", do_floppy); + if (work_pending(&floppy_work)) + pr_info("floppy_work.func=%ps\n", floppy_work.func); + if (delayed_work_pending(&fd_timer)) + pr_info("delayed work.function=%p expires=%ld\n", + fd_timer.work.func, + fd_timer.timer.expires - jiffies); + if (delayed_work_pending(&fd_timeout)) + pr_info("timer_function=%p expires=%ld\n", + fd_timeout.work.func, + fd_timeout.timer.expires - jiffies); - pr_info("cont=%p\n", cont); - pr_info("current_req=%p\n", current_req); - pr_info("command_status=%d\n", command_status); - pr_info("\n"); + pr_info("cont=%p\n", cont); + pr_info("current_req=%p\n", current_req); + pr_info("command_status=%d\n", command_status); + pr_info("\n"); } static void floppy_shutdown(struct work_struct *arg) { - unsigned long flags; + unsigned long flags; - if (initialized) - show_floppy(); - cancel_activity(); + if (initialized) + show_floppy(); + cancel_activity(); - flags = claim_dma_lock(); - fd_disable_dma(); - release_dma_lock(flags); + flags = claim_dma_lock(); + fd_disable_dma(); + release_dma_lock(flags); - /* avoid dma going to a random drive after shutdown */ + /* avoid dma going to a random drive after shutdown */ - if (initialized) - DPRINT("floppy timeout called\n"); - FDCS->reset = 1; - if (cont) { - cont->done(0); - cont->redo(); /* this will recall reset when needed */ - } else { - pr_info("no cont in shutdown!\n"); - process_fd_request(); - } - is_alive(__func__, ""); + if (initialized) + DPRINT("floppy timeout called\n"); + FDCS->reset = 1; + if (cont) { + cont->done(0); + cont->redo(); /* this will recall reset when needed */ + } else { + pr_info("no cont in shutdown!\n"); + process_fd_request(); + } + is_alive(__func__, ""); } /* start motor, check media-changed condition and write protection */ static int start_motor(void (*function)(void)) { - int mask; - int data; + int mask; + int data; - mask = 0xfc; - data = UNIT(current_drive); - if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)) { - if (!(FDCS->dor & (0x10 << UNIT(current_drive)))) { - set_debugt(); - /* no read since this drive is running */ - DRS->first_read_date = 0; - /* note motor start time if motor is not yet running */ - DRS->spinup_date = jiffies; - data |= (0x10 << UNIT(current_drive)); - } - } else if (FDCS->dor & (0x10 << UNIT(current_drive))) - mask &= ~(0x10 << UNIT(current_drive)); + mask = 0xfc; + data = UNIT(current_drive); + if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)) { + if (!(FDCS->dor & (0x10 << UNIT(current_drive)))) { + set_debugt(); + /* no read since this drive is running */ + DRS->first_read_date = 0; + /* note motor start time if motor is not yet running */ + DRS->spinup_date = jiffies; + data |= (0x10 << UNIT(current_drive)); + } + } else if (FDCS->dor & (0x10 << UNIT(current_drive))) + mask &= ~(0x10 << UNIT(current_drive)); - /* starts motor and selects floppy */ - del_timer(motor_off_timer + current_drive); - set_dor(fdc, mask, data); + /* starts motor and selects floppy */ + del_timer(motor_off_timer + current_drive); + set_dor(fdc, mask, data); - /* wait_for_completion also schedules reset if needed. */ - return fd_wait_for_completion(DRS->select_date + DP->select_delay, - function); + /* wait_for_completion also schedules reset if needed. */ + return fd_wait_for_completion(DRS->select_date + DP->select_delay, + function); } static void floppy_ready(void) { - if (FDCS->reset) { - reset_fdc(); - return; - } - if (start_motor(floppy_ready)) - return; - if (fdc_dtr()) - return; + if (FDCS->reset) { + reset_fdc(); + return; + } + if (start_motor(floppy_ready)) + return; + if (fdc_dtr()) + return; - debug_dcl(DP->flags, "calling disk change from floppy_ready\n"); - if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) && - disk_change(current_drive) && !DP->select_delay) - twaddle(); /* this clears the dcl on certain - * drive/controller combinations */ + debug_dcl(DP->flags, "calling disk change from floppy_ready\n"); + if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) && + disk_change(current_drive) && !DP->select_delay) + twaddle(); /* this clears the dcl on certain + * drive/controller combinations */ #ifdef fd_chose_dma_mode - if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) { - unsigned long flags = claim_dma_lock(); - fd_chose_dma_mode(raw_cmd->kernel_data, raw_cmd->length); - release_dma_lock(flags); - } + if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) { + unsigned long flags = claim_dma_lock(); + fd_chose_dma_mode(raw_cmd->kernel_data, raw_cmd->length); + release_dma_lock(flags); + } #endif - if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)) { - perpendicular_mode(); - fdc_specify(); /* must be done here because of hut, hlt ... */ - seek_floppy(); - } else { - if ((raw_cmd->flags & FD_RAW_READ) || - (raw_cmd->flags & FD_RAW_WRITE)) - fdc_specify(); - setup_rw_floppy(); - } + if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)) { + perpendicular_mode(); + fdc_specify(); /* must be done here because of hut, hlt ... */ + seek_floppy(); + } else { + if ((raw_cmd->flags & FD_RAW_READ) || + (raw_cmd->flags & FD_RAW_WRITE)) + fdc_specify(); + setup_rw_floppy(); + } } static void floppy_start(void) { - reschedule_timeout(current_reqD, "floppy start"); + reschedule_timeout(current_reqD, "floppy start"); - scandrives(); - debug_dcl(DP->flags, "setting NEWCHANGE in floppy_start\n"); - set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); - floppy_ready(); + scandrives(); + debug_dcl(DP->flags, "setting NEWCHANGE in floppy_start\n"); + set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); + floppy_ready(); } /* @@ -1950,74 +1949,74 @@ static void floppy_start(void) static void do_wakeup(void) { - reschedule_timeout(MAXTIMEOUT, "do wakeup"); - cont = NULL; - command_status += 2; - wake_up(&command_done); + reschedule_timeout(MAXTIMEOUT, "do wakeup"); + cont = NULL; + command_status += 2; + wake_up(&command_done); } static const struct cont_t wakeup_cont = { - .interrupt = empty, - .redo = do_wakeup, - .error = empty, - .done = (done_f)empty + .interrupt = empty, + .redo = do_wakeup, + .error = empty, + .done = (done_f)empty }; static const struct cont_t intr_cont = { - .interrupt = empty, - .redo = process_fd_request, - .error = empty, - .done = (done_f)empty + .interrupt = empty, + .redo = process_fd_request, + .error = empty, + .done = (done_f)empty }; static int wait_til_done(void (*handler)(void), bool interruptible) { - int ret; + int ret; - schedule_bh(handler); + schedule_bh(handler); - if (interruptible) - wait_event_interruptible(command_done, command_status >= 2); - else - wait_event(command_done, command_status >= 2); + if (interruptible) + wait_event_interruptible(command_done, command_status >= 2); + else + wait_event(command_done, command_status >= 2); - if (command_status < 2) { - cancel_activity(); - cont = &intr_cont; - reset_fdc(); - return -EINTR; - } + if (command_status < 2) { + cancel_activity(); + cont = &intr_cont; + reset_fdc(); + return -EINTR; + } - if (FDCS->reset) - command_status = FD_COMMAND_ERROR; - if (command_status == FD_COMMAND_OKAY) - ret = 0; - else - ret = -EIO; - command_status = FD_COMMAND_NONE; - return ret; + if (FDCS->reset) + command_status = FD_COMMAND_ERROR; + if (command_status == FD_COMMAND_OKAY) + ret = 0; + else + ret = -EIO; + command_status = FD_COMMAND_NONE; + return ret; } static void generic_done(int result) { - command_status = result; - cont = &wakeup_cont; + command_status = result; + cont = &wakeup_cont; } static void generic_success(void) { - cont->done(1); + cont->done(1); } static void generic_failure(void) { - cont->done(0); + cont->done(0); } static void success_and_wakeup(void) { - generic_success(); - cont->redo(); + generic_success(); + cont->redo(); } /* @@ -2027,49 +2026,49 @@ static void success_and_wakeup(void) static int next_valid_format(void) { - int probed_format; + int probed_format; - probed_format = DRS->probed_format; - while (1) { - if (probed_format >= 8 || !DP->autodetect[probed_format]) { - DRS->probed_format = 0; - return 1; - } - if (floppy_type[DP->autodetect[probed_format]].sect) { - DRS->probed_format = probed_format; - return 0; - } - probed_format++; - } + probed_format = DRS->probed_format; + while (1) { + if (probed_format >= 8 || !DP->autodetect[probed_format]) { + DRS->probed_format = 0; + return 1; + } + if (floppy_type[DP->autodetect[probed_format]].sect) { + DRS->probed_format = probed_format; + return 0; + } + probed_format++; + } } static void bad_flp_intr(void) { - int err_count; + int err_count; - if (probing) { - DRS->probed_format++; - if (!next_valid_format()) - return; - } - err_count = ++(*errors); - INFBOUND(DRWE->badness, err_count); - if (err_count > DP->max_errors.abort) - cont->done(0); - if (err_count > DP->max_errors.reset) - FDCS->reset = 1; - else if (err_count > DP->max_errors.recal) - DRS->track = NEED_2_RECAL; + if (probing) { + DRS->probed_format++; + if (!next_valid_format()) + return; + } + err_count = ++(*errors); + INFBOUND(DRWE->badness, err_count); + if (err_count > DP->max_errors.abort) + cont->done(0); + if (err_count > DP->max_errors.reset) + FDCS->reset = 1; + else if (err_count > DP->max_errors.recal) + DRS->track = NEED_2_RECAL; } static void set_floppy(int drive) { - int type = ITYPE(UDRS->fd_device); + int type = ITYPE(UDRS->fd_device); - if (type) - _floppy = floppy_type + type; - else - _floppy = current_type[drive]; + if (type) + _floppy = floppy_type + type; + else + _floppy = current_type[drive]; } /* @@ -2078,15 +2077,15 @@ static void set_floppy(int drive) */ static void format_interrupt(void) { - switch (interpret_errors()) { - case 1: - cont->error(); - case 2: - break; - case 0: - cont->done(1); - } - cont->redo(); + switch (interpret_errors()) { + case 1: + cont->error(); + case 2: + break; + case 0: + cont->done(1); + } + cont->redo(); } #define FM_MODE(x, y) ((y) & ~(((x)->rate & 0x80) >> 1)) @@ -2094,114 +2093,114 @@ static void format_interrupt(void) static void setup_format_params(int track) { - int n; - int il; - int count; - int head_shift; - int track_shift; - struct fparm { - unsigned char track, head, sect, size; - } *here = (struct fparm *)floppy_track_buffer; + int n; + int il; + int count; + int head_shift; + int track_shift; + struct fparm { + unsigned char track, head, sect, size; + } *here = (struct fparm *)floppy_track_buffer; - raw_cmd = &default_raw_cmd; - raw_cmd->track = track; + raw_cmd = &default_raw_cmd; + raw_cmd->track = track; - raw_cmd->flags = (FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | - FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK); - raw_cmd->rate = _floppy->rate & 0x43; - raw_cmd->cmd_count = NR_F; - COMMAND = FM_MODE(_floppy, FD_FORMAT); - DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, format_req.head); - F_SIZECODE = FD_SIZECODE(_floppy); - F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE; - F_GAP = _floppy->fmt_gap; - F_FILL = FD_FILL_BYTE; + raw_cmd->flags = (FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | + FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK); + raw_cmd->rate = _floppy->rate & 0x43; + raw_cmd->cmd_count = NR_F; + COMMAND = FM_MODE(_floppy, FD_FORMAT); + DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, format_req.head); + F_SIZECODE = FD_SIZECODE(_floppy); + F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE; + F_GAP = _floppy->fmt_gap; + F_FILL = FD_FILL_BYTE; - raw_cmd->kernel_data = floppy_track_buffer; - raw_cmd->length = 4 * F_SECT_PER_TRACK; + raw_cmd->kernel_data = floppy_track_buffer; + raw_cmd->length = 4 * F_SECT_PER_TRACK; - /* allow for about 30ms for data transport per track */ - head_shift = (F_SECT_PER_TRACK + 5) / 6; + /* allow for about 30ms for data transport per track */ + head_shift = (F_SECT_PER_TRACK + 5) / 6; - /* a ``cylinder'' is two tracks plus a little stepping time */ - track_shift = 2 * head_shift + 3; + /* a ``cylinder'' is two tracks plus a little stepping time */ + track_shift = 2 * head_shift + 3; - /* position of logical sector 1 on this track */ - n = (track_shift * format_req.track + head_shift * format_req.head) - % F_SECT_PER_TRACK; + /* position of logical sector 1 on this track */ + n = (track_shift * format_req.track + head_shift * format_req.head) + % F_SECT_PER_TRACK; - /* determine interleave */ - il = 1; - if (_floppy->fmt_gap < 0x22) - il++; + /* determine interleave */ + il = 1; + if (_floppy->fmt_gap < 0x22) + il++; - /* initialize field */ - for (count = 0; count < F_SECT_PER_TRACK; ++count) { - here[count].track = format_req.track; - here[count].head = format_req.head; - here[count].sect = 0; - here[count].size = F_SIZECODE; - } - /* place logical sectors */ - for (count = 1; count <= F_SECT_PER_TRACK; ++count) { - here[n].sect = count; - n = (n + il) % F_SECT_PER_TRACK; - if (here[n].sect) { /* sector busy, find next free sector */ - ++n; - if (n >= F_SECT_PER_TRACK) { - n -= F_SECT_PER_TRACK; - while (here[n].sect) - ++n; - } - } - } - if (_floppy->stretch & FD_SECTBASEMASK) { - for (count = 0; count < F_SECT_PER_TRACK; count++) - here[count].sect += FD_SECTBASE(_floppy) - 1; - } + /* initialize field */ + for (count = 0; count < F_SECT_PER_TRACK; ++count) { + here[count].track = format_req.track; + here[count].head = format_req.head; + here[count].sect = 0; + here[count].size = F_SIZECODE; + } + /* place logical sectors */ + for (count = 1; count <= F_SECT_PER_TRACK; ++count) { + here[n].sect = count; + n = (n + il) % F_SECT_PER_TRACK; + if (here[n].sect) { /* sector busy, find next free sector */ + ++n; + if (n >= F_SECT_PER_TRACK) { + n -= F_SECT_PER_TRACK; + while (here[n].sect) + ++n; + } + } + } + if (_floppy->stretch & FD_SECTBASEMASK) { + for (count = 0; count < F_SECT_PER_TRACK; count++) + here[count].sect += FD_SECTBASE(_floppy) - 1; + } } static void redo_format(void) { - buffer_track = -1; - setup_format_params(format_req.track << STRETCH(_floppy)); - floppy_start(); - debugt(__func__, "queue format request"); + buffer_track = -1; + setup_format_params(format_req.track << STRETCH(_floppy)); + floppy_start(); + debugt(__func__, "queue format request"); } static const struct cont_t format_cont = { - .interrupt = format_interrupt, - .redo = redo_format, - .error = bad_flp_intr, - .done = generic_done + .interrupt = format_interrupt, + .redo = redo_format, + .error = bad_flp_intr, + .done = generic_done }; static int do_format(int drive, struct format_descr *tmp_format_req) { - int ret; + int ret; - if (lock_fdc(drive)) - return -EINTR; + if (lock_fdc(drive)) + return -EINTR; - set_floppy(drive); - if (!_floppy || - _floppy->track > DP->tracks || - tmp_format_req->track >= _floppy->track || - tmp_format_req->head >= _floppy->head || - (_floppy->sect << 2) % (1 << FD_SIZECODE(_floppy)) || - !_floppy->fmt_gap) { - process_fd_request(); - return -EINVAL; - } - format_req = *tmp_format_req; - format_errors = 0; - cont = &format_cont; - errors = &format_errors; - ret = wait_til_done(redo_format, true); - if (ret == -EINTR) - return -EINTR; - process_fd_request(); - return ret; + set_floppy(drive); + if (!_floppy || + _floppy->track > DP->tracks || + tmp_format_req->track >= _floppy->track || + tmp_format_req->head >= _floppy->head || + (_floppy->sect << 2) % (1 << FD_SIZECODE(_floppy)) || + !_floppy->fmt_gap) { + process_fd_request(); + return -EINVAL; + } + format_req = *tmp_format_req; + format_errors = 0; + cont = &format_cont; + errors = &format_errors; + ret = wait_til_done(redo_format, true); + if (ret == -EINTR) + return -EINTR; + process_fd_request(); + return ret; } /* @@ -2211,189 +2210,189 @@ static int do_format(int drive, struct format_descr *tmp_format_req) static void floppy_end_request(struct request *req, blk_status_t error) { - unsigned int nr_sectors = current_count_sectors; - unsigned int drive = (unsigned long)req->rq_disk->private_data; + unsigned int nr_sectors = current_count_sectors; + unsigned int drive = (unsigned long)req->rq_disk->private_data; - /* current_count_sectors can be zero if transfer failed */ - if (error) - nr_sectors = blk_rq_cur_sectors(req); - if (blk_update_request(req, error, nr_sectors << 9)) - return; - __blk_mq_end_request(req, error); + /* current_count_sectors can be zero if transfer failed */ + if (error) + nr_sectors = blk_rq_cur_sectors(req); + if (blk_update_request(req, error, nr_sectors << 9)) + return; + __blk_mq_end_request(req, error); - /* We're done with the request */ - floppy_off(drive); - current_req = NULL; + /* We're done with the request */ + floppy_off(drive); + current_req = NULL; } /* new request_done. Can handle physical sectors which are smaller than a * logical buffer */ static void request_done(int uptodate) { - struct request *req = current_req; - int block; - char msg[sizeof("request done ") + sizeof(int) * 3]; + struct request *req = current_req; + int block; + char msg[sizeof("request done ") + sizeof(int) * 3]; - probing = 0; - snprintf(msg, sizeof(msg), "request done %d", uptodate); - reschedule_timeout(MAXTIMEOUT, msg); + probing = 0; + snprintf(msg, sizeof(msg), "request done %d", uptodate); + reschedule_timeout(MAXTIMEOUT, msg); - if (!req) { - pr_info("floppy.c: no request in request_done\n"); - return; - } + if (!req) { + pr_info("floppy.c: no request in request_done\n"); + return; + } - if (uptodate) { - /* maintain values for invalidation on geometry - * change */ - block = current_count_sectors + blk_rq_pos(req); - INFBOUND(DRS->maxblock, block); - if (block > _floppy->sect) - DRS->maxtrack = 1; + if (uptodate) { + /* maintain values for invalidation on geometry + * change */ + block = current_count_sectors + blk_rq_pos(req); + INFBOUND(DRS->maxblock, block); + if (block > _floppy->sect) + DRS->maxtrack = 1; - floppy_end_request(req, 0); - } else { - if (rq_data_dir(req) == WRITE) { - /* record write error information */ - DRWE->write_errors++; - if (DRWE->write_errors == 1) { - DRWE->first_error_sector = blk_rq_pos(req); - DRWE->first_error_generation = DRS->generation; - } - DRWE->last_error_sector = blk_rq_pos(req); - DRWE->last_error_generation = DRS->generation; - } - floppy_end_request(req, BLK_STS_IOERR); - } + floppy_end_request(req, 0); + } else { + if (rq_data_dir(req) == WRITE) { + /* record write error information */ + DRWE->write_errors++; + if (DRWE->write_errors == 1) { + DRWE->first_error_sector = blk_rq_pos(req); + DRWE->first_error_generation = DRS->generation; + } + DRWE->last_error_sector = blk_rq_pos(req); + DRWE->last_error_generation = DRS->generation; + } + floppy_end_request(req, BLK_STS_IOERR); + } } /* Interrupt handler evaluating the result of the r/w operation */ static void rw_interrupt(void) { - int eoc; - int ssize; - int heads; - int nr_sectors; + int eoc; + int ssize; + int heads; + int nr_sectors; - if (R_HEAD >= 2) { - /* some Toshiba floppy controllers occasionnally seem to - * return bogus interrupts after read/write operations, which - * can be recognized by a bad head number (>= 2) */ - return; - } + if (R_HEAD >= 2) { + /* some Toshiba floppy controllers occasionnally seem to + * return bogus interrupts after read/write operations, which + * can be recognized by a bad head number (>= 2) */ + return; + } - if (!DRS->first_read_date) - DRS->first_read_date = jiffies; + if (!DRS->first_read_date) + DRS->first_read_date = jiffies; - nr_sectors = 0; - ssize = DIV_ROUND_UP(1 << SIZECODE, 4); + nr_sectors = 0; + ssize = DIV_ROUND_UP(1 << SIZECODE, 4); - if (ST1 & ST1_EOC) - eoc = 1; - else - eoc = 0; + if (ST1 & ST1_EOC) + eoc = 1; + else + eoc = 0; - if (COMMAND & 0x80) - heads = 2; - else - heads = 1; + if (COMMAND & 0x80) + heads = 2; + else + heads = 1; - nr_sectors = (((R_TRACK - TRACK) * heads + - R_HEAD - HEAD) * SECT_PER_TRACK + - R_SECTOR - SECTOR + eoc) << SIZECODE >> 2; + nr_sectors = (((R_TRACK - TRACK) * heads + + R_HEAD - HEAD) * SECT_PER_TRACK + + R_SECTOR - SECTOR + eoc) << SIZECODE >> 2; - if (nr_sectors / ssize > - DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) { - DPRINT("long rw: %x instead of %lx\n", - nr_sectors, current_count_sectors); - pr_info("rs=%d s=%d\n", R_SECTOR, SECTOR); - pr_info("rh=%d h=%d\n", R_HEAD, HEAD); - pr_info("rt=%d t=%d\n", R_TRACK, TRACK); - pr_info("heads=%d eoc=%d\n", heads, eoc); - pr_info("spt=%d st=%d ss=%d\n", - SECT_PER_TRACK, fsector_t, ssize); - pr_info("in_sector_offset=%d\n", in_sector_offset); - } + if (nr_sectors / ssize > + DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) { + DPRINT("long rw: %x instead of %lx\n", + nr_sectors, current_count_sectors); + pr_info("rs=%d s=%d\n", R_SECTOR, SECTOR); + pr_info("rh=%d h=%d\n", R_HEAD, HEAD); + pr_info("rt=%d t=%d\n", R_TRACK, TRACK); + pr_info("heads=%d eoc=%d\n", heads, eoc); + pr_info("spt=%d st=%d ss=%d\n", + SECT_PER_TRACK, fsector_t, ssize); + pr_info("in_sector_offset=%d\n", in_sector_offset); + } - nr_sectors -= in_sector_offset; - INFBOUND(nr_sectors, 0); - SUPBOUND(current_count_sectors, nr_sectors); + nr_sectors -= in_sector_offset; + INFBOUND(nr_sectors, 0); + SUPBOUND(current_count_sectors, nr_sectors); - switch (interpret_errors()) { - case 2: - cont->redo(); - return; - case 1: - if (!current_count_sectors) { - cont->error(); - cont->redo(); - return; - } - break; - case 0: - if (!current_count_sectors) { - cont->redo(); - return; - } - current_type[current_drive] = _floppy; - floppy_sizes[TOMINOR(current_drive)] = _floppy->size; - break; - } + switch (interpret_errors()) { + case 2: + cont->redo(); + return; + case 1: + if (!current_count_sectors) { + cont->error(); + cont->redo(); + return; + } + break; + case 0: + if (!current_count_sectors) { + cont->redo(); + return; + } + current_type[current_drive] = _floppy; + floppy_sizes[TOMINOR(current_drive)] = _floppy->size; + break; + } - if (probing) { - if (DP->flags & FTD_MSG) - DPRINT("Auto-detected floppy type %s in fd%d\n", - _floppy->name, current_drive); - current_type[current_drive] = _floppy; - floppy_sizes[TOMINOR(current_drive)] = _floppy->size; - probing = 0; - } + if (probing) { + if (DP->flags & FTD_MSG) + DPRINT("Auto-detected floppy type %s in fd%d\n", + _floppy->name, current_drive); + current_type[current_drive] = _floppy; + floppy_sizes[TOMINOR(current_drive)] = _floppy->size; + probing = 0; + } - if (CT(COMMAND) != FD_READ || - raw_cmd->kernel_data == bio_data(current_req->bio)) { - /* transfer directly from buffer */ - cont->done(1); - } else if (CT(COMMAND) == FD_READ) { - buffer_track = raw_cmd->track; - buffer_drive = current_drive; - INFBOUND(buffer_max, nr_sectors + fsector_t); - } - cont->redo(); + if (CT(COMMAND) != FD_READ || + raw_cmd->kernel_data == bio_data(current_req->bio)) { + /* transfer directly from buffer */ + cont->done(1); + } else if (CT(COMMAND) == FD_READ) { + buffer_track = raw_cmd->track; + buffer_drive = current_drive; + INFBOUND(buffer_max, nr_sectors + fsector_t); + } + cont->redo(); } /* Compute maximal contiguous buffer size. */ static int buffer_chain_size(void) { - struct bio_vec bv; - int size; - struct req_iterator iter; - char *base; + struct bio_vec bv; + int size; + struct req_iterator iter; + char *base; - base = bio_data(current_req->bio); - size = 0; + base = bio_data(current_req->bio); + size = 0; - rq_for_each_segment(bv, current_req, iter) { - if (page_address(bv.bv_page) + bv.bv_offset != base + size) - break; + rq_for_each_segment(bv, current_req, iter) { + if (page_address(bv.bv_page) + bv.bv_offset != base + size) + break; - size += bv.bv_len; - } + size += bv.bv_len; + } - return size >> 9; + return size >> 9; } /* Compute the maximal transfer size */ static int transfer_size(int ssize, int max_sector, int max_size) { - SUPBOUND(max_sector, fsector_t + max_size); + SUPBOUND(max_sector, fsector_t + max_size); - /* alignment */ - max_sector -= (max_sector % _floppy->sect) % ssize; + /* alignment */ + max_sector -= (max_sector % _floppy->sect) % ssize; - /* transfer size, beginning not aligned */ - current_count_sectors = max_sector - fsector_t; + /* transfer size, beginning not aligned */ + current_count_sectors = max_sector - fsector_t; - return max_sector; + return max_sector; } /* @@ -2401,80 +2400,80 @@ static int transfer_size(int ssize, int max_sector, int max_size) */ static void copy_buffer(int ssize, int max_sector, int max_sector_2) { - int remaining; /* number of transferred 512-byte sectors */ - struct bio_vec bv; - char *buffer; - char *dma_buffer; - int size; - struct req_iterator iter; + int remaining; /* number of transferred 512-byte sectors */ + struct bio_vec bv; + char *buffer; + char *dma_buffer; + int size; + struct req_iterator iter; - max_sector = transfer_size(ssize, - min(max_sector, max_sector_2), - blk_rq_sectors(current_req)); + max_sector = transfer_size(ssize, + min(max_sector, max_sector_2), + blk_rq_sectors(current_req)); - if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE && - buffer_max > fsector_t + blk_rq_sectors(current_req)) - current_count_sectors = min_t(int, buffer_max - fsector_t, - blk_rq_sectors(current_req)); + if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE && + buffer_max > fsector_t + blk_rq_sectors(current_req)) + current_count_sectors = min_t(int, buffer_max - fsector_t, + blk_rq_sectors(current_req)); - remaining = current_count_sectors << 9; - if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) { - DPRINT("in copy buffer\n"); - pr_info("current_count_sectors=%ld\n", current_count_sectors); - pr_info("remaining=%d\n", remaining >> 9); - pr_info("current_req->nr_sectors=%u\n", - blk_rq_sectors(current_req)); - pr_info("current_req->current_nr_sectors=%u\n", - blk_rq_cur_sectors(current_req)); - pr_info("max_sector=%d\n", max_sector); - pr_info("ssize=%d\n", ssize); - } + remaining = current_count_sectors << 9; + if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) { + DPRINT("in copy buffer\n"); + pr_info("current_count_sectors=%ld\n", current_count_sectors); + pr_info("remaining=%d\n", remaining >> 9); + pr_info("current_req->nr_sectors=%u\n", + blk_rq_sectors(current_req)); + pr_info("current_req->current_nr_sectors=%u\n", + blk_rq_cur_sectors(current_req)); + pr_info("max_sector=%d\n", max_sector); + pr_info("ssize=%d\n", ssize); + } - buffer_max = max(max_sector, buffer_max); + buffer_max = max(max_sector, buffer_max); - dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9); + dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9); - size = blk_rq_cur_bytes(current_req); + size = blk_rq_cur_bytes(current_req); - rq_for_each_segment(bv, current_req, iter) { - if (!remaining) - break; + rq_for_each_segment(bv, current_req, iter) { + if (!remaining) + break; - size = bv.bv_len; - SUPBOUND(size, remaining); + size = bv.bv_len; + SUPBOUND(size, remaining); - buffer = page_address(bv.bv_page) + bv.bv_offset; - if (dma_buffer + size > - floppy_track_buffer + (max_buffer_sectors << 10) || - dma_buffer < floppy_track_buffer) { - DPRINT("buffer overrun in copy buffer %d\n", - (int)((floppy_track_buffer - dma_buffer) >> 9)); - pr_info("fsector_t=%d buffer_min=%d\n", - fsector_t, buffer_min); - pr_info("current_count_sectors=%ld\n", - current_count_sectors); - if (CT(COMMAND) == FD_READ) - pr_info("read\n"); - if (CT(COMMAND) == FD_WRITE) - pr_info("write\n"); - break; - } - if (((unsigned long)buffer) % 512) - DPRINT("%p buffer not aligned\n", buffer); + buffer = page_address(bv.bv_page) + bv.bv_offset; + if (dma_buffer + size > + floppy_track_buffer + (max_buffer_sectors << 10) || + dma_buffer < floppy_track_buffer) { + DPRINT("buffer overrun in copy buffer %d\n", + (int)((floppy_track_buffer - dma_buffer) >> 9)); + pr_info("fsector_t=%d buffer_min=%d\n", + fsector_t, buffer_min); + pr_info("current_count_sectors=%ld\n", + current_count_sectors); + if (CT(COMMAND) == FD_READ) + pr_info("read\n"); + if (CT(COMMAND) == FD_WRITE) + pr_info("write\n"); + break; + } + if (((unsigned long)buffer) % 512) + DPRINT("%p buffer not aligned\n", buffer); - if (CT(COMMAND) == FD_READ) - memcpy(buffer, dma_buffer, size); - else - memcpy(dma_buffer, buffer, size); + if (CT(COMMAND) == FD_READ) + memcpy(buffer, dma_buffer, size); + else + memcpy(dma_buffer, buffer, size); - remaining -= size; - dma_buffer += size; - } - if (remaining) { - if (remaining > 0) - max_sector -= remaining >> 9; - DPRINT("weirdness: remaining %d\n", remaining >> 9); - } + remaining -= size; + dma_buffer += size; + } + if (remaining) { + if (remaining > 0) + max_sector -= remaining >> 9; + DPRINT("weirdness: remaining %d\n", remaining >> 9); + } } /* work around a bug in pseudo DMA @@ -2486,23 +2485,23 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) */ static void virtualdmabug_workaround(void) { - int hard_sectors; - int end_sector; + int hard_sectors; + int end_sector; - if (CT(COMMAND) == FD_WRITE) { - COMMAND &= ~0x80; /* switch off multiple track mode */ + if (CT(COMMAND) == FD_WRITE) { + COMMAND &= ~0x80; /* switch off multiple track mode */ - hard_sectors = raw_cmd->length >> (7 + SIZECODE); - end_sector = SECTOR + hard_sectors - 1; - if (end_sector > SECT_PER_TRACK) { - pr_info("too many sectors %d > %d\n", - end_sector, SECT_PER_TRACK); - return; - } - SECT_PER_TRACK = end_sector; - /* make sure SECT_PER_TRACK - * points to end of transfer */ - } + hard_sectors = raw_cmd->length >> (7 + SIZECODE); + end_sector = SECTOR + hard_sectors - 1; + if (end_sector > SECT_PER_TRACK) { + pr_info("too many sectors %d > %d\n", + end_sector, SECT_PER_TRACK); + return; + } + SECT_PER_TRACK = end_sector; + /* make sure SECT_PER_TRACK + * points to end of transfer */ + } } /* @@ -2517,423 +2516,423 @@ static void virtualdmabug_workaround(void) static int make_raw_rw_request(void) { - int aligned_sector_t; - int max_sector; - int max_size; - int tracksize; - int ssize; + int aligned_sector_t; + int max_sector; + int max_size; + int tracksize; + int ssize; - if (WARN(max_buffer_sectors == 0, "VFS: Block I/O scheduled on unopened device\n")) - return 0; + if (WARN(max_buffer_sectors == 0, "VFS: Block I/O scheduled on unopened device\n")) + return 0; - set_fdc((long)current_req->rq_disk->private_data); + set_fdc((long)current_req->rq_disk->private_data); - raw_cmd = &default_raw_cmd; - raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; - raw_cmd->cmd_count = NR_RW; - if (rq_data_dir(current_req) == READ) { - raw_cmd->flags |= FD_RAW_READ; - COMMAND = FM_MODE(_floppy, FD_READ); - } else if (rq_data_dir(current_req) == WRITE) { - raw_cmd->flags |= FD_RAW_WRITE; - COMMAND = FM_MODE(_floppy, FD_WRITE); - } else { - DPRINT("%s: unknown command\n", __func__); - return 0; - } + raw_cmd = &default_raw_cmd; + raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; + raw_cmd->cmd_count = NR_RW; + if (rq_data_dir(current_req) == READ) { + raw_cmd->flags |= FD_RAW_READ; + COMMAND = FM_MODE(_floppy, FD_READ); + } else if (rq_data_dir(current_req) == WRITE) { + raw_cmd->flags |= FD_RAW_WRITE; + COMMAND = FM_MODE(_floppy, FD_WRITE); + } else { + DPRINT("%s: unknown command\n", __func__); + return 0; + } - max_sector = _floppy->sect * _floppy->head; + max_sector = _floppy->sect * _floppy->head; - TRACK = (int)blk_rq_pos(current_req) / max_sector; - fsector_t = (int)blk_rq_pos(current_req) % max_sector; - if (_floppy->track && TRACK >= _floppy->track) { - if (blk_rq_cur_sectors(current_req) & 1) { - current_count_sectors = 1; - return 1; - } else - return 0; - } - HEAD = fsector_t / _floppy->sect; + TRACK = (int)blk_rq_pos(current_req) / max_sector; + fsector_t = (int)blk_rq_pos(current_req) % max_sector; + if (_floppy->track && TRACK >= _floppy->track) { + if (blk_rq_cur_sectors(current_req) & 1) { + current_count_sectors = 1; + return 1; + } else + return 0; + } + HEAD = fsector_t / _floppy->sect; - if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) || - test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) && - fsector_t < _floppy->sect) - max_sector = _floppy->sect; + if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) || + test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) && + fsector_t < _floppy->sect) + max_sector = _floppy->sect; - /* 2M disks have phantom sectors on the first track */ - if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)) { - max_sector = 2 * _floppy->sect / 3; - if (fsector_t >= max_sector) { - current_count_sectors = - min_t(int, _floppy->sect - fsector_t, - blk_rq_sectors(current_req)); - return 1; - } - SIZECODE = 2; - } else - SIZECODE = FD_SIZECODE(_floppy); - raw_cmd->rate = _floppy->rate & 0x43; - if ((_floppy->rate & FD_2M) && (TRACK || HEAD) && raw_cmd->rate == 2) - raw_cmd->rate = 1; + /* 2M disks have phantom sectors on the first track */ + if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)) { + max_sector = 2 * _floppy->sect / 3; + if (fsector_t >= max_sector) { + current_count_sectors = + min_t(int, _floppy->sect - fsector_t, + blk_rq_sectors(current_req)); + return 1; + } + SIZECODE = 2; + } else + SIZECODE = FD_SIZECODE(_floppy); + raw_cmd->rate = _floppy->rate & 0x43; + if ((_floppy->rate & FD_2M) && (TRACK || HEAD) && raw_cmd->rate == 2) + raw_cmd->rate = 1; - if (SIZECODE) - SIZECODE2 = 0xff; - else - SIZECODE2 = 0x80; - raw_cmd->track = TRACK << STRETCH(_floppy); - DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD); - GAP = _floppy->gap; - ssize = DIV_ROUND_UP(1 << SIZECODE, 4); - SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; - SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + - FD_SECTBASE(_floppy); + if (SIZECODE) + SIZECODE2 = 0xff; + else + SIZECODE2 = 0x80; + raw_cmd->track = TRACK << STRETCH(_floppy); + DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD); + GAP = _floppy->gap; + ssize = DIV_ROUND_UP(1 << SIZECODE, 4); + SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; + SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + + FD_SECTBASE(_floppy); - /* tracksize describes the size which can be filled up with sectors - * of size ssize. - */ - tracksize = _floppy->sect - _floppy->sect % ssize; - if (tracksize < _floppy->sect) { - SECT_PER_TRACK++; - if (tracksize <= fsector_t % _floppy->sect) - SECTOR--; + /* tracksize describes the size which can be filled up with sectors + * of size ssize. + */ + tracksize = _floppy->sect - _floppy->sect % ssize; + if (tracksize < _floppy->sect) { + SECT_PER_TRACK++; + if (tracksize <= fsector_t % _floppy->sect) + SECTOR--; - /* if we are beyond tracksize, fill up using smaller sectors */ - while (tracksize <= fsector_t % _floppy->sect) { - while (tracksize + ssize > _floppy->sect) { - SIZECODE--; - ssize >>= 1; - } - SECTOR++; - SECT_PER_TRACK++; - tracksize += ssize; - } - max_sector = HEAD * _floppy->sect + tracksize; - } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) { - max_sector = _floppy->sect; - } else if (!HEAD && CT(COMMAND) == FD_WRITE) { - /* for virtual DMA bug workaround */ - max_sector = _floppy->sect; - } + /* if we are beyond tracksize, fill up using smaller sectors */ + while (tracksize <= fsector_t % _floppy->sect) { + while (tracksize + ssize > _floppy->sect) { + SIZECODE--; + ssize >>= 1; + } + SECTOR++; + SECT_PER_TRACK++; + tracksize += ssize; + } + max_sector = HEAD * _floppy->sect + tracksize; + } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) { + max_sector = _floppy->sect; + } else if (!HEAD && CT(COMMAND) == FD_WRITE) { + /* for virtual DMA bug workaround */ + max_sector = _floppy->sect; + } - in_sector_offset = (fsector_t % _floppy->sect) % ssize; - aligned_sector_t = fsector_t - in_sector_offset; - max_size = blk_rq_sectors(current_req); - if ((raw_cmd->track == buffer_track) && - (current_drive == buffer_drive) && - (fsector_t >= buffer_min) && (fsector_t < buffer_max)) { - /* data already in track buffer */ - if (CT(COMMAND) == FD_READ) { - copy_buffer(1, max_sector, buffer_max); - return 1; - } - } else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) { - if (CT(COMMAND) == FD_WRITE) { - unsigned int sectors; + in_sector_offset = (fsector_t % _floppy->sect) % ssize; + aligned_sector_t = fsector_t - in_sector_offset; + max_size = blk_rq_sectors(current_req); + if ((raw_cmd->track == buffer_track) && + (current_drive == buffer_drive) && + (fsector_t >= buffer_min) && (fsector_t < buffer_max)) { + /* data already in track buffer */ + if (CT(COMMAND) == FD_READ) { + copy_buffer(1, max_sector, buffer_max); + return 1; + } + } else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) { + if (CT(COMMAND) == FD_WRITE) { + unsigned int sectors; - sectors = fsector_t + blk_rq_sectors(current_req); - if (sectors > ssize && sectors < ssize + ssize) - max_size = ssize + ssize; - else - max_size = ssize; - } - raw_cmd->flags &= ~FD_RAW_WRITE; - raw_cmd->flags |= FD_RAW_READ; - COMMAND = FM_MODE(_floppy, FD_READ); - } else if ((unsigned long)bio_data(current_req->bio) < MAX_DMA_ADDRESS) { - unsigned long dma_limit; - int direct, indirect; + sectors = fsector_t + blk_rq_sectors(current_req); + if (sectors > ssize && sectors < ssize + ssize) + max_size = ssize + ssize; + else + max_size = ssize; + } + raw_cmd->flags &= ~FD_RAW_WRITE; + raw_cmd->flags |= FD_RAW_READ; + COMMAND = FM_MODE(_floppy, FD_READ); + } else if ((unsigned long)bio_data(current_req->bio) < MAX_DMA_ADDRESS) { + unsigned long dma_limit; + int direct, indirect; - indirect = - transfer_size(ssize, max_sector, - max_buffer_sectors * 2) - fsector_t; + indirect = + transfer_size(ssize, max_sector, + max_buffer_sectors * 2) - fsector_t; - /* - * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide - * on a 64 bit machine! - */ - max_size = buffer_chain_size(); - dma_limit = (MAX_DMA_ADDRESS - - ((unsigned long)bio_data(current_req->bio))) >> 9; - if ((unsigned long)max_size > dma_limit) - max_size = dma_limit; - /* 64 kb boundaries */ - if (CROSS_64KB(bio_data(current_req->bio), max_size << 9)) - max_size = (K_64 - - ((unsigned long)bio_data(current_req->bio)) % - K_64) >> 9; - direct = transfer_size(ssize, max_sector, max_size) - fsector_t; - /* - * We try to read tracks, but if we get too many errors, we - * go back to reading just one sector at a time. - * - * This means we should be able to read a sector even if there - * are other bad sectors on this track. - */ - if (!direct || - (indirect * 2 > direct * 3 && - *errors < DP->max_errors.read_track && - ((!probing || - (DP->read_track & (1 << DRS->probed_format)))))) { - max_size = blk_rq_sectors(current_req); - } else { - raw_cmd->kernel_data = bio_data(current_req->bio); - raw_cmd->length = current_count_sectors << 9; - if (raw_cmd->length == 0) { - DPRINT("%s: zero dma transfer attempted\n", __func__); - DPRINT("indirect=%d direct=%d fsector_t=%d\n", - indirect, direct, fsector_t); - return 0; - } - virtualdmabug_workaround(); - return 2; - } - } + /* + * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide + * on a 64 bit machine! + */ + max_size = buffer_chain_size(); + dma_limit = (MAX_DMA_ADDRESS - + ((unsigned long)bio_data(current_req->bio))) >> 9; + if ((unsigned long)max_size > dma_limit) + max_size = dma_limit; + /* 64 kb boundaries */ + if (CROSS_64KB(bio_data(current_req->bio), max_size << 9)) + max_size = (K_64 - + ((unsigned long)bio_data(current_req->bio)) % + K_64) >> 9; + direct = transfer_size(ssize, max_sector, max_size) - fsector_t; + /* + * We try to read tracks, but if we get too many errors, we + * go back to reading just one sector at a time. + * + * This means we should be able to read a sector even if there + * are other bad sectors on this track. + */ + if (!direct || + (indirect * 2 > direct * 3 && + *errors < DP->max_errors.read_track && + ((!probing || + (DP->read_track & (1 << DRS->probed_format)))))) { + max_size = blk_rq_sectors(current_req); + } else { + raw_cmd->kernel_data = bio_data(current_req->bio); + raw_cmd->length = current_count_sectors << 9; + if (raw_cmd->length == 0) { + DPRINT("%s: zero dma transfer attempted\n", __func__); + DPRINT("indirect=%d direct=%d fsector_t=%d\n", + indirect, direct, fsector_t); + return 0; + } + virtualdmabug_workaround(); + return 2; + } + } - if (CT(COMMAND) == FD_READ) - max_size = max_sector; /* unbounded */ + if (CT(COMMAND) == FD_READ) + max_size = max_sector; /* unbounded */ - /* claim buffer track if needed */ - if (buffer_track != raw_cmd->track || /* bad track */ - buffer_drive != current_drive || /* bad drive */ - fsector_t > buffer_max || - fsector_t < buffer_min || - ((CT(COMMAND) == FD_READ || - (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) && - max_sector > 2 * max_buffer_sectors + buffer_min && - max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)) { - /* not enough space */ - buffer_track = -1; - buffer_drive = current_drive; - buffer_max = buffer_min = aligned_sector_t; - } - raw_cmd->kernel_data = floppy_track_buffer + - ((aligned_sector_t - buffer_min) << 9); + /* claim buffer track if needed */ + if (buffer_track != raw_cmd->track || /* bad track */ + buffer_drive != current_drive || /* bad drive */ + fsector_t > buffer_max || + fsector_t < buffer_min || + ((CT(COMMAND) == FD_READ || + (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) && + max_sector > 2 * max_buffer_sectors + buffer_min && + max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)) { + /* not enough space */ + buffer_track = -1; + buffer_drive = current_drive; + buffer_max = buffer_min = aligned_sector_t; + } + raw_cmd->kernel_data = floppy_track_buffer + + ((aligned_sector_t - buffer_min) << 9); - if (CT(COMMAND) == FD_WRITE) { - /* copy write buffer to track buffer. - * if we get here, we know that the write - * is either aligned or the data already in the buffer - * (buffer will be overwritten) */ - if (in_sector_offset && buffer_track == -1) - DPRINT("internal error offset !=0 on write\n"); - buffer_track = raw_cmd->track; - buffer_drive = current_drive; - copy_buffer(ssize, max_sector, - 2 * max_buffer_sectors + buffer_min); - } else - transfer_size(ssize, max_sector, - 2 * max_buffer_sectors + buffer_min - - aligned_sector_t); + if (CT(COMMAND) == FD_WRITE) { + /* copy write buffer to track buffer. + * if we get here, we know that the write + * is either aligned or the data already in the buffer + * (buffer will be overwritten) */ + if (in_sector_offset && buffer_track == -1) + DPRINT("internal error offset !=0 on write\n"); + buffer_track = raw_cmd->track; + buffer_drive = current_drive; + copy_buffer(ssize, max_sector, + 2 * max_buffer_sectors + buffer_min); + } else + transfer_size(ssize, max_sector, + 2 * max_buffer_sectors + buffer_min - + aligned_sector_t); - /* round up current_count_sectors to get dma xfer size */ - raw_cmd->length = in_sector_offset + current_count_sectors; - raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1; - raw_cmd->length <<= 9; - if ((raw_cmd->length < current_count_sectors << 9) || - (raw_cmd->kernel_data != bio_data(current_req->bio) && - CT(COMMAND) == FD_WRITE && - (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max || - aligned_sector_t < buffer_min)) || - raw_cmd->length % (128 << SIZECODE) || - raw_cmd->length <= 0 || current_count_sectors <= 0) { - DPRINT("fractionary current count b=%lx s=%lx\n", - raw_cmd->length, current_count_sectors); - if (raw_cmd->kernel_data != bio_data(current_req->bio)) - pr_info("addr=%d, length=%ld\n", - (int)((raw_cmd->kernel_data - - floppy_track_buffer) >> 9), - current_count_sectors); - pr_info("st=%d ast=%d mse=%d msi=%d\n", - fsector_t, aligned_sector_t, max_sector, max_size); - pr_info("ssize=%x SIZECODE=%d\n", ssize, SIZECODE); - pr_info("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n", - COMMAND, SECTOR, HEAD, TRACK); - pr_info("buffer drive=%d\n", buffer_drive); - pr_info("buffer track=%d\n", buffer_track); - pr_info("buffer_min=%d\n", buffer_min); - pr_info("buffer_max=%d\n", buffer_max); - return 0; - } + /* round up current_count_sectors to get dma xfer size */ + raw_cmd->length = in_sector_offset + current_count_sectors; + raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1; + raw_cmd->length <<= 9; + if ((raw_cmd->length < current_count_sectors << 9) || + (raw_cmd->kernel_data != bio_data(current_req->bio) && + CT(COMMAND) == FD_WRITE && + (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max || + aligned_sector_t < buffer_min)) || + raw_cmd->length % (128 << SIZECODE) || + raw_cmd->length <= 0 || current_count_sectors <= 0) { + DPRINT("fractionary current count b=%lx s=%lx\n", + raw_cmd->length, current_count_sectors); + if (raw_cmd->kernel_data != bio_data(current_req->bio)) + pr_info("addr=%d, length=%ld\n", + (int)((raw_cmd->kernel_data - + floppy_track_buffer) >> 9), + current_count_sectors); + pr_info("st=%d ast=%d mse=%d msi=%d\n", + fsector_t, aligned_sector_t, max_sector, max_size); + pr_info("ssize=%x SIZECODE=%d\n", ssize, SIZECODE); + pr_info("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n", + COMMAND, SECTOR, HEAD, TRACK); + pr_info("buffer drive=%d\n", buffer_drive); + pr_info("buffer track=%d\n", buffer_track); + pr_info("buffer_min=%d\n", buffer_min); + pr_info("buffer_max=%d\n", buffer_max); + return 0; + } - if (raw_cmd->kernel_data != bio_data(current_req->bio)) { - if (raw_cmd->kernel_data < floppy_track_buffer || - current_count_sectors < 0 || - raw_cmd->length < 0 || - raw_cmd->kernel_data + raw_cmd->length > - floppy_track_buffer + (max_buffer_sectors << 10)) { - DPRINT("buffer overrun in schedule dma\n"); - pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n", - fsector_t, buffer_min, raw_cmd->length >> 9); - pr_info("current_count_sectors=%ld\n", - current_count_sectors); - if (CT(COMMAND) == FD_READ) - pr_info("read\n"); - if (CT(COMMAND) == FD_WRITE) - pr_info("write\n"); - return 0; - } - } else if (raw_cmd->length > blk_rq_bytes(current_req) || - current_count_sectors > blk_rq_sectors(current_req)) { - DPRINT("buffer overrun in direct transfer\n"); - return 0; - } else if (raw_cmd->length < current_count_sectors << 9) { - DPRINT("more sectors than bytes\n"); - pr_info("bytes=%ld\n", raw_cmd->length >> 9); - pr_info("sectors=%ld\n", current_count_sectors); - } - if (raw_cmd->length == 0) { - DPRINT("zero dma transfer attempted from make_raw_request\n"); - return 0; - } + if (raw_cmd->kernel_data != bio_data(current_req->bio)) { + if (raw_cmd->kernel_data < floppy_track_buffer || + current_count_sectors < 0 || + raw_cmd->length < 0 || + raw_cmd->kernel_data + raw_cmd->length > + floppy_track_buffer + (max_buffer_sectors << 10)) { + DPRINT("buffer overrun in schedule dma\n"); + pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n", + fsector_t, buffer_min, raw_cmd->length >> 9); + pr_info("current_count_sectors=%ld\n", + current_count_sectors); + if (CT(COMMAND) == FD_READ) + pr_info("read\n"); + if (CT(COMMAND) == FD_WRITE) + pr_info("write\n"); + return 0; + } + } else if (raw_cmd->length > blk_rq_bytes(current_req) || + current_count_sectors > blk_rq_sectors(current_req)) { + DPRINT("buffer overrun in direct transfer\n"); + return 0; + } else if (raw_cmd->length < current_count_sectors << 9) { + DPRINT("more sectors than bytes\n"); + pr_info("bytes=%ld\n", raw_cmd->length >> 9); + pr_info("sectors=%ld\n", current_count_sectors); + } + if (raw_cmd->length == 0) { + DPRINT("zero dma transfer attempted from make_raw_request\n"); + return 0; + } - virtualdmabug_workaround(); - return 2; + virtualdmabug_workaround(); + return 2; } static int set_next_request(void) { - current_req = list_first_entry_or_null(&floppy_reqs, struct request, - queuelist); - if (current_req) { - current_req->error_count = 0; - list_del_init(¤t_req->queuelist); - } - return current_req != NULL; + current_req = list_first_entry_or_null(&floppy_reqs, struct request, + queuelist); + if (current_req) { + current_req->error_count = 0; + list_del_init(¤t_req->queuelist); + } + return current_req != NULL; } static void redo_fd_request(void) { - int drive; - int tmp; + int drive; + int tmp; - lastredo = jiffies; - if (current_drive < N_DRIVE) - floppy_off(current_drive); + lastredo = jiffies; + if (current_drive < N_DRIVE) + floppy_off(current_drive); do_request: - if (!current_req) { - int pending; + if (!current_req) { + int pending; - spin_lock_irq(&floppy_lock); - pending = set_next_request(); - spin_unlock_irq(&floppy_lock); - if (!pending) { - do_floppy = NULL; - unlock_fdc(); - return; - } - } - drive = (long)current_req->rq_disk->private_data; - set_fdc(drive); - reschedule_timeout(current_reqD, "redo fd request"); + spin_lock_irq(&floppy_lock); + pending = set_next_request(); + spin_unlock_irq(&floppy_lock); + if (!pending) { + do_floppy = NULL; + unlock_fdc(); + return; + } + } + drive = (long)current_req->rq_disk->private_data; + set_fdc(drive); + reschedule_timeout(current_reqD, "redo fd request"); - set_floppy(drive); - raw_cmd = &default_raw_cmd; - raw_cmd->flags = 0; - if (start_motor(redo_fd_request)) - return; + set_floppy(drive); + raw_cmd = &default_raw_cmd; + raw_cmd->flags = 0; + if (start_motor(redo_fd_request)) + return; - disk_change(current_drive); - if (test_bit(current_drive, &fake_change) || - test_bit(FD_DISK_CHANGED_BIT, &DRS->flags)) { - DPRINT("disk absent or changed during operation\n"); - request_done(0); - goto do_request; - } - if (!_floppy) { /* Autodetection */ - if (!probing) { - DRS->probed_format = 0; - if (next_valid_format()) { - DPRINT("no autodetectable formats\n"); - _floppy = NULL; - request_done(0); - goto do_request; - } - } - probing = 1; - _floppy = floppy_type + DP->autodetect[DRS->probed_format]; - } else - probing = 0; - errors = &(current_req->error_count); - tmp = make_raw_rw_request(); - if (tmp < 2) { - request_done(tmp); - goto do_request; - } + disk_change(current_drive); + if (test_bit(current_drive, &fake_change) || + test_bit(FD_DISK_CHANGED_BIT, &DRS->flags)) { + DPRINT("disk absent or changed during operation\n"); + request_done(0); + goto do_request; + } + if (!_floppy) { /* Autodetection */ + if (!probing) { + DRS->probed_format = 0; + if (next_valid_format()) { + DPRINT("no autodetectable formats\n"); + _floppy = NULL; + request_done(0); + goto do_request; + } + } + probing = 1; + _floppy = floppy_type + DP->autodetect[DRS->probed_format]; + } else + probing = 0; + errors = &(current_req->error_count); + tmp = make_raw_rw_request(); + if (tmp < 2) { + request_done(tmp); + goto do_request; + } - if (test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) - twaddle(); - schedule_bh(floppy_start); - debugt(__func__, "queue fd request"); - return; + if (test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) + twaddle(); + schedule_bh(floppy_start); + debugt(__func__, "queue fd request"); + return; } static const struct cont_t rw_cont = { - .interrupt = rw_interrupt, - .redo = redo_fd_request, - .error = bad_flp_intr, - .done = request_done + .interrupt = rw_interrupt, + .redo = redo_fd_request, + .error = bad_flp_intr, + .done = request_done }; static void process_fd_request(void) { - cont = &rw_cont; - schedule_bh(redo_fd_request); + cont = &rw_cont; + schedule_bh(redo_fd_request); } static blk_status_t floppy_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd) + const struct blk_mq_queue_data *bd) { - blk_mq_start_request(bd->rq); + blk_mq_start_request(bd->rq); - if (WARN(max_buffer_sectors == 0, - "VFS: %s called on non-open device\n", __func__)) - return BLK_STS_IOERR; + if (WARN(max_buffer_sectors == 0, + "VFS: %s called on non-open device\n", __func__)) + return BLK_STS_IOERR; - if (WARN(atomic_read(&usage_count) == 0, - "warning: usage count=0, current_req=%p sect=%ld flags=%llx\n", - current_req, (long)blk_rq_pos(current_req), - (unsigned long long) current_req->cmd_flags)) - return BLK_STS_IOERR; + if (WARN(atomic_read(&usage_count) == 0, + "warning: usage count=0, current_req=%p sect=%ld flags=%llx\n", + current_req, (long)blk_rq_pos(current_req), + (unsigned long long) current_req->cmd_flags)) + return BLK_STS_IOERR; - spin_lock_irq(&floppy_lock); - list_add_tail(&bd->rq->queuelist, &floppy_reqs); - spin_unlock_irq(&floppy_lock); + spin_lock_irq(&floppy_lock); + list_add_tail(&bd->rq->queuelist, &floppy_reqs); + spin_unlock_irq(&floppy_lock); - if (test_and_set_bit(0, &fdc_busy)) { - /* fdc busy, this new request will be treated when the - current one is done */ - is_alive(__func__, "old request running"); - return BLK_STS_OK; - } + if (test_and_set_bit(0, &fdc_busy)) { + /* fdc busy, this new request will be treated when the + current one is done */ + is_alive(__func__, "old request running"); + return BLK_STS_OK; + } - command_status = FD_COMMAND_NONE; - __reschedule_timeout(MAXTIMEOUT, "fd_request"); - set_fdc(0); - process_fd_request(); - is_alive(__func__, ""); - return BLK_STS_OK; + command_status = FD_COMMAND_NONE; + __reschedule_timeout(MAXTIMEOUT, "fd_request"); + set_fdc(0); + process_fd_request(); + is_alive(__func__, ""); + return BLK_STS_OK; } static const struct cont_t poll_cont = { - .interrupt = success_and_wakeup, - .redo = floppy_ready, - .error = generic_failure, - .done = generic_done + .interrupt = success_and_wakeup, + .redo = floppy_ready, + .error = generic_failure, + .done = generic_done }; static int poll_drive(bool interruptible, int flag) { - /* no auto-sense, just clear dcl */ - raw_cmd = &default_raw_cmd; - raw_cmd->flags = flag; - raw_cmd->track = 0; - raw_cmd->cmd_count = 0; - cont = &poll_cont; - debug_dcl(DP->flags, "setting NEWCHANGE in poll_drive\n"); - set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); + /* no auto-sense, just clear dcl */ + raw_cmd = &default_raw_cmd; + raw_cmd->flags = flag; + raw_cmd->track = 0; + raw_cmd->cmd_count = 0; + cont = &poll_cont; + debug_dcl(DP->flags, "setting NEWCHANGE in poll_drive\n"); + set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); - return wait_til_done(floppy_ready, interruptible); + return wait_til_done(floppy_ready, interruptible); } /* @@ -2943,33 +2942,33 @@ static int poll_drive(bool interruptible, int flag) static void reset_intr(void) { - pr_info("weird, reset interrupt called\n"); + pr_info("weird, reset interrupt called\n"); } static const struct cont_t reset_cont = { - .interrupt = reset_intr, - .redo = success_and_wakeup, - .error = generic_failure, - .done = generic_done + .interrupt = reset_intr, + .redo = success_and_wakeup, + .error = generic_failure, + .done = generic_done }; static int user_reset_fdc(int drive, int arg, bool interruptible) { - int ret; + int ret; - if (lock_fdc(drive)) - return -EINTR; + if (lock_fdc(drive)) + return -EINTR; - if (arg == FD_RESET_ALWAYS) - FDCS->reset = 1; - if (FDCS->reset) { - cont = &reset_cont; - ret = wait_til_done(reset_fdc, interruptible); - if (ret == -EINTR) - return -EINTR; - } - process_fd_request(); - return 0; + if (arg == FD_RESET_ALWAYS) + FDCS->reset = 1; + if (FDCS->reset) { + cont = &reset_cont; + ret = wait_til_done(reset_fdc, interruptible); + if (ret == -EINTR) + return -EINTR; + } + process_fd_request(); + return 0; } /* @@ -2977,660 +2976,660 @@ static int user_reset_fdc(int drive, int arg, bool interruptible) * ======================== */ static inline int fd_copyout(void __user *param, const void *address, - unsigned long size) + unsigned long size) { - return copy_to_user(param, address, size) ? -EFAULT : 0; + return copy_to_user(param, address, size) ? -EFAULT : 0; } static inline int fd_copyin(void __user *param, void *address, - unsigned long size) + unsigned long size) { - return copy_from_user(address, param, size) ? -EFAULT : 0; + return copy_from_user(address, param, size) ? -EFAULT : 0; } static const char *drive_name(int type, int drive) { - struct floppy_struct *floppy; + struct floppy_struct *floppy; - if (type) - floppy = floppy_type + type; - else { - if (UDP->native_format) - floppy = floppy_type + UDP->native_format; - else - return "(null)"; - } - if (floppy->name) - return floppy->name; - else - return "(null)"; + if (type) + floppy = floppy_type + type; + else { + if (UDP->native_format) + floppy = floppy_type + UDP->native_format; + else + return "(null)"; + } + if (floppy->name) + return floppy->name; + else + return "(null)"; } /* raw commands */ static void raw_cmd_done(int flag) { - int i; + int i; - if (!flag) { - raw_cmd->flags |= FD_RAW_FAILURE; - raw_cmd->flags |= FD_RAW_HARDFAILURE; - } else { - raw_cmd->reply_count = inr; - if (raw_cmd->reply_count > MAX_REPLIES) - raw_cmd->reply_count = 0; - for (i = 0; i < raw_cmd->reply_count; i++) - raw_cmd->reply[i] = reply_buffer[i]; + if (!flag) { + raw_cmd->flags |= FD_RAW_FAILURE; + raw_cmd->flags |= FD_RAW_HARDFAILURE; + } else { + raw_cmd->reply_count = inr; + if (raw_cmd->reply_count > MAX_REPLIES) + raw_cmd->reply_count = 0; + for (i = 0; i < raw_cmd->reply_count; i++) + raw_cmd->reply[i] = reply_buffer[i]; - if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) { - unsigned long flags; - flags = claim_dma_lock(); - raw_cmd->length = fd_get_dma_residue(); - release_dma_lock(flags); - } + if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) { + unsigned long flags; + flags = claim_dma_lock(); + raw_cmd->length = fd_get_dma_residue(); + release_dma_lock(flags); + } - if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) && - (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0))) - raw_cmd->flags |= FD_RAW_FAILURE; + if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) && + (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0))) + raw_cmd->flags |= FD_RAW_FAILURE; - if (disk_change(current_drive)) - raw_cmd->flags |= FD_RAW_DISK_CHANGE; - else - raw_cmd->flags &= ~FD_RAW_DISK_CHANGE; - if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER) - motor_off_callback(&motor_off_timer[current_drive]); + if (disk_change(current_drive)) + raw_cmd->flags |= FD_RAW_DISK_CHANGE; + else + raw_cmd->flags &= ~FD_RAW_DISK_CHANGE; + if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER) + motor_off_callback(&motor_off_timer[current_drive]); - if (raw_cmd->next && - (!(raw_cmd->flags & FD_RAW_FAILURE) || - !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) && - ((raw_cmd->flags & FD_RAW_FAILURE) || - !(raw_cmd->flags & FD_RAW_STOP_IF_SUCCESS))) { - raw_cmd = raw_cmd->next; - return; - } - } - generic_done(flag); + if (raw_cmd->next && + (!(raw_cmd->flags & FD_RAW_FAILURE) || + !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) && + ((raw_cmd->flags & FD_RAW_FAILURE) || + !(raw_cmd->flags & FD_RAW_STOP_IF_SUCCESS))) { + raw_cmd = raw_cmd->next; + return; + } + } + generic_done(flag); } static const struct cont_t raw_cmd_cont = { - .interrupt = success_and_wakeup, - .redo = floppy_start, - .error = generic_failure, - .done = raw_cmd_done + .interrupt = success_and_wakeup, + .redo = floppy_start, + .error = generic_failure, + .done = raw_cmd_done }; static int raw_cmd_copyout(int cmd, void __user *param, - struct floppy_raw_cmd *ptr) + struct floppy_raw_cmd *ptr) { - int ret; + int ret; - while (ptr) { - struct floppy_raw_cmd cmd = *ptr; - cmd.next = NULL; - cmd.kernel_data = NULL; - ret = copy_to_user(param, &cmd, sizeof(cmd)); - if (ret) - return -EFAULT; - param += sizeof(struct floppy_raw_cmd); - if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) { - if (ptr->length >= 0 && - ptr->length <= ptr->buffer_length) { - long length = ptr->buffer_length - ptr->length; - ret = fd_copyout(ptr->data, ptr->kernel_data, - length); - if (ret) - return ret; - } - } - ptr = ptr->next; - } + while (ptr) { + struct floppy_raw_cmd cmd = *ptr; + cmd.next = NULL; + cmd.kernel_data = NULL; + ret = copy_to_user(param, &cmd, sizeof(cmd)); + if (ret) + return -EFAULT; + param += sizeof(struct floppy_raw_cmd); + if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) { + if (ptr->length >= 0 && + ptr->length <= ptr->buffer_length) { + long length = ptr->buffer_length - ptr->length; + ret = fd_copyout(ptr->data, ptr->kernel_data, + length); + if (ret) + return ret; + } + } + ptr = ptr->next; + } - return 0; + return 0; } static void raw_cmd_free(struct floppy_raw_cmd **ptr) { - struct floppy_raw_cmd *next; - struct floppy_raw_cmd *this; + struct floppy_raw_cmd *next; + struct floppy_raw_cmd *this; - this = *ptr; - *ptr = NULL; - while (this) { - if (this->buffer_length) { - fd_dma_mem_free((unsigned long)this->kernel_data, - this->buffer_length); - this->buffer_length = 0; - } - next = this->next; - kfree(this); - this = next; - } + this = *ptr; + *ptr = NULL; + while (this) { + if (this->buffer_length) { + fd_dma_mem_free((unsigned long)this->kernel_data, + this->buffer_length); + this->buffer_length = 0; + } + next = this->next; + kfree(this); + this = next; + } } static int raw_cmd_copyin(int cmd, void __user *param, - struct floppy_raw_cmd **rcmd) + struct floppy_raw_cmd **rcmd) { - struct floppy_raw_cmd *ptr; - int ret; - int i; + struct floppy_raw_cmd *ptr; + int ret; + int i; - *rcmd = NULL; + *rcmd = NULL; loop: - ptr = kmalloc(sizeof(struct floppy_raw_cmd), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - *rcmd = ptr; - ret = copy_from_user(ptr, param, sizeof(*ptr)); - ptr->next = NULL; - ptr->buffer_length = 0; - ptr->kernel_data = NULL; - if (ret) - return -EFAULT; - param += sizeof(struct floppy_raw_cmd); - if (ptr->cmd_count > 33) - /* the command may now also take up the space - * initially intended for the reply & the - * reply count. Needed for long 82078 commands - * such as RESTORE, which takes ... 17 command - * bytes. Murphy's law #137: When you reserve - * 16 bytes for a structure, you'll one day - * discover that you really need 17... - */ - return -EINVAL; + ptr = kmalloc(sizeof(struct floppy_raw_cmd), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + *rcmd = ptr; + ret = copy_from_user(ptr, param, sizeof(*ptr)); + ptr->next = NULL; + ptr->buffer_length = 0; + ptr->kernel_data = NULL; + if (ret) + return -EFAULT; + param += sizeof(struct floppy_raw_cmd); + if (ptr->cmd_count > 33) + /* the command may now also take up the space + * initially intended for the reply & the + * reply count. Needed for long 82078 commands + * such as RESTORE, which takes ... 17 command + * bytes. Murphy's law #137: When you reserve + * 16 bytes for a structure, you'll one day + * discover that you really need 17... + */ + return -EINVAL; - for (i = 0; i < 16; i++) - ptr->reply[i] = 0; - ptr->resultcode = 0; + for (i = 0; i < 16; i++) + ptr->reply[i] = 0; + ptr->resultcode = 0; - if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { - if (ptr->length <= 0) - return -EINVAL; - ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length); - fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); - if (!ptr->kernel_data) - return -ENOMEM; - ptr->buffer_length = ptr->length; - } - if (ptr->flags & FD_RAW_WRITE) { - ret = fd_copyin(ptr->data, ptr->kernel_data, ptr->length); - if (ret) - return ret; - } + if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { + if (ptr->length <= 0) + return -EINVAL; + ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length); + fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); + if (!ptr->kernel_data) + return -ENOMEM; + ptr->buffer_length = ptr->length; + } + if (ptr->flags & FD_RAW_WRITE) { + ret = fd_copyin(ptr->data, ptr->kernel_data, ptr->length); + if (ret) + return ret; + } - if (ptr->flags & FD_RAW_MORE) { - rcmd = &(ptr->next); - ptr->rate &= 0x43; - goto loop; - } + if (ptr->flags & FD_RAW_MORE) { + rcmd = &(ptr->next); + ptr->rate &= 0x43; + goto loop; + } - return 0; + return 0; } static int raw_cmd_ioctl(int cmd, void __user *param) { - struct floppy_raw_cmd *my_raw_cmd; - int drive; - int ret2; - int ret; + struct floppy_raw_cmd *my_raw_cmd; + int drive; + int ret2; + int ret; - if (FDCS->rawcmd <= 1) - FDCS->rawcmd = 1; - for (drive = 0; drive < N_DRIVE; drive++) { - if (FDC(drive) != fdc) - continue; - if (drive == current_drive) { - if (UDRS->fd_ref > 1) { - FDCS->rawcmd = 2; - break; - } - } else if (UDRS->fd_ref) { - FDCS->rawcmd = 2; - break; - } - } + if (FDCS->rawcmd <= 1) + FDCS->rawcmd = 1; + for (drive = 0; drive < N_DRIVE; drive++) { + if (FDC(drive) != fdc) + continue; + if (drive == current_drive) { + if (UDRS->fd_ref > 1) { + FDCS->rawcmd = 2; + break; + } + } else if (UDRS->fd_ref) { + FDCS->rawcmd = 2; + break; + } + } - if (FDCS->reset) - return -EIO; + if (FDCS->reset) + return -EIO; - ret = raw_cmd_copyin(cmd, param, &my_raw_cmd); - if (ret) { - raw_cmd_free(&my_raw_cmd); - return ret; - } + ret = raw_cmd_copyin(cmd, param, &my_raw_cmd); + if (ret) { + raw_cmd_free(&my_raw_cmd); + return ret; + } - raw_cmd = my_raw_cmd; - cont = &raw_cmd_cont; - ret = wait_til_done(floppy_start, true); - debug_dcl(DP->flags, "calling disk change from raw_cmd ioctl\n"); + raw_cmd = my_raw_cmd; + cont = &raw_cmd_cont; + ret = wait_til_done(floppy_start, true); + debug_dcl(DP->flags, "calling disk change from raw_cmd ioctl\n"); - if (ret != -EINTR && FDCS->reset) - ret = -EIO; + if (ret != -EINTR && FDCS->reset) + ret = -EIO; - DRS->track = NO_TRACK; + DRS->track = NO_TRACK; - ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd); - if (!ret) - ret = ret2; - raw_cmd_free(&my_raw_cmd); - return ret; + ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd); + if (!ret) + ret = ret2; + raw_cmd_free(&my_raw_cmd); + return ret; } static int invalidate_drive(struct block_device *bdev) { - /* invalidate the buffer track to force a reread */ - set_bit((long)bdev->bd_disk->private_data, &fake_change); - process_fd_request(); - check_disk_change(bdev); - return 0; + /* invalidate the buffer track to force a reread */ + set_bit((long)bdev->bd_disk->private_data, &fake_change); + process_fd_request(); + check_disk_change(bdev); + return 0; } static int set_geometry(unsigned int cmd, struct floppy_struct *g, - int drive, int type, struct block_device *bdev) + int drive, int type, struct block_device *bdev) { - int cnt; + int cnt; - /* sanity checking for parameters. */ - if (g->sect <= 0 || - g->head <= 0 || - g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) || - /* check if reserved bits are set */ - (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0) - return -EINVAL; - if (type) { - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - mutex_lock(&open_lock); - if (lock_fdc(drive)) { - mutex_unlock(&open_lock); - return -EINTR; - } - floppy_type[type] = *g; - floppy_type[type].name = "user format"; - for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) - floppy_sizes[cnt] = floppy_sizes[cnt + 0x80] = - floppy_type[type].size + 1; - process_fd_request(); - for (cnt = 0; cnt < N_DRIVE; cnt++) { - struct block_device *bdev = opened_bdev[cnt]; - if (!bdev || ITYPE(drive_state[cnt].fd_device) != type) - continue; - __invalidate_device(bdev, true); - } - mutex_unlock(&open_lock); - } else { - int oldStretch; + /* sanity checking for parameters. */ + if (g->sect <= 0 || + g->head <= 0 || + g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) || + /* check if reserved bits are set */ + (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0) + return -EINVAL; + if (type) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + mutex_lock(&open_lock); + if (lock_fdc(drive)) { + mutex_unlock(&open_lock); + return -EINTR; + } + floppy_type[type] = *g; + floppy_type[type].name = "user format"; + for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) + floppy_sizes[cnt] = floppy_sizes[cnt + 0x80] = + floppy_type[type].size + 1; + process_fd_request(); + for (cnt = 0; cnt < N_DRIVE; cnt++) { + struct block_device *bdev = opened_bdev[cnt]; + if (!bdev || ITYPE(drive_state[cnt].fd_device) != type) + continue; + __invalidate_device(bdev, true); + } + mutex_unlock(&open_lock); + } else { + int oldStretch; - if (lock_fdc(drive)) - return -EINTR; - if (cmd != FDDEFPRM) { - /* notice a disk change immediately, else - * we lose our settings immediately*/ - if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) - return -EINTR; - } - oldStretch = g->stretch; - user_params[drive] = *g; - if (buffer_drive == drive) - SUPBOUND(buffer_max, user_params[drive].sect); - current_type[drive] = &user_params[drive]; - floppy_sizes[drive] = user_params[drive].size; - if (cmd == FDDEFPRM) - DRS->keep_data = -1; - else - DRS->keep_data = 1; - /* invalidation. Invalidate only when needed, i.e. - * when there are already sectors in the buffer cache - * whose number will change. This is useful, because - * mtools often changes the geometry of the disk after - * looking at the boot block */ - if (DRS->maxblock > user_params[drive].sect || - DRS->maxtrack || - ((user_params[drive].sect ^ oldStretch) & - (FD_SWAPSIDES | FD_SECTBASEMASK))) - invalidate_drive(bdev); - else - process_fd_request(); - } - return 0; + if (lock_fdc(drive)) + return -EINTR; + if (cmd != FDDEFPRM) { + /* notice a disk change immediately, else + * we lose our settings immediately*/ + if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) + return -EINTR; + } + oldStretch = g->stretch; + user_params[drive] = *g; + if (buffer_drive == drive) + SUPBOUND(buffer_max, user_params[drive].sect); + current_type[drive] = &user_params[drive]; + floppy_sizes[drive] = user_params[drive].size; + if (cmd == FDDEFPRM) + DRS->keep_data = -1; + else + DRS->keep_data = 1; + /* invalidation. Invalidate only when needed, i.e. + * when there are already sectors in the buffer cache + * whose number will change. This is useful, because + * mtools often changes the geometry of the disk after + * looking at the boot block */ + if (DRS->maxblock > user_params[drive].sect || + DRS->maxtrack || + ((user_params[drive].sect ^ oldStretch) & + (FD_SWAPSIDES | FD_SECTBASEMASK))) + invalidate_drive(bdev); + else + process_fd_request(); + } + return 0; } /* handle obsolete ioctl's */ static unsigned int ioctl_table[] = { - FDCLRPRM, - FDSETPRM, - FDDEFPRM, - FDGETPRM, - FDMSGON, - FDMSGOFF, - FDFMTBEG, - FDFMTTRK, - FDFMTEND, - FDSETEMSGTRESH, - FDFLUSH, - FDSETMAXERRS, - FDGETMAXERRS, - FDGETDRVTYP, - FDSETDRVPRM, - FDGETDRVPRM, - FDGETDRVSTAT, - FDPOLLDRVSTAT, - FDRESET, - FDGETFDCSTAT, - FDWERRORCLR, - FDWERRORGET, - FDRAWCMD, - FDEJECT, - FDTWADDLE + FDCLRPRM, + FDSETPRM, + FDDEFPRM, + FDGETPRM, + FDMSGON, + FDMSGOFF, + FDFMTBEG, + FDFMTTRK, + FDFMTEND, + FDSETEMSGTRESH, + FDFLUSH, + FDSETMAXERRS, + FDGETMAXERRS, + FDGETDRVTYP, + FDSETDRVPRM, + FDGETDRVPRM, + FDGETDRVSTAT, + FDPOLLDRVSTAT, + FDRESET, + FDGETFDCSTAT, + FDWERRORCLR, + FDWERRORGET, + FDRAWCMD, + FDEJECT, + FDTWADDLE }; static int normalize_ioctl(unsigned int *cmd, int *size) { - int i; + int i; - for (i = 0; i < ARRAY_SIZE(ioctl_table); i++) { - if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)) { - *size = _IOC_SIZE(*cmd); - *cmd = ioctl_table[i]; - if (*size > _IOC_SIZE(*cmd)) { - pr_info("ioctl not yet supported\n"); - return -EFAULT; - } - return 0; - } - } - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(ioctl_table); i++) { + if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)) { + *size = _IOC_SIZE(*cmd); + *cmd = ioctl_table[i]; + if (*size > _IOC_SIZE(*cmd)) { + pr_info("ioctl not yet supported\n"); + return -EFAULT; + } + return 0; + } + } + return -EINVAL; } static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) { - if (type) - *g = &floppy_type[type]; - else { - if (lock_fdc(drive)) - return -EINTR; - if (poll_drive(false, 0) == -EINTR) - return -EINTR; - process_fd_request(); - *g = current_type[drive]; - } - if (!*g) - return -ENODEV; - return 0; + if (type) + *g = &floppy_type[type]; + else { + if (lock_fdc(drive)) + return -EINTR; + if (poll_drive(false, 0) == -EINTR) + return -EINTR; + process_fd_request(); + *g = current_type[drive]; + } + if (!*g) + return -ENODEV; + return 0; } static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) { - int drive = (long)bdev->bd_disk->private_data; - int type = ITYPE(drive_state[drive].fd_device); - struct floppy_struct *g; - int ret; + int drive = (long)bdev->bd_disk->private_data; + int type = ITYPE(drive_state[drive].fd_device); + struct floppy_struct *g; + int ret; - ret = get_floppy_geometry(drive, type, &g); - if (ret) - return ret; + ret = get_floppy_geometry(drive, type, &g); + if (ret) + return ret; - geo->heads = g->head; - geo->sectors = g->sect; - geo->cylinders = g->track; - return 0; + geo->heads = g->head; + geo->sectors = g->sect; + geo->cylinders = g->track; + return 0; } static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, - unsigned long param) + unsigned long param) { - int drive = (long)bdev->bd_disk->private_data; - int type = ITYPE(UDRS->fd_device); - int i; - int ret; - int size; - union inparam { - struct floppy_struct g; /* geometry */ - struct format_descr f; - struct floppy_max_errors max_errors; - struct floppy_drive_params dp; - } inparam; /* parameters coming from user space */ - const void *outparam; /* parameters passed back to user space */ + int drive = (long)bdev->bd_disk->private_data; + int type = ITYPE(UDRS->fd_device); + int i; + int ret; + int size; + union inparam { + struct floppy_struct g; /* geometry */ + struct format_descr f; + struct floppy_max_errors max_errors; + struct floppy_drive_params dp; + } inparam; /* parameters coming from user space */ + const void *outparam; /* parameters passed back to user space */ - /* convert compatibility eject ioctls into floppy eject ioctl. - * We do this in order to provide a means to eject floppy disks before - * installing the new fdutils package */ - if (cmd == CDROMEJECT || /* CD-ROM eject */ - cmd == 0x6470) { /* SunOS floppy eject */ - DPRINT("obsolete eject ioctl\n"); - DPRINT("please use floppycontrol --eject\n"); - cmd = FDEJECT; - } + /* convert compatibility eject ioctls into floppy eject ioctl. + * We do this in order to provide a means to eject floppy disks before + * installing the new fdutils package */ + if (cmd == CDROMEJECT || /* CD-ROM eject */ + cmd == 0x6470) { /* SunOS floppy eject */ + DPRINT("obsolete eject ioctl\n"); + DPRINT("please use floppycontrol --eject\n"); + cmd = FDEJECT; + } - if (!((cmd & 0xff00) == 0x0200)) - return -EINVAL; + if (!((cmd & 0xff00) == 0x0200)) + return -EINVAL; - /* convert the old style command into a new style command */ - ret = normalize_ioctl(&cmd, &size); - if (ret) - return ret; + /* convert the old style command into a new style command */ + ret = normalize_ioctl(&cmd, &size); + if (ret) + return ret; - /* permission checks */ - if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) || - ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) - return -EPERM; + /* permission checks */ + if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) || + ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) + return -EPERM; - if (WARN_ON(size < 0 || size > sizeof(inparam))) - return -EINVAL; + if (WARN_ON(size < 0 || size > sizeof(inparam))) + return -EINVAL; - /* copyin */ - memset(&inparam, 0, sizeof(inparam)); - if (_IOC_DIR(cmd) & _IOC_WRITE) { - ret = fd_copyin((void __user *)param, &inparam, size); - if (ret) - return ret; - } + /* copyin */ + memset(&inparam, 0, sizeof(inparam)); + if (_IOC_DIR(cmd) & _IOC_WRITE) { + ret = fd_copyin((void __user *)param, &inparam, size); + if (ret) + return ret; + } - switch (cmd) { - case FDEJECT: - if (UDRS->fd_ref != 1) - /* somebody else has this drive open */ - return -EBUSY; - if (lock_fdc(drive)) - return -EINTR; + switch (cmd) { + case FDEJECT: + if (UDRS->fd_ref != 1) + /* somebody else has this drive open */ + return -EBUSY; + if (lock_fdc(drive)) + return -EINTR; - /* do the actual eject. Fails on - * non-Sparc architectures */ - ret = fd_eject(UNIT(drive)); + /* do the actual eject. Fails on + * non-Sparc architectures */ + ret = fd_eject(UNIT(drive)); - set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); - set_bit(FD_VERIFY_BIT, &UDRS->flags); - process_fd_request(); - return ret; - case FDCLRPRM: - if (lock_fdc(drive)) - return -EINTR; - current_type[drive] = NULL; - floppy_sizes[drive] = MAX_DISK_SIZE << 1; - UDRS->keep_data = 0; - return invalidate_drive(bdev); - case FDSETPRM: - case FDDEFPRM: - return set_geometry(cmd, &inparam.g, drive, type, bdev); - case FDGETPRM: - ret = get_floppy_geometry(drive, type, - (struct floppy_struct **)&outparam); - if (ret) - return ret; - memcpy(&inparam.g, outparam, - offsetof(struct floppy_struct, name)); - outparam = &inparam.g; - break; - case FDMSGON: - UDP->flags |= FTD_MSG; - return 0; - case FDMSGOFF: - UDP->flags &= ~FTD_MSG; - return 0; - case FDFMTBEG: - if (lock_fdc(drive)) - return -EINTR; - if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) - return -EINTR; - ret = UDRS->flags; - process_fd_request(); - if (ret & FD_VERIFY) - return -ENODEV; - if (!(ret & FD_DISK_WRITABLE)) - return -EROFS; - return 0; - case FDFMTTRK: - if (UDRS->fd_ref != 1) - return -EBUSY; - return do_format(drive, &inparam.f); - case FDFMTEND: - case FDFLUSH: - if (lock_fdc(drive)) - return -EINTR; - return invalidate_drive(bdev); - case FDSETEMSGTRESH: - UDP->max_errors.reporting = (unsigned short)(param & 0x0f); - return 0; - case FDGETMAXERRS: - outparam = &UDP->max_errors; - break; - case FDSETMAXERRS: - UDP->max_errors = inparam.max_errors; - break; - case FDGETDRVTYP: - outparam = drive_name(type, drive); - SUPBOUND(size, strlen((const char *)outparam) + 1); - break; - case FDSETDRVPRM: - *UDP = inparam.dp; - break; - case FDGETDRVPRM: - outparam = UDP; - break; - case FDPOLLDRVSTAT: - if (lock_fdc(drive)) - return -EINTR; - if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) - return -EINTR; - process_fd_request(); - /* fall through */ - case FDGETDRVSTAT: - outparam = UDRS; - break; - case FDRESET: - return user_reset_fdc(drive, (int)param, true); - case FDGETFDCSTAT: - outparam = UFDCS; - break; - case FDWERRORCLR: - memset(UDRWE, 0, sizeof(*UDRWE)); - return 0; - case FDWERRORGET: - outparam = UDRWE; - break; - case FDRAWCMD: - if (type) - return -EINVAL; - if (lock_fdc(drive)) - return -EINTR; - set_floppy(drive); - i = raw_cmd_ioctl(cmd, (void __user *)param); - if (i == -EINTR) - return -EINTR; - process_fd_request(); - return i; - case FDTWADDLE: - if (lock_fdc(drive)) - return -EINTR; - twaddle(); - process_fd_request(); - return 0; - default: - return -EINVAL; - } + set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + set_bit(FD_VERIFY_BIT, &UDRS->flags); + process_fd_request(); + return ret; + case FDCLRPRM: + if (lock_fdc(drive)) + return -EINTR; + current_type[drive] = NULL; + floppy_sizes[drive] = MAX_DISK_SIZE << 1; + UDRS->keep_data = 0; + return invalidate_drive(bdev); + case FDSETPRM: + case FDDEFPRM: + return set_geometry(cmd, &inparam.g, drive, type, bdev); + case FDGETPRM: + ret = get_floppy_geometry(drive, type, + (struct floppy_struct **)&outparam); + if (ret) + return ret; + memcpy(&inparam.g, outparam, + offsetof(struct floppy_struct, name)); + outparam = &inparam.g; + break; + case FDMSGON: + UDP->flags |= FTD_MSG; + return 0; + case FDMSGOFF: + UDP->flags &= ~FTD_MSG; + return 0; + case FDFMTBEG: + if (lock_fdc(drive)) + return -EINTR; + if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) + return -EINTR; + ret = UDRS->flags; + process_fd_request(); + if (ret & FD_VERIFY) + return -ENODEV; + if (!(ret & FD_DISK_WRITABLE)) + return -EROFS; + return 0; + case FDFMTTRK: + if (UDRS->fd_ref != 1) + return -EBUSY; + return do_format(drive, &inparam.f); + case FDFMTEND: + case FDFLUSH: + if (lock_fdc(drive)) + return -EINTR; + return invalidate_drive(bdev); + case FDSETEMSGTRESH: + UDP->max_errors.reporting = (unsigned short)(param & 0x0f); + return 0; + case FDGETMAXERRS: + outparam = &UDP->max_errors; + break; + case FDSETMAXERRS: + UDP->max_errors = inparam.max_errors; + break; + case FDGETDRVTYP: + outparam = drive_name(type, drive); + SUPBOUND(size, strlen((const char *)outparam) + 1); + break; + case FDSETDRVPRM: + *UDP = inparam.dp; + break; + case FDGETDRVPRM: + outparam = UDP; + break; + case FDPOLLDRVSTAT: + if (lock_fdc(drive)) + return -EINTR; + if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) + return -EINTR; + process_fd_request(); + /* fall through */ + case FDGETDRVSTAT: + outparam = UDRS; + break; + case FDRESET: + return user_reset_fdc(drive, (int)param, true); + case FDGETFDCSTAT: + outparam = UFDCS; + break; + case FDWERRORCLR: + memset(UDRWE, 0, sizeof(*UDRWE)); + return 0; + case FDWERRORGET: + outparam = UDRWE; + break; + case FDRAWCMD: + if (type) + return -EINVAL; + if (lock_fdc(drive)) + return -EINTR; + set_floppy(drive); + i = raw_cmd_ioctl(cmd, (void __user *)param); + if (i == -EINTR) + return -EINTR; + process_fd_request(); + return i; + case FDTWADDLE: + if (lock_fdc(drive)) + return -EINTR; + twaddle(); + process_fd_request(); + return 0; + default: + return -EINVAL; + } - if (_IOC_DIR(cmd) & _IOC_READ) - return fd_copyout((void __user *)param, outparam, size); + if (_IOC_DIR(cmd) & _IOC_READ) + return fd_copyout((void __user *)param, outparam, size); - return 0; + return 0; } static int fd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long param) + unsigned int cmd, unsigned long param) { - int ret; + int ret; - mutex_lock(&floppy_mutex); - ret = fd_locked_ioctl(bdev, mode, cmd, param); - mutex_unlock(&floppy_mutex); + mutex_lock(&floppy_mutex); + ret = fd_locked_ioctl(bdev, mode, cmd, param); + mutex_unlock(&floppy_mutex); - return ret; + return ret; } #ifdef CONFIG_COMPAT struct compat_floppy_drive_params { - char cmos; - compat_ulong_t max_dtr; - compat_ulong_t hlt; - compat_ulong_t hut; - compat_ulong_t srt; - compat_ulong_t spinup; - compat_ulong_t spindown; - unsigned char spindown_offset; - unsigned char select_delay; - unsigned char rps; - unsigned char tracks; - compat_ulong_t timeout; - unsigned char interleave_sect; - struct floppy_max_errors max_errors; - char flags; - char read_track; - short autodetect[8]; - compat_int_t checkfreq; - compat_int_t native_format; + char cmos; + compat_ulong_t max_dtr; + compat_ulong_t hlt; + compat_ulong_t hut; + compat_ulong_t srt; + compat_ulong_t spinup; + compat_ulong_t spindown; + unsigned char spindown_offset; + unsigned char select_delay; + unsigned char rps; + unsigned char tracks; + compat_ulong_t timeout; + unsigned char interleave_sect; + struct floppy_max_errors max_errors; + char flags; + char read_track; + short autodetect[8]; + compat_int_t checkfreq; + compat_int_t native_format; }; struct compat_floppy_drive_struct { - signed char flags; - compat_ulong_t spinup_date; - compat_ulong_t select_date; - compat_ulong_t first_read_date; - short probed_format; - short track; - short maxblock; - short maxtrack; - compat_int_t generation; - compat_int_t keep_data; - compat_int_t fd_ref; - compat_int_t fd_device; - compat_int_t last_checked; - compat_caddr_t dmabuf; - compat_int_t bufblocks; + signed char flags; + compat_ulong_t spinup_date; + compat_ulong_t select_date; + compat_ulong_t first_read_date; + short probed_format; + short track; + short maxblock; + short maxtrack; + compat_int_t generation; + compat_int_t keep_data; + compat_int_t fd_ref; + compat_int_t fd_device; + compat_int_t last_checked; + compat_caddr_t dmabuf; + compat_int_t bufblocks; }; struct compat_floppy_fdc_state { - compat_int_t spec1; - compat_int_t spec2; - compat_int_t dtr; - unsigned char version; - unsigned char dor; - compat_ulong_t address; - unsigned int rawcmd:2; - unsigned int reset:1; - unsigned int need_configure:1; - unsigned int perp_mode:2; - unsigned int has_fifo:1; - unsigned int driver_version; - unsigned char track[4]; + compat_int_t spec1; + compat_int_t spec2; + compat_int_t dtr; + unsigned char version; + unsigned char dor; + compat_ulong_t address; + unsigned int rawcmd : 2; + unsigned int reset : 1; + unsigned int need_configure : 1; + unsigned int perp_mode : 2; + unsigned int has_fifo : 1; + unsigned int driver_version; + unsigned char track[4]; }; struct compat_floppy_write_errors { - unsigned int write_errors; - compat_ulong_t first_error_sector; - compat_int_t first_error_generation; - compat_ulong_t last_error_sector; - compat_int_t last_error_generation; - compat_uint_t badness; + unsigned int write_errors; + compat_ulong_t first_error_sector; + compat_int_t first_error_generation; + compat_ulong_t last_error_sector; + compat_int_t last_error_generation; + compat_uint_t badness; }; #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) @@ -3643,320 +3642,320 @@ struct compat_floppy_write_errors { #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd, - struct compat_floppy_struct __user *arg) + struct compat_floppy_struct __user *arg) { - struct floppy_struct v; - int drive, type; - int err; + struct floppy_struct v; + int drive, type; + int err; - BUILD_BUG_ON(offsetof(struct floppy_struct, name) != - offsetof(struct compat_floppy_struct, name)); + BUILD_BUG_ON(offsetof(struct floppy_struct, name) != + offsetof(struct compat_floppy_struct, name)); - if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) - return -EPERM; + if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) + return -EPERM; - memset(&v, 0, sizeof(struct floppy_struct)); - if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name))) - return -EFAULT; + memset(&v, 0, sizeof(struct floppy_struct)); + if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name))) + return -EFAULT; - mutex_lock(&floppy_mutex); - drive = (long)bdev->bd_disk->private_data; - type = ITYPE(UDRS->fd_device); - err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM, - &v, drive, type, bdev); - mutex_unlock(&floppy_mutex); - return err; + mutex_lock(&floppy_mutex); + drive = (long)bdev->bd_disk->private_data; + type = ITYPE(UDRS->fd_device); + err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM, + &v, drive, type, bdev); + mutex_unlock(&floppy_mutex); + return err; } static int compat_get_prm(int drive, - struct compat_floppy_struct __user *arg) + struct compat_floppy_struct __user *arg) { - struct compat_floppy_struct v; - struct floppy_struct *p; - int err; + struct compat_floppy_struct v; + struct floppy_struct *p; + int err; - memset(&v, 0, sizeof(v)); - mutex_lock(&floppy_mutex); - err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p); - if (err) { - mutex_unlock(&floppy_mutex); - return err; - } - memcpy(&v, p, offsetof(struct floppy_struct, name)); - mutex_unlock(&floppy_mutex); - if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct))) - return -EFAULT; - return 0; + memset(&v, 0, sizeof(v)); + mutex_lock(&floppy_mutex); + err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p); + if (err) { + mutex_unlock(&floppy_mutex); + return err; + } + memcpy(&v, p, offsetof(struct floppy_struct, name)); + mutex_unlock(&floppy_mutex); + if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct))) + return -EFAULT; + return 0; } static int compat_setdrvprm(int drive, - struct compat_floppy_drive_params __user *arg) + struct compat_floppy_drive_params __user *arg) { - struct compat_floppy_drive_params v; + struct compat_floppy_drive_params v; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params))) - return -EFAULT; - mutex_lock(&floppy_mutex); - UDP->cmos = v.cmos; - UDP->max_dtr = v.max_dtr; - UDP->hlt = v.hlt; - UDP->hut = v.hut; - UDP->srt = v.srt; - UDP->spinup = v.spinup; - UDP->spindown = v.spindown; - UDP->spindown_offset = v.spindown_offset; - UDP->select_delay = v.select_delay; - UDP->rps = v.rps; - UDP->tracks = v.tracks; - UDP->timeout = v.timeout; - UDP->interleave_sect = v.interleave_sect; - UDP->max_errors = v.max_errors; - UDP->flags = v.flags; - UDP->read_track = v.read_track; - memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect)); - UDP->checkfreq = v.checkfreq; - UDP->native_format = v.native_format; - mutex_unlock(&floppy_mutex); - return 0; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params))) + return -EFAULT; + mutex_lock(&floppy_mutex); + UDP->cmos = v.cmos; + UDP->max_dtr = v.max_dtr; + UDP->hlt = v.hlt; + UDP->hut = v.hut; + UDP->srt = v.srt; + UDP->spinup = v.spinup; + UDP->spindown = v.spindown; + UDP->spindown_offset = v.spindown_offset; + UDP->select_delay = v.select_delay; + UDP->rps = v.rps; + UDP->tracks = v.tracks; + UDP->timeout = v.timeout; + UDP->interleave_sect = v.interleave_sect; + UDP->max_errors = v.max_errors; + UDP->flags = v.flags; + UDP->read_track = v.read_track; + memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect)); + UDP->checkfreq = v.checkfreq; + UDP->native_format = v.native_format; + mutex_unlock(&floppy_mutex); + return 0; } static int compat_getdrvprm(int drive, - struct compat_floppy_drive_params __user *arg) + struct compat_floppy_drive_params __user *arg) { - struct compat_floppy_drive_params v; + struct compat_floppy_drive_params v; - memset(&v, 0, sizeof(struct compat_floppy_drive_params)); - mutex_lock(&floppy_mutex); - v.cmos = UDP->cmos; - v.max_dtr = UDP->max_dtr; - v.hlt = UDP->hlt; - v.hut = UDP->hut; - v.srt = UDP->srt; - v.spinup = UDP->spinup; - v.spindown = UDP->spindown; - v.spindown_offset = UDP->spindown_offset; - v.select_delay = UDP->select_delay; - v.rps = UDP->rps; - v.tracks = UDP->tracks; - v.timeout = UDP->timeout; - v.interleave_sect = UDP->interleave_sect; - v.max_errors = UDP->max_errors; - v.flags = UDP->flags; - v.read_track = UDP->read_track; - memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect)); - v.checkfreq = UDP->checkfreq; - v.native_format = UDP->native_format; - mutex_unlock(&floppy_mutex); + memset(&v, 0, sizeof(struct compat_floppy_drive_params)); + mutex_lock(&floppy_mutex); + v.cmos = UDP->cmos; + v.max_dtr = UDP->max_dtr; + v.hlt = UDP->hlt; + v.hut = UDP->hut; + v.srt = UDP->srt; + v.spinup = UDP->spinup; + v.spindown = UDP->spindown; + v.spindown_offset = UDP->spindown_offset; + v.select_delay = UDP->select_delay; + v.rps = UDP->rps; + v.tracks = UDP->tracks; + v.timeout = UDP->timeout; + v.interleave_sect = UDP->interleave_sect; + v.max_errors = UDP->max_errors; + v.flags = UDP->flags; + v.read_track = UDP->read_track; + memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect)); + v.checkfreq = UDP->checkfreq; + v.native_format = UDP->native_format; + mutex_unlock(&floppy_mutex); - if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params))) - return -EFAULT; - return 0; + if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params))) + return -EFAULT; + return 0; } static int compat_getdrvstat(int drive, bool poll, - struct compat_floppy_drive_struct __user *arg) + struct compat_floppy_drive_struct __user *arg) { - struct compat_floppy_drive_struct v; + struct compat_floppy_drive_struct v; - memset(&v, 0, sizeof(struct compat_floppy_drive_struct)); - mutex_lock(&floppy_mutex); + memset(&v, 0, sizeof(struct compat_floppy_drive_struct)); + mutex_lock(&floppy_mutex); - if (poll) { - if (lock_fdc(drive)) - goto Eintr; - if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) - goto Eintr; - process_fd_request(); - } - v.spinup_date = UDRS->spinup_date; - v.select_date = UDRS->select_date; - v.first_read_date = UDRS->first_read_date; - v.probed_format = UDRS->probed_format; - v.track = UDRS->track; - v.maxblock = UDRS->maxblock; - v.maxtrack = UDRS->maxtrack; - v.generation = UDRS->generation; - v.keep_data = UDRS->keep_data; - v.fd_ref = UDRS->fd_ref; - v.fd_device = UDRS->fd_device; - v.last_checked = UDRS->last_checked; - v.dmabuf = (uintptr_t)UDRS->dmabuf; - v.bufblocks = UDRS->bufblocks; - mutex_unlock(&floppy_mutex); + if (poll) { + if (lock_fdc(drive)) + goto Eintr; + if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) + goto Eintr; + process_fd_request(); + } + v.spinup_date = UDRS->spinup_date; + v.select_date = UDRS->select_date; + v.first_read_date = UDRS->first_read_date; + v.probed_format = UDRS->probed_format; + v.track = UDRS->track; + v.maxblock = UDRS->maxblock; + v.maxtrack = UDRS->maxtrack; + v.generation = UDRS->generation; + v.keep_data = UDRS->keep_data; + v.fd_ref = UDRS->fd_ref; + v.fd_device = UDRS->fd_device; + v.last_checked = UDRS->last_checked; + v.dmabuf = (uintptr_t)UDRS->dmabuf; + v.bufblocks = UDRS->bufblocks; + mutex_unlock(&floppy_mutex); - if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) - return -EFAULT; - return 0; + if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) + return -EFAULT; + return 0; Eintr: - mutex_unlock(&floppy_mutex); - return -EINTR; + mutex_unlock(&floppy_mutex); + return -EINTR; } static int compat_getfdcstat(int drive, - struct compat_floppy_fdc_state __user *arg) + struct compat_floppy_fdc_state __user *arg) { - struct compat_floppy_fdc_state v32; - struct floppy_fdc_state v; + struct compat_floppy_fdc_state v32; + struct floppy_fdc_state v; - mutex_lock(&floppy_mutex); - v = *UFDCS; - mutex_unlock(&floppy_mutex); + mutex_lock(&floppy_mutex); + v = *UFDCS; + mutex_unlock(&floppy_mutex); - memset(&v32, 0, sizeof(struct compat_floppy_fdc_state)); - v32.spec1 = v.spec1; - v32.spec2 = v.spec2; - v32.dtr = v.dtr; - v32.version = v.version; - v32.dor = v.dor; - v32.address = v.address; - v32.rawcmd = v.rawcmd; - v32.reset = v.reset; - v32.need_configure = v.need_configure; - v32.perp_mode = v.perp_mode; - v32.has_fifo = v.has_fifo; - v32.driver_version = v.driver_version; - memcpy(v32.track, v.track, 4); - if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state))) - return -EFAULT; - return 0; + memset(&v32, 0, sizeof(struct compat_floppy_fdc_state)); + v32.spec1 = v.spec1; + v32.spec2 = v.spec2; + v32.dtr = v.dtr; + v32.version = v.version; + v32.dor = v.dor; + v32.address = v.address; + v32.rawcmd = v.rawcmd; + v32.reset = v.reset; + v32.need_configure = v.need_configure; + v32.perp_mode = v.perp_mode; + v32.has_fifo = v.has_fifo; + v32.driver_version = v.driver_version; + memcpy(v32.track, v.track, 4); + if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state))) + return -EFAULT; + return 0; } static int compat_werrorget(int drive, - struct compat_floppy_write_errors __user *arg) + struct compat_floppy_write_errors __user *arg) { - struct compat_floppy_write_errors v32; - struct floppy_write_errors v; + struct compat_floppy_write_errors v32; + struct floppy_write_errors v; - memset(&v32, 0, sizeof(struct compat_floppy_write_errors)); - mutex_lock(&floppy_mutex); - v = *UDRWE; - mutex_unlock(&floppy_mutex); - v32.write_errors = v.write_errors; - v32.first_error_sector = v.first_error_sector; - v32.first_error_generation = v.first_error_generation; - v32.last_error_sector = v.last_error_sector; - v32.last_error_generation = v.last_error_generation; - v32.badness = v.badness; - if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors))) - return -EFAULT; - return 0; + memset(&v32, 0, sizeof(struct compat_floppy_write_errors)); + mutex_lock(&floppy_mutex); + v = *UDRWE; + mutex_unlock(&floppy_mutex); + v32.write_errors = v.write_errors; + v32.first_error_sector = v.first_error_sector; + v32.first_error_generation = v.first_error_generation; + v32.last_error_sector = v.last_error_sector; + v32.last_error_generation = v.last_error_generation; + v32.badness = v.badness; + if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors))) + return -EFAULT; + return 0; } static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, - unsigned long param) + unsigned long param) { - int drive = (long)bdev->bd_disk->private_data; - switch (cmd) { - case FDMSGON: - case FDMSGOFF: - case FDSETEMSGTRESH: - case FDFLUSH: - case FDWERRORCLR: - case FDEJECT: - case FDCLRPRM: - case FDFMTBEG: - case FDRESET: - case FDTWADDLE: - return fd_ioctl(bdev, mode, cmd, param); - case FDSETMAXERRS: - case FDGETMAXERRS: - case FDGETDRVTYP: - case FDFMTEND: - case FDFMTTRK: - case FDRAWCMD: - return fd_ioctl(bdev, mode, cmd, - (unsigned long)compat_ptr(param)); - case FDSETPRM32: - case FDDEFPRM32: - return compat_set_geometry(bdev, mode, cmd, compat_ptr(param)); - case FDGETPRM32: - return compat_get_prm(drive, compat_ptr(param)); - case FDSETDRVPRM32: - return compat_setdrvprm(drive, compat_ptr(param)); - case FDGETDRVPRM32: - return compat_getdrvprm(drive, compat_ptr(param)); - case FDPOLLDRVSTAT32: - return compat_getdrvstat(drive, true, compat_ptr(param)); - case FDGETDRVSTAT32: - return compat_getdrvstat(drive, false, compat_ptr(param)); - case FDGETFDCSTAT32: - return compat_getfdcstat(drive, compat_ptr(param)); - case FDWERRORGET32: - return compat_werrorget(drive, compat_ptr(param)); - } - return -EINVAL; + int drive = (long)bdev->bd_disk->private_data; + switch (cmd) { + case FDMSGON: + case FDMSGOFF: + case FDSETEMSGTRESH: + case FDFLUSH: + case FDWERRORCLR: + case FDEJECT: + case FDCLRPRM: + case FDFMTBEG: + case FDRESET: + case FDTWADDLE: + return fd_ioctl(bdev, mode, cmd, param); + case FDSETMAXERRS: + case FDGETMAXERRS: + case FDGETDRVTYP: + case FDFMTEND: + case FDFMTTRK: + case FDRAWCMD: + return fd_ioctl(bdev, mode, cmd, + (unsigned long)compat_ptr(param)); + case FDSETPRM32: + case FDDEFPRM32: + return compat_set_geometry(bdev, mode, cmd, compat_ptr(param)); + case FDGETPRM32: + return compat_get_prm(drive, compat_ptr(param)); + case FDSETDRVPRM32: + return compat_setdrvprm(drive, compat_ptr(param)); + case FDGETDRVPRM32: + return compat_getdrvprm(drive, compat_ptr(param)); + case FDPOLLDRVSTAT32: + return compat_getdrvstat(drive, true, compat_ptr(param)); + case FDGETDRVSTAT32: + return compat_getdrvstat(drive, false, compat_ptr(param)); + case FDGETFDCSTAT32: + return compat_getfdcstat(drive, compat_ptr(param)); + case FDWERRORGET32: + return compat_werrorget(drive, compat_ptr(param)); + } + return -EINVAL; } #endif static void __init config_types(void) { - bool has_drive = false; - int drive; + bool has_drive = false; + int drive; - /* read drive info out of physical CMOS */ - drive = 0; - if (!UDP->cmos) - UDP->cmos = FLOPPY0_TYPE; - drive = 1; - if (!UDP->cmos && FLOPPY1_TYPE) - UDP->cmos = FLOPPY1_TYPE; + /* read drive info out of physical CMOS */ + drive = 0; + if (!UDP->cmos) + UDP->cmos = FLOPPY0_TYPE; + drive = 1; + if (!UDP->cmos && FLOPPY1_TYPE) + UDP->cmos = FLOPPY1_TYPE; - /* FIXME: additional physical CMOS drive detection should go here */ + /* FIXME: additional physical CMOS drive detection should go here */ - for (drive = 0; drive < N_DRIVE; drive++) { - unsigned int type = UDP->cmos; - struct floppy_drive_params *params; - const char *name = NULL; - char temparea[32]; + for (drive = 0; drive < N_DRIVE; drive++) { + unsigned int type = UDP->cmos; + struct floppy_drive_params *params; + const char *name = NULL; + char temparea[32]; - if (type < ARRAY_SIZE(default_drive_params)) { - params = &default_drive_params[type].params; - if (type) { - name = default_drive_params[type].name; - allowed_drive_mask |= 1 << drive; - } else - allowed_drive_mask &= ~(1 << drive); - } else { - params = &default_drive_params[0].params; - snprintf(temparea, sizeof(temparea), - "unknown type %d (usb?)", type); - name = temparea; - } - if (name) { - const char *prepend; - if (!has_drive) { - prepend = ""; - has_drive = true; - pr_info("Floppy drive(s):"); - } else { - prepend = ","; - } + if (type < ARRAY_SIZE(default_drive_params)) { + params = &default_drive_params[type].params; + if (type) { + name = default_drive_params[type].name; + allowed_drive_mask |= 1 << drive; + } else + allowed_drive_mask &= ~(1 << drive); + } else { + params = &default_drive_params[0].params; + snprintf(temparea, sizeof(temparea), + "unknown type %d (usb?)", type); + name = temparea; + } + if (name) { + const char *prepend; + if (!has_drive) { + prepend = ""; + has_drive = true; + pr_info("Floppy drive(s):"); + } else { + prepend = ","; + } - pr_cont("%s fd%d is %s", prepend, drive, name); - } - *UDP = *params; - } + pr_cont("%s fd%d is %s", prepend, drive, name); + } + *UDP = *params; + } - if (has_drive) - pr_cont("\n"); + if (has_drive) + pr_cont("\n"); } static void floppy_release(struct gendisk *disk, fmode_t mode) { - int drive = (long)disk->private_data; + int drive = (long)disk->private_data; - mutex_lock(&floppy_mutex); - mutex_lock(&open_lock); - if (!UDRS->fd_ref--) { - DPRINT("floppy_release with fd_ref == 0"); - UDRS->fd_ref = 0; - } - if (!UDRS->fd_ref) - opened_bdev[drive] = NULL; - mutex_unlock(&open_lock); - mutex_unlock(&floppy_mutex); + mutex_lock(&floppy_mutex); + mutex_lock(&open_lock); + if (!UDRS->fd_ref--) { + DPRINT("floppy_release with fd_ref == 0"); + UDRS->fd_ref = 0; + } + if (!UDRS->fd_ref) + opened_bdev[drive] = NULL; + mutex_unlock(&open_lock); + mutex_unlock(&floppy_mutex); } /* @@ -3966,124 +3965,124 @@ static void floppy_release(struct gendisk *disk, fmode_t mode) */ static int floppy_open(struct block_device *bdev, fmode_t mode) { - int drive = (long)bdev->bd_disk->private_data; - int old_dev, new_dev; - int try; - int res = -EBUSY; - char *tmp; + int drive = (long)bdev->bd_disk->private_data; + int old_dev, new_dev; + int try; + int res = -EBUSY; + char *tmp; - mutex_lock(&floppy_mutex); - mutex_lock(&open_lock); - old_dev = UDRS->fd_device; - if (opened_bdev[drive] && opened_bdev[drive] != bdev) - goto out2; + mutex_lock(&floppy_mutex); + mutex_lock(&open_lock); + old_dev = UDRS->fd_device; + if (opened_bdev[drive] && opened_bdev[drive] != bdev) + goto out2; - if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) { - set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); - set_bit(FD_VERIFY_BIT, &UDRS->flags); - } + if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) { + set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + set_bit(FD_VERIFY_BIT, &UDRS->flags); + } - UDRS->fd_ref++; + UDRS->fd_ref++; - opened_bdev[drive] = bdev; + opened_bdev[drive] = bdev; - res = -ENXIO; + res = -ENXIO; - if (!floppy_track_buffer) { - /* if opening an ED drive, reserve a big buffer, - * else reserve a small one */ - if ((UDP->cmos == 6) || (UDP->cmos == 5)) - try = 64; /* Only 48 actually useful */ - else - try = 32; /* Only 24 actually useful */ + if (!floppy_track_buffer) { + /* if opening an ED drive, reserve a big buffer, + * else reserve a small one */ + if ((UDP->cmos == 6) || (UDP->cmos == 5)) + try = 64; /* Only 48 actually useful */ + else + try = 32; /* Only 24 actually useful */ - tmp = (char *)fd_dma_mem_alloc(1024 * try); - if (!tmp && !floppy_track_buffer) { - try >>= 1; /* buffer only one side */ - INFBOUND(try, 16); - tmp = (char *)fd_dma_mem_alloc(1024 * try); - } - if (!tmp && !floppy_track_buffer) - fallback_on_nodma_alloc(&tmp, 2048 * try); - if (!tmp && !floppy_track_buffer) { - DPRINT("Unable to allocate DMA memory\n"); - goto out; - } - if (floppy_track_buffer) { - if (tmp) - fd_dma_mem_free((unsigned long)tmp, try * 1024); - } else { - buffer_min = buffer_max = -1; - floppy_track_buffer = tmp; - max_buffer_sectors = try; - } - } + tmp = (char *)fd_dma_mem_alloc(1024 * try); + if (!tmp && !floppy_track_buffer) { + try >>= 1; /* buffer only one side */ + INFBOUND(try, 16); + tmp = (char *)fd_dma_mem_alloc(1024 * try); + } + if (!tmp && !floppy_track_buffer) + fallback_on_nodma_alloc(&tmp, 2048 * try); + if (!tmp && !floppy_track_buffer) { + DPRINT("Unable to allocate DMA memory\n"); + goto out; + } + if (floppy_track_buffer) { + if (tmp) + fd_dma_mem_free((unsigned long)tmp, try * 1024); + } else { + buffer_min = buffer_max = -1; + floppy_track_buffer = tmp; + max_buffer_sectors = try; + } + } - new_dev = MINOR(bdev->bd_dev); - UDRS->fd_device = new_dev; - set_capacity(disks[drive], floppy_sizes[new_dev]); - if (old_dev != -1 && old_dev != new_dev) { - if (buffer_drive == drive) - buffer_track = -1; - } + new_dev = MINOR(bdev->bd_dev); + UDRS->fd_device = new_dev; + set_capacity(disks[drive], floppy_sizes[new_dev]); + if (old_dev != -1 && old_dev != new_dev) { + if (buffer_drive == drive) + buffer_track = -1; + } - if (UFDCS->rawcmd == 1) - UFDCS->rawcmd = 2; + if (UFDCS->rawcmd == 1) + UFDCS->rawcmd = 2; - if (!(mode & FMODE_NDELAY)) { - if (mode & (FMODE_READ|FMODE_WRITE)) { - UDRS->last_checked = 0; - clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); - check_disk_change(bdev); - if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) - goto out; - if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) - goto out; - } - res = -EROFS; - if ((mode & FMODE_WRITE) && - !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) - goto out; - } - mutex_unlock(&open_lock); - mutex_unlock(&floppy_mutex); - return 0; + if (!(mode & FMODE_NDELAY)) { + if (mode & (FMODE_READ|FMODE_WRITE)) { + UDRS->last_checked = 0; + clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); + check_disk_change(bdev); + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) + goto out; + if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) + goto out; + } + res = -EROFS; + if ((mode & FMODE_WRITE) && + !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) + goto out; + } + mutex_unlock(&open_lock); + mutex_unlock(&floppy_mutex); + return 0; out: - UDRS->fd_ref--; + UDRS->fd_ref--; - if (!UDRS->fd_ref) - opened_bdev[drive] = NULL; + if (!UDRS->fd_ref) + opened_bdev[drive] = NULL; out2: - mutex_unlock(&open_lock); - mutex_unlock(&floppy_mutex); - return res; + mutex_unlock(&open_lock); + mutex_unlock(&floppy_mutex); + return res; } /* * Check if the disk has been changed or if a change has been faked. */ static unsigned int floppy_check_events(struct gendisk *disk, - unsigned int clearing) + unsigned int clearing) { - int drive = (long)disk->private_data; + int drive = (long)disk->private_data; - if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || - test_bit(FD_VERIFY_BIT, &UDRS->flags)) - return DISK_EVENT_MEDIA_CHANGE; + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || + test_bit(FD_VERIFY_BIT, &UDRS->flags)) + return DISK_EVENT_MEDIA_CHANGE; - if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { - if (lock_fdc(drive)) - return 0; - poll_drive(false, 0); - process_fd_request(); - } + if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { + if (lock_fdc(drive)) + return 0; + poll_drive(false, 0); + process_fd_request(); + } - if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || - test_bit(FD_VERIFY_BIT, &UDRS->flags) || - test_bit(drive, &fake_change) || - drive_no_geom(drive)) - return DISK_EVENT_MEDIA_CHANGE; - return 0; + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || + test_bit(FD_VERIFY_BIT, &UDRS->flags) || + test_bit(drive, &fake_change) || + drive_no_geom(drive)) + return DISK_EVENT_MEDIA_CHANGE; + return 0; } /* @@ -4093,63 +4092,63 @@ static unsigned int floppy_check_events(struct gendisk *disk, */ struct rb0_cbdata { - int drive; - struct completion complete; + int drive; + struct completion complete; }; static void floppy_rb0_cb(struct bio *bio) { - struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private; - int drive = cbdata->drive; + struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private; + int drive = cbdata->drive; - if (bio->bi_status) { - pr_info("floppy: error %d while reading block 0\n", - bio->bi_status); - set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); - } - complete(&cbdata->complete); + if (bio->bi_status) { + pr_info("floppy: error %d while reading block 0\n", + bio->bi_status); + set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); + } + complete(&cbdata->complete); } static int __floppy_read_block_0(struct block_device *bdev, int drive) { - struct bio bio; - struct bio_vec bio_vec; - struct page *page; - struct rb0_cbdata cbdata; - size_t size; + struct bio bio; + struct bio_vec bio_vec; + struct page *page; + struct rb0_cbdata cbdata; + size_t size; - page = alloc_page(GFP_NOIO); - if (!page) { - process_fd_request(); - return -ENOMEM; - } + page = alloc_page(GFP_NOIO); + if (!page) { + process_fd_request(); + return -ENOMEM; + } - size = bdev->bd_block_size; - if (!size) - size = 1024; + size = bdev->bd_block_size; + if (!size) + size = 1024; - cbdata.drive = drive; + cbdata.drive = drive; - bio_init(&bio, &bio_vec, 1); - bio_set_dev(&bio, bdev); - bio_add_page(&bio, page, size, 0); + bio_init(&bio, &bio_vec, 1); + bio_set_dev(&bio, bdev); + bio_add_page(&bio, page, size, 0); - bio.bi_iter.bi_sector = 0; - bio.bi_flags |= (1 << BIO_QUIET); - bio.bi_private = &cbdata; - bio.bi_end_io = floppy_rb0_cb; - bio_set_op_attrs(&bio, REQ_OP_READ, 0); + bio.bi_iter.bi_sector = 0; + bio.bi_flags |= (1 << BIO_QUIET); + bio.bi_private = &cbdata; + bio.bi_end_io = floppy_rb0_cb; + bio_set_op_attrs(&bio, REQ_OP_READ, 0); - init_completion(&cbdata.complete); + init_completion(&cbdata.complete); - submit_bio(&bio); - process_fd_request(); + submit_bio(&bio); + process_fd_request(); - wait_for_completion(&cbdata.complete); + wait_for_completion(&cbdata.complete); - __free_page(page); + __free_page(page); - return 0; + return 0; } /* revalidate the floppy disk, i.e. trigger format autodetection by reading @@ -4158,58 +4157,58 @@ static int __floppy_read_block_0(struct block_device *bdev, int drive) * geometry formats */ static int floppy_revalidate(struct gendisk *disk) { - int drive = (long)disk->private_data; - int cf; - int res = 0; + int drive = (long)disk->private_data; + int cf; + int res = 0; - if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || - test_bit(FD_VERIFY_BIT, &UDRS->flags) || - test_bit(drive, &fake_change) || - drive_no_geom(drive)) { - if (WARN(atomic_read(&usage_count) == 0, - "VFS: revalidate called on non-open device.\n")) - return -EFAULT; + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || + test_bit(FD_VERIFY_BIT, &UDRS->flags) || + test_bit(drive, &fake_change) || + drive_no_geom(drive)) { + if (WARN(atomic_read(&usage_count) == 0, + "VFS: revalidate called on non-open device.\n")) + return -EFAULT; - res = lock_fdc(drive); - if (res) - return res; - cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || - test_bit(FD_VERIFY_BIT, &UDRS->flags)); - if (!(cf || test_bit(drive, &fake_change) || drive_no_geom(drive))) { - process_fd_request(); /*already done by another thread */ - return 0; - } - UDRS->maxblock = 0; - UDRS->maxtrack = 0; - if (buffer_drive == drive) - buffer_track = -1; - clear_bit(drive, &fake_change); - clear_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); - if (cf) - UDRS->generation++; - if (drive_no_geom(drive)) { - /* auto-sensing */ - res = __floppy_read_block_0(opened_bdev[drive], drive); - } else { - if (cf) - poll_drive(false, FD_RAW_NEED_DISK); - process_fd_request(); - } - } - set_capacity(disk, floppy_sizes[UDRS->fd_device]); - return res; + res = lock_fdc(drive); + if (res) + return res; + cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || + test_bit(FD_VERIFY_BIT, &UDRS->flags)); + if (!(cf || test_bit(drive, &fake_change) || drive_no_geom(drive))) { + process_fd_request(); /*already done by another thread */ + return 0; + } + UDRS->maxblock = 0; + UDRS->maxtrack = 0; + if (buffer_drive == drive) + buffer_track = -1; + clear_bit(drive, &fake_change); + clear_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + if (cf) + UDRS->generation++; + if (drive_no_geom(drive)) { + /* auto-sensing */ + res = __floppy_read_block_0(opened_bdev[drive], drive); + } else { + if (cf) + poll_drive(false, FD_RAW_NEED_DISK); + process_fd_request(); + } + } + set_capacity(disk, floppy_sizes[UDRS->fd_device]); + return res; } static const struct block_device_operations floppy_fops = { - .owner = THIS_MODULE, - .open = floppy_open, - .release = floppy_release, - .ioctl = fd_ioctl, - .getgeo = fd_getgeo, - .check_events = floppy_check_events, - .revalidate_disk = floppy_revalidate, + .owner = THIS_MODULE, + .open = floppy_open, + .release = floppy_release, + .ioctl = fd_ioctl, + .getgeo = fd_getgeo, + .check_events = floppy_check_events, + .revalidate_disk = floppy_revalidate, #ifdef CONFIG_COMPAT - .compat_ioctl = fd_compat_ioctl, + .compat_ioctl = fd_compat_ioctl, #endif }; @@ -4222,669 +4221,668 @@ static const struct block_device_operations floppy_fops = { /* This routine was written by David C. Niemi */ static char __init get_fdc_version(void) { - int r; + int r; - output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */ - if (FDCS->reset) - return FDC_NONE; - r = result(); - if (r <= 0x00) - return FDC_NONE; /* No FDC present ??? */ - if ((r == 1) && (reply_buffer[0] == 0x80)) { - pr_info("FDC %d is an 8272A\n", fdc); - return FDC_8272A; /* 8272a/765 don't know DUMPREGS */ - } - if (r != 10) { - pr_info("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n", - fdc, r); - return FDC_UNKNOWN; - } + output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */ + if (FDCS->reset) + return FDC_NONE; + r = result(); + if (r <= 0x00) + return FDC_NONE; /* No FDC present ??? */ + if ((r == 1) && (reply_buffer[0] == 0x80)) { + pr_info("FDC %d is an 8272A\n", fdc); + return FDC_8272A; /* 8272a/765 don't know DUMPREGS */ + } + if (r != 10) { + pr_info("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n", + fdc, r); + return FDC_UNKNOWN; + } - if (!fdc_configure()) { - pr_info("FDC %d is an 82072\n", fdc); - return FDC_82072; /* 82072 doesn't know CONFIGURE */ - } + if (!fdc_configure()) { + pr_info("FDC %d is an 82072\n", fdc); + return FDC_82072; /* 82072 doesn't know CONFIGURE */ + } - output_byte(FD_PERPENDICULAR); - if (need_more_output() == MORE_OUTPUT) { - output_byte(0); - } else { - pr_info("FDC %d is an 82072A\n", fdc); - return FDC_82072A; /* 82072A as found on Sparcs. */ - } + output_byte(FD_PERPENDICULAR); + if (need_more_output() == MORE_OUTPUT) { + output_byte(0); + } else { + pr_info("FDC %d is an 82072A\n", fdc); + return FDC_82072A; /* 82072A as found on Sparcs. */ + } - output_byte(FD_UNLOCK); - r = result(); - if ((r == 1) && (reply_buffer[0] == 0x80)) { - pr_info("FDC %d is a pre-1991 82077\n", fdc); - return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know - * LOCK/UNLOCK */ - } - if ((r != 1) || (reply_buffer[0] != 0x00)) { - pr_info("FDC %d init: UNLOCK: unexpected return of %d bytes.\n", - fdc, r); - return FDC_UNKNOWN; - } - output_byte(FD_PARTID); - r = result(); - if (r != 1) { - pr_info("FDC %d init: PARTID: unexpected return of %d bytes.\n", - fdc, r); - return FDC_UNKNOWN; - } - if (reply_buffer[0] == 0x80) { - pr_info("FDC %d is a post-1991 82077\n", fdc); - return FDC_82077; /* Revised 82077AA passes all the tests */ - } - switch (reply_buffer[0] >> 5) { - case 0x0: - /* Either a 82078-1 or a 82078SL running at 5Volt */ - pr_info("FDC %d is an 82078.\n", fdc); - return FDC_82078; - case 0x1: - pr_info("FDC %d is a 44pin 82078\n", fdc); - return FDC_82078; - case 0x2: - pr_info("FDC %d is a S82078B\n", fdc); - return FDC_S82078B; - case 0x3: - pr_info("FDC %d is a National Semiconductor PC87306\n", fdc); - return FDC_87306; - default: - pr_info("FDC %d init: 82078 variant with unknown PARTID=%d.\n", - fdc, reply_buffer[0] >> 5); - return FDC_82078_UNKN; - } -} /* get_fdc_version */ + output_byte(FD_UNLOCK); + r = result(); + if ((r == 1) && (reply_buffer[0] == 0x80)) { + pr_info("FDC %d is a pre-1991 82077\n", fdc); + return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know + * LOCK/UNLOCK */ + } + if ((r != 1) || (reply_buffer[0] != 0x00)) { + pr_info("FDC %d init: UNLOCK: unexpected return of %d bytes.\n", + fdc, r); + return FDC_UNKNOWN; + } + output_byte(FD_PARTID); + r = result(); + if (r != 1) { + pr_info("FDC %d init: PARTID: unexpected return of %d bytes.\n", + fdc, r); + return FDC_UNKNOWN; + } + if (reply_buffer[0] == 0x80) { + pr_info("FDC %d is a post-1991 82077\n", fdc); + return FDC_82077; /* Revised 82077AA passes all the tests */ + } + switch (reply_buffer[0] >> 5) { + case 0x0: + /* Either a 82078-1 or a 82078SL running at 5Volt */ + pr_info("FDC %d is an 82078.\n", fdc); + return FDC_82078; + case 0x1: + pr_info("FDC %d is a 44pin 82078\n", fdc); + return FDC_82078; + case 0x2: + pr_info("FDC %d is a S82078B\n", fdc); + return FDC_S82078B; + case 0x3: + pr_info("FDC %d is a National Semiconductor PC87306\n", fdc); + return FDC_87306; + default: + pr_info("FDC %d init: 82078 variant with unknown PARTID=%d.\n", + fdc, reply_buffer[0] >> 5); + return FDC_82078_UNKN; + } +} /* get_fdc_version */ /* lilo configuration */ static void __init floppy_set_flags(int *ints, int param, int param2) { - int i; + int i; - for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) { - if (param) - default_drive_params[i].params.flags |= param2; - else - default_drive_params[i].params.flags &= ~param2; - } - DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param); + for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) { + if (param) + default_drive_params[i].params.flags |= param2; + else + default_drive_params[i].params.flags &= ~param2; + } + DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param); } static void __init daring(int *ints, int param, int param2) { - int i; + int i; - for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) { - if (param) { - default_drive_params[i].params.select_delay = 0; - default_drive_params[i].params.flags |= - FD_SILENT_DCL_CLEAR; - } else { - default_drive_params[i].params.select_delay = - 2 * HZ / 100; - default_drive_params[i].params.flags &= - ~FD_SILENT_DCL_CLEAR; - } - } - DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken"); + for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) { + if (param) { + default_drive_params[i].params.select_delay = 0; + default_drive_params[i].params.flags |= + FD_SILENT_DCL_CLEAR; + } else { + default_drive_params[i].params.select_delay = + 2 * HZ / 100; + default_drive_params[i].params.flags &= + ~FD_SILENT_DCL_CLEAR; + } + } + DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken"); } static void __init set_cmos(int *ints, int dummy, int dummy2) { - int current_drive = 0; + int current_drive = 0; - if (ints[0] != 2) { - DPRINT("wrong number of parameters for CMOS\n"); - return; - } - current_drive = ints[1]; - if (current_drive < 0 || current_drive >= 8) { - DPRINT("bad drive for set_cmos\n"); - return; - } + if (ints[0] != 2) { + DPRINT("wrong number of parameters for CMOS\n"); + return; + } + current_drive = ints[1]; + if (current_drive < 0 || current_drive >= 8) { + DPRINT("bad drive for set_cmos\n"); + return; + } #if N_FDC > 1 - if (current_drive >= 4 && !FDC2) - FDC2 = 0x370; + if (current_drive >= 4 && !FDC2) + FDC2 = 0x370; #endif - DP->cmos = ints[2]; - DPRINT("setting CMOS code to %d\n", ints[2]); + DP->cmos = ints[2]; + DPRINT("setting CMOS code to %d\n", ints[2]); } static struct param_table { - const char *name; - void (*fn) (int *ints, int param, int param2); - int *var; - int def_param; - int param2; + const char *name; + void (*fn) (int *ints, int param, int param2); + int *var; + int def_param; + int param2; } config_params[] __initdata = { - {"allowed_drive_mask", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */ - {"all_drives", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */ - {"asus_pci", NULL, &allowed_drive_mask, 0x33, 0}, - {"irq", NULL, &FLOPPY_IRQ, 6, 0}, - {"dma", NULL, &FLOPPY_DMA, 2, 0}, - {"daring", daring, NULL, 1, 0}, + {"allowed_drive_mask", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */ + {"all_drives", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */ + {"asus_pci", NULL, &allowed_drive_mask, 0x33, 0}, + {"irq", NULL, &FLOPPY_IRQ, 6, 0}, + {"dma", NULL, &FLOPPY_DMA, 2, 0}, + {"daring", daring, NULL, 1, 0}, #if N_FDC > 1 - {"two_fdc", NULL, &FDC2, 0x370, 0}, - {"one_fdc", NULL, &FDC2, 0, 0}, + {"two_fdc", NULL, &FDC2, 0x370, 0}, + {"one_fdc", NULL, &FDC2, 0, 0}, #endif - {"thinkpad", floppy_set_flags, NULL, 1, FD_INVERTED_DCL}, - {"broken_dcl", floppy_set_flags, NULL, 1, FD_BROKEN_DCL}, - {"messages", floppy_set_flags, NULL, 1, FTD_MSG}, - {"silent_dcl_clear", floppy_set_flags, NULL, 1, FD_SILENT_DCL_CLEAR}, - {"debug", floppy_set_flags, NULL, 1, FD_DEBUG}, - {"nodma", NULL, &can_use_virtual_dma, 1, 0}, - {"omnibook", NULL, &can_use_virtual_dma, 1, 0}, - {"yesdma", NULL, &can_use_virtual_dma, 0, 0}, - {"fifo_depth", NULL, &fifo_depth, 0xa, 0}, - {"nofifo", NULL, &no_fifo, 0x20, 0}, - {"usefifo", NULL, &no_fifo, 0, 0}, - {"cmos", set_cmos, NULL, 0, 0}, - {"slow", NULL, &slow_floppy, 1, 0}, - {"unexpected_interrupts", NULL, &print_unex, 1, 0}, - {"no_unexpected_interrupts", NULL, &print_unex, 0, 0}, - {"L40SX", NULL, &print_unex, 0, 0} + {"thinkpad", floppy_set_flags, NULL, 1, FD_INVERTED_DCL}, + {"broken_dcl", floppy_set_flags, NULL, 1, FD_BROKEN_DCL}, + {"messages", floppy_set_flags, NULL, 1, FTD_MSG}, + {"silent_dcl_clear", floppy_set_flags, NULL, 1, FD_SILENT_DCL_CLEAR}, + {"debug", floppy_set_flags, NULL, 1, FD_DEBUG}, + {"nodma", NULL, &can_use_virtual_dma, 1, 0}, + {"omnibook", NULL, &can_use_virtual_dma, 1, 0}, + {"yesdma", NULL, &can_use_virtual_dma, 0, 0}, + {"fifo_depth", NULL, &fifo_depth, 0xa, 0}, + {"nofifo", NULL, &no_fifo, 0x20, 0}, + {"usefifo", NULL, &no_fifo, 0, 0}, + {"cmos", set_cmos, NULL, 0, 0}, + {"slow", NULL, &slow_floppy, 1, 0}, + {"unexpected_interrupts", NULL, &print_unex, 1, 0}, + {"no_unexpected_interrupts", NULL, &print_unex, 0, 0}, + {"L40SX", NULL, &print_unex, 0, 0} - EXTRA_FLOPPY_PARAMS + EXTRA_FLOPPY_PARAMS }; static int __init floppy_setup(char *str) { - int i; - int param; - int ints[11]; + int i; + int param; + int ints[11]; - str = get_options(str, ARRAY_SIZE(ints), ints); - if (str) { - for (i = 0; i < ARRAY_SIZE(config_params); i++) { - if (strcmp(str, config_params[i].name) == 0) { - if (ints[0]) - param = ints[1]; - else - param = config_params[i].def_param; - if (config_params[i].fn) - config_params[i].fn(ints, param, - config_params[i]. - param2); - if (config_params[i].var) { - DPRINT("%s=%d\n", str, param); - *config_params[i].var = param; - } - return 1; - } - } - } - if (str) { - DPRINT("unknown floppy option [%s]\n", str); + str = get_options(str, ARRAY_SIZE(ints), ints); + if (str) { + for (i = 0; i < ARRAY_SIZE(config_params); i++) { + if (strcmp(str, config_params[i].name) == 0) { + if (ints[0]) + param = ints[1]; + else + param = config_params[i].def_param; + if (config_params[i].fn) + config_params[i].fn(ints, param, + config_params[i]. + param2); + if (config_params[i].var) { + DPRINT("%s=%d\n", str, param); + *config_params[i].var = param; + } + return 1; + } + } + } + if (str) { + DPRINT("unknown floppy option [%s]\n", str); - DPRINT("allowed options are:"); - for (i = 0; i < ARRAY_SIZE(config_params); i++) - pr_cont(" %s", config_params[i].name); - pr_cont("\n"); - } else - DPRINT("botched floppy option\n"); - DPRINT("Read Documentation/blockdev/floppy.txt\n"); - return 0; + DPRINT("allowed options are:"); + for (i = 0; i < ARRAY_SIZE(config_params); i++) + pr_cont(" %s", config_params[i].name); + pr_cont("\n"); + } else + DPRINT("botched floppy option\n"); + DPRINT("Read Documentation/blockdev/floppy.txt\n"); + return 0; } static int have_no_fdc = -ENODEV; static ssize_t floppy_cmos_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { - struct platform_device *p = to_platform_device(dev); - int drive; + struct platform_device *p = to_platform_device(dev); + int drive; - drive = p->id; - return sprintf(buf, "%X\n", UDP->cmos); + drive = p->id; + return sprintf(buf, "%X\n", UDP->cmos); } static DEVICE_ATTR(cmos, 0444, floppy_cmos_show, NULL); static struct attribute *floppy_dev_attrs[] = { - &dev_attr_cmos.attr, - NULL + &dev_attr_cmos.attr, + NULL }; ATTRIBUTE_GROUPS(floppy_dev); static void floppy_device_release(struct device *dev) -{ -} +{} static int floppy_resume(struct device *dev) { - int fdc; + int fdc; - for (fdc = 0; fdc < N_FDC; fdc++) - if (FDCS->address != -1) - user_reset_fdc(-1, FD_RESET_ALWAYS, false); + for (fdc = 0; fdc < N_FDC; fdc++) + if (FDCS->address != -1) + user_reset_fdc(-1, FD_RESET_ALWAYS, false); - return 0; + return 0; } static const struct dev_pm_ops floppy_pm_ops = { - .resume = floppy_resume, - .restore = floppy_resume, + .resume = floppy_resume, + .restore = floppy_resume, }; static struct platform_driver floppy_driver = { - .driver = { - .name = "floppy", - .pm = &floppy_pm_ops, - }, + .driver = { + .name = "floppy", + .pm = &floppy_pm_ops, + }, }; static const struct blk_mq_ops floppy_mq_ops = { - .queue_rq = floppy_queue_rq, + .queue_rq = floppy_queue_rq, }; static struct platform_device floppy_device[N_DRIVE]; static bool floppy_available(int drive) { - if (!(allowed_drive_mask & (1 << drive))) - return false; - if (fdc_state[FDC(drive)].version == FDC_NONE) - return false; - return true; + if (!(allowed_drive_mask & (1 << drive))) + return false; + if (fdc_state[FDC(drive)].version == FDC_NONE) + return false; + return true; } static struct kobject *floppy_find(dev_t dev, int *part, void *data) { - int drive = (*part & 3) | ((*part & 0x80) >> 5); - if (drive >= N_DRIVE || !floppy_available(drive)) - return NULL; - if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) - return NULL; - *part = 0; - return get_disk_and_module(disks[drive]); + int drive = (*part & 3) | ((*part & 0x80) >> 5); + if (drive >= N_DRIVE || !floppy_available(drive)) + return NULL; + if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) + return NULL; + *part = 0; + return get_disk_and_module(disks[drive]); } static int __init do_floppy_init(void) { - int i, unit, drive, err; + int i, unit, drive, err; - set_debugt(); - interruptjiffies = resultjiffies = jiffies; + set_debugt(); + interruptjiffies = resultjiffies = jiffies; #if defined(CONFIG_PPC) - if (check_legacy_ioport(FDC1)) - return -ENODEV; + if (check_legacy_ioport(FDC1)) + return -ENODEV; #endif - raw_cmd = NULL; + raw_cmd = NULL; - floppy_wq = alloc_ordered_workqueue("floppy", 0); - if (!floppy_wq) - return -ENOMEM; + floppy_wq = alloc_ordered_workqueue("floppy", 0); + if (!floppy_wq) + return -ENOMEM; - for (drive = 0; drive < N_DRIVE; drive++) { - disks[drive] = alloc_disk(1); - if (!disks[drive]) { - err = -ENOMEM; - goto out_put_disk; - } + for (drive = 0; drive < N_DRIVE; drive++) { + disks[drive] = alloc_disk(1); + if (!disks[drive]) { + err = -ENOMEM; + goto out_put_disk; + } - disks[drive]->queue = blk_mq_init_sq_queue(&tag_sets[drive], - &floppy_mq_ops, 2, - BLK_MQ_F_SHOULD_MERGE); - if (IS_ERR(disks[drive]->queue)) { - err = PTR_ERR(disks[drive]->queue); - disks[drive]->queue = NULL; - goto out_put_disk; - } + disks[drive]->queue = blk_mq_init_sq_queue(&tag_sets[drive], + &floppy_mq_ops, 2, + BLK_MQ_F_SHOULD_MERGE); + if (IS_ERR(disks[drive]->queue)) { + err = PTR_ERR(disks[drive]->queue); + disks[drive]->queue = NULL; + goto out_put_disk; + } - blk_queue_bounce_limit(disks[drive]->queue, BLK_BOUNCE_HIGH); - blk_queue_max_hw_sectors(disks[drive]->queue, 64); - disks[drive]->major = FLOPPY_MAJOR; - disks[drive]->first_minor = TOMINOR(drive); - disks[drive]->fops = &floppy_fops; - disks[drive]->events = DISK_EVENT_MEDIA_CHANGE; - sprintf(disks[drive]->disk_name, "fd%d", drive); + blk_queue_bounce_limit(disks[drive]->queue, BLK_BOUNCE_HIGH); + blk_queue_max_hw_sectors(disks[drive]->queue, 64); + disks[drive]->major = FLOPPY_MAJOR; + disks[drive]->first_minor = TOMINOR(drive); + disks[drive]->fops = &floppy_fops; + disks[drive]->events = DISK_EVENT_MEDIA_CHANGE; + sprintf(disks[drive]->disk_name, "fd%d", drive); - timer_setup(&motor_off_timer[drive], motor_off_callback, 0); - } + timer_setup(&motor_off_timer[drive], motor_off_callback, 0); + } - err = register_blkdev(FLOPPY_MAJOR, "fd"); - if (err) - goto out_put_disk; + err = register_blkdev(FLOPPY_MAJOR, "fd"); + if (err) + goto out_put_disk; - err = platform_driver_register(&floppy_driver); - if (err) - goto out_unreg_blkdev; + err = platform_driver_register(&floppy_driver); + if (err) + goto out_unreg_blkdev; - blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, - floppy_find, NULL, NULL); + blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, + floppy_find, NULL, NULL); - for (i = 0; i < 256; i++) - if (ITYPE(i)) - floppy_sizes[i] = floppy_type[ITYPE(i)].size; - else - floppy_sizes[i] = MAX_DISK_SIZE << 1; + for (i = 0; i < 256; i++) + if (ITYPE(i)) + floppy_sizes[i] = floppy_type[ITYPE(i)].size; + else + floppy_sizes[i] = MAX_DISK_SIZE << 1; - reschedule_timeout(MAXTIMEOUT, "floppy init"); - config_types(); + reschedule_timeout(MAXTIMEOUT, "floppy init"); + config_types(); - for (i = 0; i < N_FDC; i++) { - fdc = i; - memset(FDCS, 0, sizeof(*FDCS)); - FDCS->dtr = -1; - FDCS->dor = 0x4; + for (i = 0; i < N_FDC; i++) { + fdc = i; + memset(FDCS, 0, sizeof(*FDCS)); + FDCS->dtr = -1; + FDCS->dor = 0x4; #if defined(__sparc__) || defined(__mc68000__) - /*sparcs/sun3x don't have a DOR reset which we can fall back on to */ + /*sparcs/sun3x don't have a DOR reset which we can fall back on to */ #ifdef __mc68000__ - if (MACH_IS_SUN3X) + if (MACH_IS_SUN3X) #endif - FDCS->version = FDC_82072A; + FDCS->version = FDC_82072A; #endif - } + } - use_virtual_dma = can_use_virtual_dma & 1; - fdc_state[0].address = FDC1; - if (fdc_state[0].address == -1) { - cancel_delayed_work(&fd_timeout); - err = -ENODEV; - goto out_unreg_region; - } + use_virtual_dma = can_use_virtual_dma & 1; + fdc_state[0].address = FDC1; + if (fdc_state[0].address == -1) { + cancel_delayed_work(&fd_timeout); + err = -ENODEV; + goto out_unreg_region; + } #if N_FDC > 1 - fdc_state[1].address = FDC2; + fdc_state[1].address = FDC2; #endif - fdc = 0; /* reset fdc in case of unexpected interrupt */ - err = floppy_grab_irq_and_dma(); - if (err) { - cancel_delayed_work(&fd_timeout); - err = -EBUSY; - goto out_unreg_region; - } + fdc = 0; /* reset fdc in case of unexpected interrupt */ + err = floppy_grab_irq_and_dma(); + if (err) { + cancel_delayed_work(&fd_timeout); + err = -EBUSY; + goto out_unreg_region; + } - /* initialise drive state */ - for (drive = 0; drive < N_DRIVE; drive++) { - memset(UDRS, 0, sizeof(*UDRS)); - memset(UDRWE, 0, sizeof(*UDRWE)); - set_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags); - set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); - set_bit(FD_VERIFY_BIT, &UDRS->flags); - UDRS->fd_device = -1; - floppy_track_buffer = NULL; - max_buffer_sectors = 0; - } - /* - * Small 10 msec delay to let through any interrupt that - * initialization might have triggered, to not - * confuse detection: - */ - msleep(10); + /* initialise drive state */ + for (drive = 0; drive < N_DRIVE; drive++) { + memset(UDRS, 0, sizeof(*UDRS)); + memset(UDRWE, 0, sizeof(*UDRWE)); + set_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags); + set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); + set_bit(FD_VERIFY_BIT, &UDRS->flags); + UDRS->fd_device = -1; + floppy_track_buffer = NULL; + max_buffer_sectors = 0; + } + /* + * Small 10 msec delay to let through any interrupt that + * initialization might have triggered, to not + * confuse detection: + */ + msleep(10); - for (i = 0; i < N_FDC; i++) { - fdc = i; - FDCS->driver_version = FD_DRIVER_VERSION; - for (unit = 0; unit < 4; unit++) - FDCS->track[unit] = 0; - if (FDCS->address == -1) - continue; - FDCS->rawcmd = 2; - if (user_reset_fdc(-1, FD_RESET_ALWAYS, false)) { - /* free ioports reserved by floppy_grab_irq_and_dma() */ - floppy_release_regions(fdc); - FDCS->address = -1; - FDCS->version = FDC_NONE; - continue; - } - /* Try to determine the floppy controller type */ - FDCS->version = get_fdc_version(); - if (FDCS->version == FDC_NONE) { - /* free ioports reserved by floppy_grab_irq_and_dma() */ - floppy_release_regions(fdc); - FDCS->address = -1; - continue; - } - if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A) - can_use_virtual_dma = 0; + for (i = 0; i < N_FDC; i++) { + fdc = i; + FDCS->driver_version = FD_DRIVER_VERSION; + for (unit = 0; unit < 4; unit++) + FDCS->track[unit] = 0; + if (FDCS->address == -1) + continue; + FDCS->rawcmd = 2; + if (user_reset_fdc(-1, FD_RESET_ALWAYS, false)) { + /* free ioports reserved by floppy_grab_irq_and_dma() */ + floppy_release_regions(fdc); + FDCS->address = -1; + FDCS->version = FDC_NONE; + continue; + } + /* Try to determine the floppy controller type */ + FDCS->version = get_fdc_version(); + if (FDCS->version == FDC_NONE) { + /* free ioports reserved by floppy_grab_irq_and_dma() */ + floppy_release_regions(fdc); + FDCS->address = -1; + continue; + } + if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A) + can_use_virtual_dma = 0; - have_no_fdc = 0; - /* Not all FDCs seem to be able to handle the version command - * properly, so force a reset for the standard FDC clones, - * to avoid interrupt garbage. - */ - user_reset_fdc(-1, FD_RESET_ALWAYS, false); - } - fdc = 0; - cancel_delayed_work(&fd_timeout); - current_drive = 0; - initialized = true; - if (have_no_fdc) { - DPRINT("no floppy controllers found\n"); - err = have_no_fdc; - goto out_release_dma; - } + have_no_fdc = 0; + /* Not all FDCs seem to be able to handle the version command + * properly, so force a reset for the standard FDC clones, + * to avoid interrupt garbage. + */ + user_reset_fdc(-1, FD_RESET_ALWAYS, false); + } + fdc = 0; + cancel_delayed_work(&fd_timeout); + current_drive = 0; + initialized = true; + if (have_no_fdc) { + DPRINT("no floppy controllers found\n"); + err = have_no_fdc; + goto out_release_dma; + } - for (drive = 0; drive < N_DRIVE; drive++) { - if (!floppy_available(drive)) - continue; + for (drive = 0; drive < N_DRIVE; drive++) { + if (!floppy_available(drive)) + continue; - floppy_device[drive].name = floppy_device_name; - floppy_device[drive].id = drive; - floppy_device[drive].dev.release = floppy_device_release; - floppy_device[drive].dev.groups = floppy_dev_groups; + floppy_device[drive].name = floppy_device_name; + floppy_device[drive].id = drive; + floppy_device[drive].dev.release = floppy_device_release; + floppy_device[drive].dev.groups = floppy_dev_groups; - err = platform_device_register(&floppy_device[drive]); - if (err) - goto out_remove_drives; + err = platform_device_register(&floppy_device[drive]); + if (err) + goto out_remove_drives; - /* to be cleaned up... */ - disks[drive]->private_data = (void *)(long)drive; - disks[drive]->flags |= GENHD_FL_REMOVABLE; - device_add_disk(&floppy_device[drive].dev, disks[drive], NULL); - } + /* to be cleaned up... */ + disks[drive]->private_data = (void *)(long)drive; + disks[drive]->flags |= GENHD_FL_REMOVABLE; + device_add_disk(&floppy_device[drive].dev, disks[drive], NULL); + } - return 0; + return 0; out_remove_drives: - while (drive--) { - if (floppy_available(drive)) { - del_gendisk(disks[drive]); - platform_device_unregister(&floppy_device[drive]); - } - } + while (drive--) { + if (floppy_available(drive)) { + del_gendisk(disks[drive]); + platform_device_unregister(&floppy_device[drive]); + } + } out_release_dma: - if (atomic_read(&usage_count)) - floppy_release_irq_and_dma(); + if (atomic_read(&usage_count)) + floppy_release_irq_and_dma(); out_unreg_region: - blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); - platform_driver_unregister(&floppy_driver); + blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); + platform_driver_unregister(&floppy_driver); out_unreg_blkdev: - unregister_blkdev(FLOPPY_MAJOR, "fd"); + unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: - destroy_workqueue(floppy_wq); - for (drive = 0; drive < N_DRIVE; drive++) { - if (!disks[drive]) - break; - if (disks[drive]->queue) { - del_timer_sync(&motor_off_timer[drive]); - blk_cleanup_queue(disks[drive]->queue); - disks[drive]->queue = NULL; - blk_mq_free_tag_set(&tag_sets[drive]); - } - put_disk(disks[drive]); - } - return err; + destroy_workqueue(floppy_wq); + for (drive = 0; drive < N_DRIVE; drive++) { + if (!disks[drive]) + break; + if (disks[drive]->queue) { + del_timer_sync(&motor_off_timer[drive]); + blk_cleanup_queue(disks[drive]->queue); + disks[drive]->queue = NULL; + blk_mq_free_tag_set(&tag_sets[drive]); + } + put_disk(disks[drive]); + } + return err; } #ifndef MODULE static __init void floppy_async_init(void *data, async_cookie_t cookie) { - do_floppy_init(); + do_floppy_init(); } #endif static int __init floppy_init(void) { #ifdef MODULE - return do_floppy_init(); + return do_floppy_init(); #else - /* Don't hold up the bootup by the floppy initialization */ - async_schedule(floppy_async_init, NULL); - return 0; + /* Don't hold up the bootup by the floppy initialization */ + async_schedule(floppy_async_init, NULL); + return 0; #endif } static const struct io_region { - int offset; - int size; + int offset; + int size; } io_regions[] = { - { 2, 1 }, - /* address + 3 is sometimes reserved by pnp bios for motherboard */ - { 4, 2 }, - /* address + 6 is reserved, and may be taken by IDE. - * Unfortunately, Adaptec doesn't know this :-(, */ - { 7, 1 }, + { 2, 1 }, + /* address + 3 is sometimes reserved by pnp bios for motherboard */ + { 4, 2 }, + /* address + 6 is reserved, and may be taken by IDE. + * Unfortunately, Adaptec doesn't know this :-(, */ + { 7, 1 }, }; static void floppy_release_allocated_regions(int fdc, const struct io_region *p) { - while (p != io_regions) { - p--; - release_region(FDCS->address + p->offset, p->size); - } + while (p != io_regions) { + p--; + release_region(FDCS->address + p->offset, p->size); + } } #define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)])) static int floppy_request_regions(int fdc) { - const struct io_region *p; + const struct io_region *p; - for (p = io_regions; p < ARRAY_END(io_regions); p++) { - if (!request_region(FDCS->address + p->offset, - p->size, "floppy")) { - DPRINT("Floppy io-port 0x%04lx in use\n", - FDCS->address + p->offset); - floppy_release_allocated_regions(fdc, p); - return -EBUSY; - } - } - return 0; + for (p = io_regions; p < ARRAY_END(io_regions); p++) { + if (!request_region(FDCS->address + p->offset, + p->size, "floppy")) { + DPRINT("Floppy io-port 0x%04lx in use\n", + FDCS->address + p->offset); + floppy_release_allocated_regions(fdc, p); + return -EBUSY; + } + } + return 0; } static void floppy_release_regions(int fdc) { - floppy_release_allocated_regions(fdc, ARRAY_END(io_regions)); + floppy_release_allocated_regions(fdc, ARRAY_END(io_regions)); } static int floppy_grab_irq_and_dma(void) { - if (atomic_inc_return(&usage_count) > 1) - return 0; + if (atomic_inc_return(&usage_count) > 1) + return 0; - /* - * We might have scheduled a free_irq(), wait it to - * drain first: - */ - flush_workqueue(floppy_wq); + /* + * We might have scheduled a free_irq(), wait it to + * drain first: + */ + flush_workqueue(floppy_wq); - if (fd_request_irq()) { - DPRINT("Unable to grab IRQ%d for the floppy driver\n", - FLOPPY_IRQ); - atomic_dec(&usage_count); - return -1; - } - if (fd_request_dma()) { - DPRINT("Unable to grab DMA%d for the floppy driver\n", - FLOPPY_DMA); - if (can_use_virtual_dma & 2) - use_virtual_dma = can_use_virtual_dma = 1; - if (!(can_use_virtual_dma & 1)) { - fd_free_irq(); - atomic_dec(&usage_count); - return -1; - } - } + if (fd_request_irq()) { + DPRINT("Unable to grab IRQ%d for the floppy driver\n", + FLOPPY_IRQ); + atomic_dec(&usage_count); + return -1; + } + if (fd_request_dma()) { + DPRINT("Unable to grab DMA%d for the floppy driver\n", + FLOPPY_DMA); + if (can_use_virtual_dma & 2) + use_virtual_dma = can_use_virtual_dma = 1; + if (!(can_use_virtual_dma & 1)) { + fd_free_irq(); + atomic_dec(&usage_count); + return -1; + } + } - for (fdc = 0; fdc < N_FDC; fdc++) { - if (FDCS->address != -1) { - if (floppy_request_regions(fdc)) - goto cleanup; - } - } - for (fdc = 0; fdc < N_FDC; fdc++) { - if (FDCS->address != -1) { - reset_fdc_info(1); - fd_outb(FDCS->dor, FD_DOR); - } - } - fdc = 0; - set_dor(0, ~0, 8); /* avoid immediate interrupt */ + for (fdc = 0; fdc < N_FDC; fdc++) { + if (FDCS->address != -1) { + if (floppy_request_regions(fdc)) + goto cleanup; + } + } + for (fdc = 0; fdc < N_FDC; fdc++) { + if (FDCS->address != -1) { + reset_fdc_info(1); + fd_outb(FDCS->dor, FD_DOR); + } + } + fdc = 0; + set_dor(0, ~0, 8); /* avoid immediate interrupt */ - for (fdc = 0; fdc < N_FDC; fdc++) - if (FDCS->address != -1) - fd_outb(FDCS->dor, FD_DOR); - /* - * The driver will try and free resources and relies on us - * to know if they were allocated or not. - */ - fdc = 0; - irqdma_allocated = 1; - return 0; + for (fdc = 0; fdc < N_FDC; fdc++) + if (FDCS->address != -1) + fd_outb(FDCS->dor, FD_DOR); + /* + * The driver will try and free resources and relies on us + * to know if they were allocated or not. + */ + fdc = 0; + irqdma_allocated = 1; + return 0; cleanup: - fd_free_irq(); - fd_free_dma(); - while (--fdc >= 0) - floppy_release_regions(fdc); - atomic_dec(&usage_count); - return -1; + fd_free_irq(); + fd_free_dma(); + while (--fdc >= 0) + floppy_release_regions(fdc); + atomic_dec(&usage_count); + return -1; } static void floppy_release_irq_and_dma(void) { - int old_fdc; + int old_fdc; #ifndef __sparc__ - int drive; + int drive; #endif - long tmpsize; - unsigned long tmpaddr; + long tmpsize; + unsigned long tmpaddr; - if (!atomic_dec_and_test(&usage_count)) - return; + if (!atomic_dec_and_test(&usage_count)) + return; - if (irqdma_allocated) { - fd_disable_dma(); - fd_free_dma(); - fd_free_irq(); - irqdma_allocated = 0; - } - set_dor(0, ~0, 8); + if (irqdma_allocated) { + fd_disable_dma(); + fd_free_dma(); + fd_free_irq(); + irqdma_allocated = 0; + } + set_dor(0, ~0, 8); #if N_FDC > 1 - set_dor(1, ~8, 0); + set_dor(1, ~8, 0); #endif - if (floppy_track_buffer && max_buffer_sectors) { - tmpsize = max_buffer_sectors * 1024; - tmpaddr = (unsigned long)floppy_track_buffer; - floppy_track_buffer = NULL; - max_buffer_sectors = 0; - buffer_min = buffer_max = -1; - fd_dma_mem_free(tmpaddr, tmpsize); - } + if (floppy_track_buffer && max_buffer_sectors) { + tmpsize = max_buffer_sectors * 1024; + tmpaddr = (unsigned long)floppy_track_buffer; + floppy_track_buffer = NULL; + max_buffer_sectors = 0; + buffer_min = buffer_max = -1; + fd_dma_mem_free(tmpaddr, tmpsize); + } #ifndef __sparc__ - for (drive = 0; drive < N_FDC * 4; drive++) - if (timer_pending(motor_off_timer + drive)) - pr_info("motor off timer %d still active\n", drive); + for (drive = 0; drive < N_FDC * 4; drive++) + if (timer_pending(motor_off_timer + drive)) + pr_info("motor off timer %d still active\n", drive); #endif - if (delayed_work_pending(&fd_timeout)) - pr_info("floppy timer still active:%s\n", timeout_message); - if (delayed_work_pending(&fd_timer)) - pr_info("auxiliary floppy timer still active\n"); - if (work_pending(&floppy_work)) - pr_info("work still pending\n"); - old_fdc = fdc; - for (fdc = 0; fdc < N_FDC; fdc++) - if (FDCS->address != -1) - floppy_release_regions(fdc); - fdc = old_fdc; + if (delayed_work_pending(&fd_timeout)) + pr_info("floppy timer still active:%s\n", timeout_message); + if (delayed_work_pending(&fd_timer)) + pr_info("auxiliary floppy timer still active\n"); + if (work_pending(&floppy_work)) + pr_info("work still pending\n"); + old_fdc = fdc; + for (fdc = 0; fdc < N_FDC; fdc++) + if (FDCS->address != -1) + floppy_release_regions(fdc); + fdc = old_fdc; } #ifdef MODULE @@ -4893,68 +4891,68 @@ static char *floppy; static void __init parse_floppy_cfg_string(char *cfg) { - char *ptr; + char *ptr; - while (*cfg) { - ptr = cfg; - while (*cfg && *cfg != ' ' && *cfg != '\t') - cfg++; - if (*cfg) { - *cfg = '\0'; - cfg++; - } - if (*ptr) - floppy_setup(ptr); - } + while (*cfg) { + ptr = cfg; + while (*cfg && *cfg != ' ' && *cfg != '\t') + cfg++; + if (*cfg) { + *cfg = '\0'; + cfg++; + } + if (*ptr) + floppy_setup(ptr); + } } static int __init floppy_module_init(void) { - if (floppy) - parse_floppy_cfg_string(floppy); - return floppy_init(); + if (floppy) + parse_floppy_cfg_string(floppy); + return floppy_init(); } module_init(floppy_module_init); static void __exit floppy_module_exit(void) { - int drive; + int drive; - blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); - unregister_blkdev(FLOPPY_MAJOR, "fd"); - platform_driver_unregister(&floppy_driver); + blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); + unregister_blkdev(FLOPPY_MAJOR, "fd"); + platform_driver_unregister(&floppy_driver); - destroy_workqueue(floppy_wq); + destroy_workqueue(floppy_wq); - for (drive = 0; drive < N_DRIVE; drive++) { - del_timer_sync(&motor_off_timer[drive]); + for (drive = 0; drive < N_DRIVE; drive++) { + del_timer_sync(&motor_off_timer[drive]); - if (floppy_available(drive)) { - del_gendisk(disks[drive]); - platform_device_unregister(&floppy_device[drive]); - } - blk_cleanup_queue(disks[drive]->queue); - blk_mq_free_tag_set(&tag_sets[drive]); + if (floppy_available(drive)) { + del_gendisk(disks[drive]); + platform_device_unregister(&floppy_device[drive]); + } + blk_cleanup_queue(disks[drive]->queue); + blk_mq_free_tag_set(&tag_sets[drive]); - /* - * These disks have not called add_disk(). Don't put down - * queue reference in put_disk(). - */ - if (!(allowed_drive_mask & (1 << drive)) || - fdc_state[FDC(drive)].version == FDC_NONE) - disks[drive]->queue = NULL; + /* + * These disks have not called add_disk(). Don't put down + * queue reference in put_disk(). + */ + if (!(allowed_drive_mask & (1 << drive)) || + fdc_state[FDC(drive)].version == FDC_NONE) + disks[drive]->queue = NULL; - put_disk(disks[drive]); - } + put_disk(disks[drive]); + } - cancel_delayed_work_sync(&fd_timeout); - cancel_delayed_work_sync(&fd_timer); + cancel_delayed_work_sync(&fd_timeout); + cancel_delayed_work_sync(&fd_timer); - if (atomic_read(&usage_count)) - floppy_release_irq_and_dma(); + if (atomic_read(&usage_count)) + floppy_release_irq_and_dma(); - /* eject disk, if any */ - fd_eject(0); + /* eject disk, if any */ + fd_eject(0); } module_exit(floppy_module_exit); @@ -4968,8 +4966,8 @@ MODULE_LICENSE("GPL"); /* This doesn't actually get used other than for module information */ static const struct pnp_device_id floppy_pnpids[] = { - {"PNP0700", 0}, - {} + {"PNP0700", 0}, + {} }; MODULE_DEVICE_TABLE(pnp, floppy_pnpids); diff --git a/test/bug-hunting/cve/CVE-2019-14494/SplashOutputDev.h b/test/bug-hunting/cve/CVE-2019-14494/SplashOutputDev.h index ef95f7068..6ab2c68d3 100644 --- a/test/bug-hunting/cve/CVE-2019-14494/SplashOutputDev.h +++ b/test/bug-hunting/cve/CVE-2019-14494/SplashOutputDev.h @@ -55,127 +55,163 @@ struct SplashTransparencyGroup; // Splash dynamic pattern //------------------------------------------------------------------------ -class SplashFunctionPattern: public SplashPattern { +class SplashFunctionPattern : public SplashPattern { public: - SplashFunctionPattern(SplashColorMode colorMode, GfxState *state, GfxFunctionShading *shading); + SplashFunctionPattern(SplashColorMode colorMode, GfxState *state, GfxFunctionShading *shading); - SplashPattern *copy() override { return new SplashFunctionPattern(colorMode, state, (GfxFunctionShading *) shading); } + SplashPattern *copy() override { + return new SplashFunctionPattern(colorMode, state, (GfxFunctionShading *) shading); + } - ~SplashFunctionPattern(); + ~SplashFunctionPattern(); - bool testPosition(int x, int y) override { return true; } + bool testPosition(int x, int y) override { + return true; + } - bool isStatic() override { return false; } + bool isStatic() override { + return false; + } - bool getColor(int x, int y, SplashColorPtr c) override; + bool getColor(int x, int y, SplashColorPtr c) override; - virtual GfxFunctionShading *getShading() { return shading; } + virtual GfxFunctionShading *getShading() { + return shading; + } - bool isCMYK() override { return gfxMode == csDeviceCMYK; } + bool isCMYK() override { + return gfxMode == csDeviceCMYK; + } protected: - Matrix ictm; - double xMin, yMin, xMax, yMax; - GfxFunctionShading *shading; - GfxState *state; - SplashColorMode colorMode; - GfxColorSpaceMode gfxMode; + Matrix ictm; + double xMin, yMin, xMax, yMax; + GfxFunctionShading *shading; + GfxState *state; + SplashColorMode colorMode; + GfxColorSpaceMode gfxMode; }; -class SplashUnivariatePattern: public SplashPattern { +class SplashUnivariatePattern : public SplashPattern { public: - SplashUnivariatePattern(SplashColorMode colorMode, GfxState *state, GfxUnivariateShading *shading); + SplashUnivariatePattern(SplashColorMode colorMode, GfxState *state, GfxUnivariateShading *shading); - ~SplashUnivariatePattern(); + ~SplashUnivariatePattern(); - bool getColor(int x, int y, SplashColorPtr c) override; + bool getColor(int x, int y, SplashColorPtr c) override; - bool testPosition(int x, int y) override; + bool testPosition(int x, int y) override; - bool isStatic() override { return false; } + bool isStatic() override { + return false; + } - virtual bool getParameter(double xs, double ys, double *t) = 0; + virtual bool getParameter(double xs, double ys, double *t) = 0; - virtual GfxUnivariateShading *getShading() { return shading; } + virtual GfxUnivariateShading *getShading() { + return shading; + } - bool isCMYK() override { return gfxMode == csDeviceCMYK; } + bool isCMYK() override { + return gfxMode == csDeviceCMYK; + } protected: - Matrix ictm; - double t0, t1, dt; - GfxUnivariateShading *shading; - GfxState *state; - SplashColorMode colorMode; - GfxColorSpaceMode gfxMode; + Matrix ictm; + double t0, t1, dt; + GfxUnivariateShading *shading; + GfxState *state; + SplashColorMode colorMode; + GfxColorSpaceMode gfxMode; }; -class SplashAxialPattern: public SplashUnivariatePattern { +class SplashAxialPattern : public SplashUnivariatePattern { public: - SplashAxialPattern(SplashColorMode colorMode, GfxState *state, GfxAxialShading *shading); + SplashAxialPattern(SplashColorMode colorMode, GfxState *state, GfxAxialShading *shading); - SplashPattern *copy() override { return new SplashAxialPattern(colorMode, state, (GfxAxialShading *) shading); } + SplashPattern *copy() override { + return new SplashAxialPattern(colorMode, state, (GfxAxialShading *) shading); + } - ~SplashAxialPattern(); + ~SplashAxialPattern(); - bool getParameter(double xs, double ys, double *t) override; + bool getParameter(double xs, double ys, double *t) override; private: - double x0, y0, x1, y1; - double dx, dy, mul; + double x0, y0, x1, y1; + double dx, dy, mul; }; // see GfxState.h, GfxGouraudTriangleShading -class SplashGouraudPattern: public SplashGouraudColor { +class SplashGouraudPattern : public SplashGouraudColor { public: - SplashGouraudPattern(bool bDirectColorTranslation, GfxState *state, GfxGouraudTriangleShading *shading); + SplashGouraudPattern(bool bDirectColorTranslation, GfxState *state, GfxGouraudTriangleShading *shading); - SplashPattern *copy() override { return new SplashGouraudPattern(bDirectColorTranslation, state, shading); } + SplashPattern *copy() override { + return new SplashGouraudPattern(bDirectColorTranslation, state, shading); + } - ~SplashGouraudPattern(); + ~SplashGouraudPattern(); - bool getColor(int x, int y, SplashColorPtr c) override { return false; } + bool getColor(int x, int y, SplashColorPtr c) override { + return false; + } - bool testPosition(int x, int y) override { return false; } + bool testPosition(int x, int y) override { + return false; + } - bool isStatic() override { return false; } + bool isStatic() override { + return false; + } - bool isCMYK() override { return gfxMode == csDeviceCMYK; } + bool isCMYK() override { + return gfxMode == csDeviceCMYK; + } - bool isParameterized() override { return shading->isParameterized(); } - int getNTriangles() override { return shading->getNTriangles(); } - void getTriangle(int i, double *x0, double *y0, double *color0, - double *x1, double *y1, double *color1, - double *x2, double *y2, double *color2) override - { shading->getTriangle(i, x0, y0, color0, x1, y1, color1, x2, y2, color2); } + bool isParameterized() override { + return shading->isParameterized(); + } + int getNTriangles() override { + return shading->getNTriangles(); + } + void getTriangle(int i, double *x0, double *y0, double *color0, + double *x1, double *y1, double *color1, + double *x2, double *y2, double *color2) override + { + shading->getTriangle(i, x0, y0, color0, x1, y1, color1, x2, y2, color2); + } - void getParameterizedColor(double t, SplashColorMode mode, SplashColorPtr c) override; + void getParameterizedColor(double t, SplashColorMode mode, SplashColorPtr c) override; private: - GfxGouraudTriangleShading *shading; - GfxState *state; - bool bDirectColorTranslation; - GfxColorSpaceMode gfxMode; + GfxGouraudTriangleShading *shading; + GfxState *state; + bool bDirectColorTranslation; + GfxColorSpaceMode gfxMode; }; // see GfxState.h, GfxRadialShading -class SplashRadialPattern: public SplashUnivariatePattern { +class SplashRadialPattern : public SplashUnivariatePattern { public: - SplashRadialPattern(SplashColorMode colorMode, GfxState *state, GfxRadialShading *shading); + SplashRadialPattern(SplashColorMode colorMode, GfxState *state, GfxRadialShading *shading); - SplashPattern *copy() override { return new SplashRadialPattern(colorMode, state, (GfxRadialShading *) shading); } + SplashPattern *copy() override { + return new SplashRadialPattern(colorMode, state, (GfxRadialShading *) shading); + } - ~SplashRadialPattern(); + ~SplashRadialPattern(); - bool getParameter(double xs, double ys, double *t) override; + bool getParameter(double xs, double ys, double *t) override; private: - double x0, y0, r0, dx, dy, dr; - double a, inva; + double x0, y0, r0, dx, dy, dr; + double a, inva; }; //------------------------------------------------------------------------ @@ -187,281 +223,311 @@ private: // SplashOutputDev //------------------------------------------------------------------------ -class SplashOutputDev: public OutputDev { +class SplashOutputDev : public OutputDev { public: - // Constructor. - SplashOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, - bool reverseVideoA, SplashColorPtr paperColorA, - bool bitmapTopDownA = true, - SplashThinLineMode thinLineMode = splashThinLineDefault, - bool overprintPreviewA = globalParams->getOverprintPreview()); + // Constructor. + SplashOutputDev(SplashColorMode colorModeA, int bitmapRowPadA, + bool reverseVideoA, SplashColorPtr paperColorA, + bool bitmapTopDownA = true, + SplashThinLineMode thinLineMode = splashThinLineDefault, + bool overprintPreviewA = globalParams->getOverprintPreview()); - // Destructor. - ~SplashOutputDev(); + // Destructor. + ~SplashOutputDev(); - //----- get info about output device + //----- get info about output device - // Does this device use tilingPatternFill()? If this returns false, - // tiling pattern fills will be reduced to a series of other drawing - // operations. - bool useTilingPatternFill() override { return true; } + // Does this device use tilingPatternFill()? If this returns false, + // tiling pattern fills will be reduced to a series of other drawing + // operations. + bool useTilingPatternFill() override { + return true; + } - // Does this device use functionShadedFill(), axialShadedFill(), and - // radialShadedFill()? If this returns false, these shaded fills - // will be reduced to a series of other drawing operations. - bool useShadedFills(int type) override - { return (type >= 1 && type <= 5) ? true : false; } + // Does this device use functionShadedFill(), axialShadedFill(), and + // radialShadedFill()? If this returns false, these shaded fills + // will be reduced to a series of other drawing operations. + bool useShadedFills(int type) override + { + return (type >= 1 && type <= 5) ? true : false; + } - // Does this device use upside-down coordinates? - // (Upside-down means (0,0) is the top left corner of the page.) - bool upsideDown() override { return bitmapTopDown ^ bitmapUpsideDown; } + // Does this device use upside-down coordinates? + // (Upside-down means (0,0) is the top left corner of the page.) + bool upsideDown() override { + return bitmapTopDown ^ bitmapUpsideDown; + } - // Does this device use drawChar() or drawString()? - bool useDrawChar() override { return true; } + // Does this device use drawChar() or drawString()? + bool useDrawChar() override { + return true; + } - // Does this device use beginType3Char/endType3Char? Otherwise, - // text in Type 3 fonts will be drawn with drawChar/drawString. - bool interpretType3Chars() override { return true; } + // Does this device use beginType3Char/endType3Char? Otherwise, + // text in Type 3 fonts will be drawn with drawChar/drawString. + bool interpretType3Chars() override { + return true; + } - //----- initialization and control + //----- initialization and control - // Start a page. - void startPage(int pageNum, GfxState *state, XRef *xref) override; + // Start a page. + void startPage(int pageNum, GfxState *state, XRef *xref) override; - // End a page. - void endPage() override; + // End a page. + void endPage() override; - //----- save/restore graphics state - void saveState(GfxState *state) override; - void restoreState(GfxState *state) override; + //----- save/restore graphics state + void saveState(GfxState *state) override; + void restoreState(GfxState *state) override; - //----- update graphics state - void updateAll(GfxState *state) override; - void updateCTM(GfxState *state, double m11, double m12, - double m21, double m22, double m31, double m32) override; - void updateLineDash(GfxState *state) override; - void updateFlatness(GfxState *state) override; - void updateLineJoin(GfxState *state) override; - void updateLineCap(GfxState *state) override; - void updateMiterLimit(GfxState *state) override; - void updateLineWidth(GfxState *state) override; - void updateStrokeAdjust(GfxState *state) override; - void updateFillColorSpace(GfxState *state) override; - void updateStrokeColorSpace(GfxState *state) override; - void updateFillColor(GfxState *state) override; - void updateStrokeColor(GfxState *state) override; - void updateBlendMode(GfxState *state) override; - void updateFillOpacity(GfxState *state) override; - void updateStrokeOpacity(GfxState *state) override; - void updatePatternOpacity(GfxState *state) override; - void clearPatternOpacity(GfxState *state) override; - void updateFillOverprint(GfxState *state) override; - void updateStrokeOverprint(GfxState *state) override; - void updateOverprintMode(GfxState *state) override; - void updateTransfer(GfxState *state) override; + //----- update graphics state + void updateAll(GfxState *state) override; + void updateCTM(GfxState *state, double m11, double m12, + double m21, double m22, double m31, double m32) override; + void updateLineDash(GfxState *state) override; + void updateFlatness(GfxState *state) override; + void updateLineJoin(GfxState *state) override; + void updateLineCap(GfxState *state) override; + void updateMiterLimit(GfxState *state) override; + void updateLineWidth(GfxState *state) override; + void updateStrokeAdjust(GfxState *state) override; + void updateFillColorSpace(GfxState *state) override; + void updateStrokeColorSpace(GfxState *state) override; + void updateFillColor(GfxState *state) override; + void updateStrokeColor(GfxState *state) override; + void updateBlendMode(GfxState *state) override; + void updateFillOpacity(GfxState *state) override; + void updateStrokeOpacity(GfxState *state) override; + void updatePatternOpacity(GfxState *state) override; + void clearPatternOpacity(GfxState *state) override; + void updateFillOverprint(GfxState *state) override; + void updateStrokeOverprint(GfxState *state) override; + void updateOverprintMode(GfxState *state) override; + void updateTransfer(GfxState *state) override; - //----- update text state - void updateFont(GfxState *state) override; + //----- update text state + void updateFont(GfxState *state) override; - //----- path painting - void stroke(GfxState *state) override; - void fill(GfxState *state) override; - void eoFill(GfxState *state) override; - bool tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *catalog, Object *str, - const double *pmat, int paintType, int tilingType, Dict *resDict, - const double *mat, const double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep) override; - bool functionShadedFill(GfxState *state, GfxFunctionShading *shading) override; - bool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) override; - bool radialShadedFill(GfxState *state, GfxRadialShading *shading, double tMin, double tMax) override; - bool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) override; + //----- path painting + void stroke(GfxState *state) override; + void fill(GfxState *state) override; + void eoFill(GfxState *state) override; + bool tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *catalog, Object *str, + const double *pmat, int paintType, int tilingType, Dict *resDict, + const double *mat, const double *bbox, + int x0, int y0, int x1, int y1, + double xStep, double yStep) override; + bool functionShadedFill(GfxState *state, GfxFunctionShading *shading) override; + bool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) override; + bool radialShadedFill(GfxState *state, GfxRadialShading *shading, double tMin, double tMax) override; + bool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) override; - //----- path clipping - void clip(GfxState *state) override; - void eoClip(GfxState *state) override; - void clipToStrokePath(GfxState *state) override; + //----- path clipping + void clip(GfxState *state) override; + void eoClip(GfxState *state) override; + void clipToStrokePath(GfxState *state) override; - //----- text drawing - void drawChar(GfxState *state, double x, double y, - double dx, double dy, - double originX, double originY, - CharCode code, int nBytes, Unicode *u, int uLen) override; - bool beginType3Char(GfxState *state, double x, double y, - double dx, double dy, - CharCode code, Unicode *u, int uLen) override; - void endType3Char(GfxState *state) override; - void beginTextObject(GfxState *state) override; - void endTextObject(GfxState *state) override; + //----- text drawing + void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, Unicode *u, int uLen) override; + bool beginType3Char(GfxState *state, double x, double y, + double dx, double dy, + CharCode code, Unicode *u, int uLen) override; + void endType3Char(GfxState *state) override; + void beginTextObject(GfxState *state) override; + void endTextObject(GfxState *state) override; - //----- image drawing - void drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool interpolate, bool inlineImg) override; - void setSoftMaskFromImageMask(GfxState *state, - Object *ref, Stream *str, - int width, int height, bool invert, - bool inlineImg, double *baseMatrix) override; - void unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix) override; - void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - bool interpolate, int *maskColors, bool inlineImg) override; - void drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, int maskWidth, int maskHeight, - bool maskInvert, bool maskInterpolate) override; - void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap, - bool maskInterpolate) override; + //----- image drawing + void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, bool invert, + bool interpolate, bool inlineImg) override; + void setSoftMaskFromImageMask(GfxState *state, + Object *ref, Stream *str, + int width, int height, bool invert, + bool inlineImg, double *baseMatrix) override; + void unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix) override; + void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + bool interpolate, int *maskColors, bool inlineImg) override; + void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + bool interpolate, + Stream *maskStr, int maskWidth, int maskHeight, + bool maskInvert, bool maskInterpolate) override; + void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + bool interpolate, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + bool maskInterpolate) override; - //----- Type 3 font operators - void type3D0(GfxState *state, double wx, double wy) override; - void type3D1(GfxState *state, double wx, double wy, - double llx, double lly, double urx, double ury) override; + //----- Type 3 font operators + void type3D0(GfxState *state, double wx, double wy) override; + void type3D1(GfxState *state, double wx, double wy, + double llx, double lly, double urx, double ury) override; - //----- transparency groups and soft masks - bool checkTransparencyGroup(GfxState *state, bool knockout) override; - void beginTransparencyGroup(GfxState *state, const double *bbox, - GfxColorSpace *blendingColorSpace, - bool isolated, bool knockout, - bool forSoftMask) override; - void endTransparencyGroup(GfxState *state) override; - void paintTransparencyGroup(GfxState *state, const double *bbox) override; - void setSoftMask(GfxState *state, const double *bbox, bool alpha, - Function *transferFunc, GfxColor *backdropColor) override; - void clearSoftMask(GfxState *state) override; + //----- transparency groups and soft masks + bool checkTransparencyGroup(GfxState *state, bool knockout) override; + void beginTransparencyGroup(GfxState *state, const double *bbox, + GfxColorSpace *blendingColorSpace, + bool isolated, bool knockout, + bool forSoftMask) override; + void endTransparencyGroup(GfxState *state) override; + void paintTransparencyGroup(GfxState *state, const double *bbox) override; + void setSoftMask(GfxState *state, const double *bbox, bool alpha, + Function *transferFunc, GfxColor *backdropColor) override; + void clearSoftMask(GfxState *state) override; - //----- special access + //----- special access - // Called to indicate that a new PDF document has been loaded. - void startDoc(PDFDoc *docA); - - void setPaperColor(SplashColorPtr paperColorA); + // Called to indicate that a new PDF document has been loaded. + void startDoc(PDFDoc *docA); - bool isReverseVideo() { return reverseVideo; } - void setReverseVideo(bool reverseVideoA) { reverseVideo = reverseVideoA; } + void setPaperColor(SplashColorPtr paperColorA); - // Get the bitmap and its size. - SplashBitmap *getBitmap() { return bitmap; } - int getBitmapWidth(); - int getBitmapHeight(); + bool isReverseVideo() { + return reverseVideo; + } + void setReverseVideo(bool reverseVideoA) { + reverseVideo = reverseVideoA; + } - // Returns the last rasterized bitmap, transferring ownership to the - // caller. - SplashBitmap *takeBitmap(); + // Get the bitmap and its size. + SplashBitmap *getBitmap() { + return bitmap; + } + int getBitmapWidth(); + int getBitmapHeight(); - // Set this flag to true to generate an upside-down bitmap (useful - // for Windows BMP files). - void setBitmapUpsideDown(bool f) { bitmapUpsideDown = f; } + // Returns the last rasterized bitmap, transferring ownership to the + // caller. + SplashBitmap *takeBitmap(); - // Get the Splash object. - Splash *getSplash() { return splash; } + // Set this flag to true to generate an upside-down bitmap (useful + // for Windows BMP files). + void setBitmapUpsideDown(bool f) { + bitmapUpsideDown = f; + } - // Get the modified region. - void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax); + // Get the Splash object. + Splash *getSplash() { + return splash; + } - // Clear the modified region. - void clearModRegion(); + // Get the modified region. + void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax); - SplashFont *getCurrentFont() { return font; } + // Clear the modified region. + void clearModRegion(); - // If is true, don't draw horizontal text. - // If is true, don't draw rotated (non-horizontal) text. - void setSkipText(bool skipHorizTextA, bool skipRotatedTextA) - { skipHorizText = skipHorizTextA; skipRotatedText = skipRotatedTextA; } + SplashFont *getCurrentFont() { + return font; + } - int getNestCount() { return nestCount; } + // If is true, don't draw horizontal text. + // If is true, don't draw rotated (non-horizontal) text. + void setSkipText(bool skipHorizTextA, bool skipRotatedTextA) + { + skipHorizText = skipHorizTextA; skipRotatedText = skipRotatedTextA; + } + + int getNestCount() { + return nestCount; + } #if 1 //~tmp: turn off anti-aliasing temporarily - bool getVectorAntialias() override; - void setVectorAntialias(bool vaa) override; + bool getVectorAntialias() override; + void setVectorAntialias(bool vaa) override; #endif - bool getFontAntialias() { return fontAntialias; } - void setFontAntialias(bool anti) { fontAntialias = anti; } + bool getFontAntialias() { + return fontAntialias; + } + void setFontAntialias(bool anti) { + fontAntialias = anti; + } - void setFreeTypeHinting(bool enable, bool enableSlightHinting); + void setFreeTypeHinting(bool enable, bool enableSlightHinting); protected: - void doUpdateFont(GfxState *state); + void doUpdateFont(GfxState *state); private: - bool univariateShadedFill(GfxState *state, SplashUnivariatePattern *pattern, double tMin, double tMax); + bool univariateShadedFill(GfxState *state, SplashUnivariatePattern *pattern, double tMin, double tMax); - void setupScreenParams(double hDPI, double vDPI); - SplashPattern *getColor(GfxGray gray); - SplashPattern *getColor(GfxRGB *rgb); + void setupScreenParams(double hDPI, double vDPI); + SplashPattern *getColor(GfxGray gray); + SplashPattern *getColor(GfxRGB *rgb); #ifdef SPLASH_CMYK - SplashPattern *getColor(GfxCMYK *cmyk); - SplashPattern *getColor(GfxColor *deviceN); + SplashPattern *getColor(GfxCMYK *cmyk); + SplashPattern *getColor(GfxColor *deviceN); #endif - static void getMatteColor( SplashColorMode colorMode, GfxImageColorMap *colorMap, const GfxColor * matteColor, SplashColor splashMatteColor); - void setOverprintMask(GfxColorSpace *colorSpace, bool overprintFlag, - int overprintMode, const GfxColor *singleColor, bool grayIndexed = false); - SplashPath convertPath(GfxState *state, GfxPath *path, - bool dropEmptySubpaths); - void drawType3Glyph(GfxState *state, T3FontCache *t3Font, - T3FontCacheTag *tag, unsigned char *data); + static void getMatteColor( SplashColorMode colorMode, GfxImageColorMap *colorMap, const GfxColor * matteColor, SplashColor splashMatteColor); + void setOverprintMask(GfxColorSpace *colorSpace, bool overprintFlag, + int overprintMode, const GfxColor *singleColor, bool grayIndexed = false); + SplashPath convertPath(GfxState *state, GfxPath *path, + bool dropEmptySubpaths); + void drawType3Glyph(GfxState *state, T3FontCache *t3Font, + T3FontCacheTag *tag, unsigned char *data); #ifdef USE_CMS - bool useIccImageSrc(void *data); - static void iccTransform(void *data, SplashBitmap *bitmap); - static bool iccImageSrc(void *data, SplashColorPtr colorLine, - unsigned char *alphaLine); + bool useIccImageSrc(void *data); + static void iccTransform(void *data, SplashBitmap *bitmap); + static bool iccImageSrc(void *data, SplashColorPtr colorLine, + unsigned char *alphaLine); #endif - static bool imageMaskSrc(void *data, SplashColorPtr line); - static bool imageSrc(void *data, SplashColorPtr colorLine, - unsigned char *alphaLine); - static bool alphaImageSrc(void *data, SplashColorPtr line, - unsigned char *alphaLine); - static bool maskedImageSrc(void *data, SplashColorPtr line, - unsigned char *alphaLine); - static bool tilingBitmapSrc(void *data, SplashColorPtr line, - unsigned char *alphaLine); + static bool imageMaskSrc(void *data, SplashColorPtr line); + static bool imageSrc(void *data, SplashColorPtr colorLine, + unsigned char *alphaLine); + static bool alphaImageSrc(void *data, SplashColorPtr line, + unsigned char *alphaLine); + static bool maskedImageSrc(void *data, SplashColorPtr line, + unsigned char *alphaLine); + static bool tilingBitmapSrc(void *data, SplashColorPtr line, + unsigned char *alphaLine); - bool keepAlphaChannel; // don't fill with paper color, keep alpha channel + bool keepAlphaChannel; // don't fill with paper color, keep alpha channel - SplashColorMode colorMode; - int bitmapRowPad; - bool bitmapTopDown; - bool bitmapUpsideDown; - bool fontAntialias; - bool vectorAntialias; - bool overprintPreview; - bool enableFreeTypeHinting; - bool enableSlightHinting; - bool reverseVideo; // reverse video mode - SplashColor paperColor; // paper color - SplashScreenParams screenParams; - bool skipHorizText; - bool skipRotatedText; + SplashColorMode colorMode; + int bitmapRowPad; + bool bitmapTopDown; + bool bitmapUpsideDown; + bool fontAntialias; + bool vectorAntialias; + bool overprintPreview; + bool enableFreeTypeHinting; + bool enableSlightHinting; + bool reverseVideo; // reverse video mode + SplashColor paperColor; // paper color + SplashScreenParams screenParams; + bool skipHorizText; + bool skipRotatedText; - PDFDoc *doc; // the current document - XRef *xref; // the xref of the current document + PDFDoc *doc; // the current document + XRef *xref; // the xref of the current document - SplashBitmap *bitmap; - Splash *splash; - SplashFontEngine *fontEngine; + SplashBitmap *bitmap; + Splash *splash; + SplashFontEngine *fontEngine; - T3FontCache * // Type 3 font cache - t3FontCache[splashOutT3FontCacheSize]; - int nT3Fonts; // number of valid entries in t3FontCache - T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack + T3FontCache * // Type 3 font cache + t3FontCache[splashOutT3FontCacheSize]; + int nT3Fonts; // number of valid entries in t3FontCache + T3GlyphStack *t3GlyphStack; // Type 3 glyph context stack - SplashFont *font; // current font - bool needFontUpdate; // set when the font needs to be updated - SplashPath *textClipPath; // clipping path built with text object + SplashFont *font; // current font + bool needFontUpdate; // set when the font needs to be updated + SplashPath *textClipPath; // clipping path built with text object - SplashTransparencyGroup * // transparency group stack - transpGroupStack; - int nestCount; + SplashTransparencyGroup * // transparency group stack + transpGroupStack; + int nestCount; }; #endif diff --git a/test/bug-hunting/cve/CVE-2019-14981/feature.c b/test/bug-hunting/cve/CVE-2019-14981/feature.c index a0205ba15..e68f37e21 100644 --- a/test/bug-hunting/cve/CVE-2019-14981/feature.c +++ b/test/bug-hunting/cve/CVE-2019-14981/feature.c @@ -1,45 +1,45 @@ /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% FFFFF EEEEE AAA TTTTT U U RRRR EEEEE % -% F E A A T U U R R E % -% FFF EEE AAAAA T U U RRRR EEE % -% F E A A T U U R R E % -% F EEEEE A A T UUU R R EEEEE % -% % -% % -% MagickCore Image Feature Methods % -% % -% Software Design % -% Cristy % -% July 1992 % -% % -% % -% Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % -% dedicated to making software imaging solutions freely available. % -% % -% You may not use this file except in compliance with the License. You may % -% obtain a copy of the License at % -% % -% https://imagemagick.org/script/license.php % -% % -% Unless required by applicable law or agreed to in writing, software % -% distributed under the License is distributed on an "AS IS" BASIS, % -% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % -% See the License for the specific language governing permissions and % -% limitations under the License. % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% -% -*/ - + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % FFFFF EEEEE AAA TTTTT U U RRRR EEEEE % + % F E A A T U U R R E % + % FFF EEE AAAAA T U U RRRR EEE % + % F E A A T U U R R E % + % F EEEEE A A T UUU R R EEEEE % + % % + % % + % MagickCore Image Feature Methods % + % % + % Software Design % + % Cristy % + % July 1992 % + % % + % % + % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % + % dedicated to making software imaging solutions freely available. % + % % + % You may not use this file except in compliance with the License. You may % + % obtain a copy of the License at % + % % + % https://imagemagick.org/script/license.php % + % % + % Unless required by applicable law or agreed to in writing, software % + % distributed under the License is distributed on an "AS IS" BASIS, % + % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % + % See the License for the specific language governing permissions and % + % limitations under the License. % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % + % + */ + /* - Include declarations. -*/ + Include declarations. + */ #include "MagickCore/studio.h" #include "MagickCore/animate.h" #include "MagickCore/artifact.h" @@ -93,548 +93,548 @@ #include "MagickCore/timer.h" #include "MagickCore/utility.h" #include "MagickCore/version.h" - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% C a n n y E d g e I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% CannyEdgeImage() uses a multi-stage algorithm to detect a wide range of -% edges in images. -% -% The format of the CannyEdgeImage method is: -% -% Image *CannyEdgeImage(const Image *image,const double radius, -% const double sigma,const double lower_percent, -% const double upper_percent,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image. -% -% o radius: the radius of the gaussian smoothing filter. -% -% o sigma: the sigma of the gaussian smoothing filter. -% -% o lower_percent: percentage of edge pixels in the lower threshold. -% -% o upper_percent: percentage of edge pixels in the upper threshold. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % C a n n y E d g e I m a g e % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % CannyEdgeImage() uses a multi-stage algorithm to detect a wide range of + % edges in images. + % + % The format of the CannyEdgeImage method is: + % + % Image *CannyEdgeImage(const Image *image,const double radius, + % const double sigma,const double lower_percent, + % const double upper_percent,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image. + % + % o radius: the radius of the gaussian smoothing filter. + % + % o sigma: the sigma of the gaussian smoothing filter. + % + % o lower_percent: percentage of edge pixels in the lower threshold. + % + % o upper_percent: percentage of edge pixels in the upper threshold. + % + % o exception: return any errors or warnings in this structure. + % + */ typedef struct _CannyInfo { - double - magnitude, - intensity; + double + magnitude, + intensity; - int - orientation; + int + orientation; - ssize_t - x, - y; + ssize_t + x, + y; } CannyInfo; static inline MagickBooleanType IsAuthenticPixel(const Image *image, - const ssize_t x,const ssize_t y) + const ssize_t x,const ssize_t y) { - if ((x < 0) || (x >= (ssize_t) image->columns)) - return(MagickFalse); - if ((y < 0) || (y >= (ssize_t) image->rows)) - return(MagickFalse); - return(MagickTrue); + if ((x < 0) || (x >= (ssize_t) image->columns)) + return(MagickFalse); + if ((y < 0) || (y >= (ssize_t) image->rows)) + return(MagickFalse); + return(MagickTrue); } static MagickBooleanType TraceEdges(Image *edge_image,CacheView *edge_view, - MatrixInfo *canny_cache,const ssize_t x,const ssize_t y, - const double lower_threshold,ExceptionInfo *exception) + MatrixInfo *canny_cache,const ssize_t x,const ssize_t y, + const double lower_threshold,ExceptionInfo *exception) { - CannyInfo - edge, - pixel; + CannyInfo + edge, + pixel; - MagickBooleanType - status; + MagickBooleanType + status; - register Quantum + register Quantum *q; - register ssize_t - i; + register ssize_t + i; - q=GetCacheViewAuthenticPixels(edge_view,x,y,1,1,exception); - if (q == (Quantum *) NULL) - return(MagickFalse); - *q=QuantumRange; - status=SyncCacheViewAuthenticPixels(edge_view,exception); - if (status == MagickFalse) - return(MagickFalse); - if (GetMatrixElement(canny_cache,0,0,&edge) == MagickFalse) - return(MagickFalse); - edge.x=x; - edge.y=y; - if (SetMatrixElement(canny_cache,0,0,&edge) == MagickFalse) - return(MagickFalse); - for (i=1; i != 0; ) - { - ssize_t - v; - - i--; - status=GetMatrixElement(canny_cache,i,0,&edge); + q=GetCacheViewAuthenticPixels(edge_view,x,y,1,1,exception); + if (q == (Quantum *) NULL) + return(MagickFalse); + *q=QuantumRange; + status=SyncCacheViewAuthenticPixels(edge_view,exception); if (status == MagickFalse) - return(MagickFalse); - for (v=(-1); v <= 1; v++) + return(MagickFalse); + if (GetMatrixElement(canny_cache,0,0,&edge) == MagickFalse) + return(MagickFalse); + edge.x=x; + edge.y=y; + if (SetMatrixElement(canny_cache,0,0,&edge) == MagickFalse) + return(MagickFalse); + for (i=1; i != 0;) { - ssize_t - u; + ssize_t + v; - for (u=(-1); u <= 1; u++) - { - if ((u == 0) && (v == 0)) - continue; - if (IsAuthenticPixel(edge_image,edge.x+u,edge.y+v) == MagickFalse) - continue; - /* - Not an edge if gradient value is below the lower threshold. - */ - q=GetCacheViewAuthenticPixels(edge_view,edge.x+u,edge.y+v,1,1, - exception); - if (q == (Quantum *) NULL) - return(MagickFalse); - status=GetMatrixElement(canny_cache,edge.x+u,edge.y+v,&pixel); + i--; + status=GetMatrixElement(canny_cache,i,0,&edge); if (status == MagickFalse) - return(MagickFalse); - if ((GetPixelIntensity(edge_image,q) == 0.0) && - (pixel.intensity >= lower_threshold)) - { - *q=QuantumRange; - status=SyncCacheViewAuthenticPixels(edge_view,exception); - if (status == MagickFalse) - return(MagickFalse); - edge.x+=u; - edge.y+=v; - status=SetMatrixElement(canny_cache,i,0,&edge); - if (status == MagickFalse) - return(MagickFalse); - i++; - } - } + return(MagickFalse); + for (v=(-1); v <= 1; v++) + { + ssize_t + u; + + for (u=(-1); u <= 1; u++) + { + if ((u == 0) && (v == 0)) + continue; + if (IsAuthenticPixel(edge_image,edge.x+u,edge.y+v) == MagickFalse) + continue; + /* + Not an edge if gradient value is below the lower threshold. + */ + q=GetCacheViewAuthenticPixels(edge_view,edge.x+u,edge.y+v,1,1, + exception); + if (q == (Quantum *) NULL) + return(MagickFalse); + status=GetMatrixElement(canny_cache,edge.x+u,edge.y+v,&pixel); + if (status == MagickFalse) + return(MagickFalse); + if ((GetPixelIntensity(edge_image,q) == 0.0) && + (pixel.intensity >= lower_threshold)) + { + *q=QuantumRange; + status=SyncCacheViewAuthenticPixels(edge_view,exception); + if (status == MagickFalse) + return(MagickFalse); + edge.x+=u; + edge.y+=v; + status=SetMatrixElement(canny_cache,i,0,&edge); + if (status == MagickFalse) + return(MagickFalse); + i++; + } + } + } } - } - return(MagickTrue); + return(MagickTrue); } MagickExport Image *CannyEdgeImage(const Image *image,const double radius, - const double sigma,const double lower_percent,const double upper_percent, - ExceptionInfo *exception) + const double sigma,const double lower_percent,const double upper_percent, + ExceptionInfo *exception) { #define CannyEdgeImageTag "CannyEdge/Image" - CacheView + CacheView *edge_view; - CannyInfo - element; + CannyInfo + element; - char - geometry[MagickPathExtent]; + char + geometry[MagickPathExtent]; - double - lower_threshold, - max, - min, - upper_threshold; + double + lower_threshold, + max, + min, + upper_threshold; - Image + Image *edge_image; - KernelInfo + KernelInfo *kernel_info; - MagickBooleanType - status; + MagickBooleanType + status; - MagickOffsetType - progress; + MagickOffsetType + progress; - MatrixInfo + MatrixInfo *canny_cache; - ssize_t - y; + ssize_t + y; - assert(image != (const Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - /* - Filter out noise. - */ - (void) FormatLocaleString(geometry,MagickPathExtent, - "blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma); - kernel_info=AcquireKernelInfo(geometry,exception); - if (kernel_info == (KernelInfo *) NULL) - ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); - edge_image=MorphologyImage(image,ConvolveMorphology,1,kernel_info,exception); - kernel_info=DestroyKernelInfo(kernel_info); - if (edge_image == (Image *) NULL) - return((Image *) NULL); - if (TransformImageColorspace(edge_image,GRAYColorspace,exception) == MagickFalse) + assert(image != (const Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + /* + Filter out noise. + */ + (void) FormatLocaleString(geometry,MagickPathExtent, + "blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma); + kernel_info=AcquireKernelInfo(geometry,exception); + if (kernel_info == (KernelInfo *) NULL) + ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); + edge_image=MorphologyImage(image,ConvolveMorphology,1,kernel_info,exception); + kernel_info=DestroyKernelInfo(kernel_info); + if (edge_image == (Image *) NULL) + return((Image *) NULL); + if (TransformImageColorspace(edge_image,GRAYColorspace,exception) == MagickFalse) { - edge_image=DestroyImage(edge_image); - return((Image *) NULL); + edge_image=DestroyImage(edge_image); + return((Image *) NULL); } - (void) SetImageAlphaChannel(edge_image,OffAlphaChannel,exception); - /* - Find the intensity gradient of the image. - */ - canny_cache=AcquireMatrixInfo(edge_image->columns,edge_image->rows, - sizeof(CannyInfo),exception); - if (canny_cache == (MatrixInfo *) NULL) + (void) SetImageAlphaChannel(edge_image,OffAlphaChannel,exception); + /* + Find the intensity gradient of the image. + */ + canny_cache=AcquireMatrixInfo(edge_image->columns,edge_image->rows, + sizeof(CannyInfo),exception); + if (canny_cache == (MatrixInfo *) NULL) { - edge_image=DestroyImage(edge_image); - return((Image *) NULL); + edge_image=DestroyImage(edge_image); + return((Image *) NULL); } - status=MagickTrue; - edge_view=AcquireVirtualCacheView(edge_image,exception); + status=MagickTrue; + edge_view=AcquireVirtualCacheView(edge_image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static) shared(status) \ magick_number_threads(edge_image,edge_image,edge_image->rows,1) #endif - for (y=0; y < (ssize_t) edge_image->rows; y++) - { - register const Quantum - *magick_restrict p; - - register ssize_t - x; - - if (status == MagickFalse) - continue; - p=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns+1,2, - exception); - if (p == (const Quantum *) NULL) - { - status=MagickFalse; - continue; - } - for (x=0; x < (ssize_t) edge_image->columns; x++) + for (y=0; y < (ssize_t) edge_image->rows; y++) { - CannyInfo - pixel; + register const Quantum + *magick_restrict p; - double - dx, - dy; + register ssize_t + x; - register const Quantum - *magick_restrict kernel_pixels; - - ssize_t - v; - - static double - Gx[2][2] = + if (status == MagickFalse) + continue; + p=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns+1,2, + exception); + if (p == (const Quantum *) NULL) { - { -1.0, +1.0 }, - { -1.0, +1.0 } - }, - Gy[2][2] = - { - { +1.0, +1.0 }, - { -1.0, -1.0 } - }; - - (void) memset(&pixel,0,sizeof(pixel)); - dx=0.0; - dy=0.0; - kernel_pixels=p; - for (v=0; v < 2; v++) - { - ssize_t - u; - - for (u=0; u < 2; u++) - { - double - intensity; - - intensity=GetPixelIntensity(edge_image,kernel_pixels+u); - dx+=0.5*Gx[v][u]*intensity; - dy+=0.5*Gy[v][u]*intensity; + status=MagickFalse; + continue; } - kernel_pixels+=edge_image->columns+1; - } - pixel.magnitude=hypot(dx,dy); - pixel.orientation=0; - if (fabs(dx) > MagickEpsilon) + for (x=0; x < (ssize_t) edge_image->columns; x++) { - double - slope; + CannyInfo + pixel; - slope=dy/dx; - if (slope < 0.0) + double + dx, + dy; + + register const Quantum + *magick_restrict kernel_pixels; + + ssize_t + v; + + static double + Gx[2][2] = { - if (slope < -2.41421356237) - pixel.orientation=0; - else - if (slope < -0.414213562373) - pixel.orientation=1; - else - pixel.orientation=2; - } - else + { -1.0, +1.0 }, + { -1.0, +1.0 } + }, + Gy[2][2] = { - if (slope > 2.41421356237) - pixel.orientation=0; - else - if (slope > 0.414213562373) - pixel.orientation=3; - else - pixel.orientation=2; + { +1.0, +1.0 }, + { -1.0, -1.0 } + }; + + (void) memset(&pixel,0,sizeof(pixel)); + dx=0.0; + dy=0.0; + kernel_pixels=p; + for (v=0; v < 2; v++) + { + ssize_t + u; + + for (u=0; u < 2; u++) + { + double + intensity; + + intensity=GetPixelIntensity(edge_image,kernel_pixels+u); + dx+=0.5*Gx[v][u]*intensity; + dy+=0.5*Gy[v][u]*intensity; + } + kernel_pixels+=edge_image->columns+1; } + pixel.magnitude=hypot(dx,dy); + pixel.orientation=0; + if (fabs(dx) > MagickEpsilon) + { + double + slope; + + slope=dy/dx; + if (slope < 0.0) + { + if (slope < -2.41421356237) + pixel.orientation=0; + else + if (slope < -0.414213562373) + pixel.orientation=1; + else + pixel.orientation=2; + } + else + { + if (slope > 2.41421356237) + pixel.orientation=0; + else + if (slope > 0.414213562373) + pixel.orientation=3; + else + pixel.orientation=2; + } + } + if (SetMatrixElement(canny_cache,x,y,&pixel) == MagickFalse) + continue; + p+=GetPixelChannels(edge_image); } - if (SetMatrixElement(canny_cache,x,y,&pixel) == MagickFalse) - continue; - p+=GetPixelChannels(edge_image); } - } - edge_view=DestroyCacheView(edge_view); - /* - Non-maxima suppression, remove pixels that are not considered to be part - of an edge. - */ - progress=0; - (void) GetMatrixElement(canny_cache,0,0,&element); - max=element.intensity; - min=element.intensity; - edge_view=AcquireAuthenticCacheView(edge_image,exception); + edge_view=DestroyCacheView(edge_view); + /* + Non-maxima suppression, remove pixels that are not considered to be part + of an edge. + */ + progress=0; + (void) GetMatrixElement(canny_cache,0,0,&element); + max=element.intensity; + min=element.intensity; + edge_view=AcquireAuthenticCacheView(edge_image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static) shared(status) \ magick_number_threads(edge_image,edge_image,edge_image->rows,1) #endif - for (y=0; y < (ssize_t) edge_image->rows; y++) - { - register Quantum - *magick_restrict q; - - register ssize_t - x; - - if (status == MagickFalse) - continue; - q=GetCacheViewAuthenticPixels(edge_view,0,y,edge_image->columns,1, - exception); - if (q == (Quantum *) NULL) - { - status=MagickFalse; - continue; - } - for (x=0; x < (ssize_t) edge_image->columns; x++) + for (y=0; y < (ssize_t) edge_image->rows; y++) { - CannyInfo - alpha_pixel, - beta_pixel, - pixel; + register Quantum + *magick_restrict q; - (void) GetMatrixElement(canny_cache,x,y,&pixel); - switch (pixel.orientation) - { - case 0: - default: + register ssize_t + x; + + if (status == MagickFalse) + continue; + q=GetCacheViewAuthenticPixels(edge_view,0,y,edge_image->columns,1, + exception); + if (q == (Quantum *) NULL) { - /* - 0 degrees, north and south. - */ - (void) GetMatrixElement(canny_cache,x,y-1,&alpha_pixel); - (void) GetMatrixElement(canny_cache,x,y+1,&beta_pixel); - break; + status=MagickFalse; + continue; } - case 1: + for (x=0; x < (ssize_t) edge_image->columns; x++) { - /* - 45 degrees, northwest and southeast. - */ - (void) GetMatrixElement(canny_cache,x-1,y-1,&alpha_pixel); - (void) GetMatrixElement(canny_cache,x+1,y+1,&beta_pixel); - break; - } - case 2: - { - /* - 90 degrees, east and west. - */ - (void) GetMatrixElement(canny_cache,x-1,y,&alpha_pixel); - (void) GetMatrixElement(canny_cache,x+1,y,&beta_pixel); - break; - } - case 3: - { - /* - 135 degrees, northeast and southwest. - */ - (void) GetMatrixElement(canny_cache,x+1,y-1,&beta_pixel); - (void) GetMatrixElement(canny_cache,x-1,y+1,&alpha_pixel); - break; - } - } - pixel.intensity=pixel.magnitude; - if ((pixel.magnitude < alpha_pixel.magnitude) || - (pixel.magnitude < beta_pixel.magnitude)) - pixel.intensity=0; - (void) SetMatrixElement(canny_cache,x,y,&pixel); + CannyInfo + alpha_pixel, + beta_pixel, + pixel; + + (void) GetMatrixElement(canny_cache,x,y,&pixel); + switch (pixel.orientation) + { + case 0: + default: + { + /* + 0 degrees, north and south. + */ + (void) GetMatrixElement(canny_cache,x,y-1,&alpha_pixel); + (void) GetMatrixElement(canny_cache,x,y+1,&beta_pixel); + break; + } + case 1: + { + /* + 45 degrees, northwest and southeast. + */ + (void) GetMatrixElement(canny_cache,x-1,y-1,&alpha_pixel); + (void) GetMatrixElement(canny_cache,x+1,y+1,&beta_pixel); + break; + } + case 2: + { + /* + 90 degrees, east and west. + */ + (void) GetMatrixElement(canny_cache,x-1,y,&alpha_pixel); + (void) GetMatrixElement(canny_cache,x+1,y,&beta_pixel); + break; + } + case 3: + { + /* + 135 degrees, northeast and southwest. + */ + (void) GetMatrixElement(canny_cache,x+1,y-1,&beta_pixel); + (void) GetMatrixElement(canny_cache,x-1,y+1,&alpha_pixel); + break; + } + } + pixel.intensity=pixel.magnitude; + if ((pixel.magnitude < alpha_pixel.magnitude) || + (pixel.magnitude < beta_pixel.magnitude)) + pixel.intensity=0; + (void) SetMatrixElement(canny_cache,x,y,&pixel); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_CannyEdgeImage) #endif - { - if (pixel.intensity < min) - min=pixel.intensity; - if (pixel.intensity > max) - max=pixel.intensity; - } - *q=0; - q+=GetPixelChannels(edge_image); + { + if (pixel.intensity < min) + min=pixel.intensity; + if (pixel.intensity > max) + max=pixel.intensity; + } + *q=0; + q+=GetPixelChannels(edge_image); + } + if (SyncCacheViewAuthenticPixels(edge_view,exception) == MagickFalse) + status=MagickFalse; } - if (SyncCacheViewAuthenticPixels(edge_view,exception) == MagickFalse) - status=MagickFalse; - } - edge_view=DestroyCacheView(edge_view); - /* - Estimate hysteresis threshold. - */ - lower_threshold=lower_percent*(max-min)+min; - upper_threshold=upper_percent*(max-min)+min; - /* - Hysteresis threshold. - */ - edge_view=AcquireAuthenticCacheView(edge_image,exception); - for (y=0; y < (ssize_t) edge_image->rows; y++) - { - register ssize_t - x; - - if (status == MagickFalse) - continue; - for (x=0; x < (ssize_t) edge_image->columns; x++) + edge_view=DestroyCacheView(edge_view); + /* + Estimate hysteresis threshold. + */ + lower_threshold=lower_percent*(max-min)+min; + upper_threshold=upper_percent*(max-min)+min; + /* + Hysteresis threshold. + */ + edge_view=AcquireAuthenticCacheView(edge_image,exception); + for (y=0; y < (ssize_t) edge_image->rows; y++) { - CannyInfo - pixel; + register ssize_t + x; - register const Quantum - *magick_restrict p; + if (status == MagickFalse) + continue; + for (x=0; x < (ssize_t) edge_image->columns; x++) + { + CannyInfo + pixel; - /* - Edge if pixel gradient higher than upper threshold. - */ - p=GetCacheViewVirtualPixels(edge_view,x,y,1,1,exception); - if (p == (const Quantum *) NULL) - continue; - status=GetMatrixElement(canny_cache,x,y,&pixel); - if (status == MagickFalse) - continue; - if ((GetPixelIntensity(edge_image,p) == 0.0) && - (pixel.intensity >= upper_threshold)) - status=TraceEdges(edge_image,edge_view,canny_cache,x,y,lower_threshold, - exception); - } - if (image->progress_monitor != (MagickProgressMonitor) NULL) - { - MagickBooleanType - proceed; + register const Quantum + *magick_restrict p; + + /* + Edge if pixel gradient higher than upper threshold. + */ + p=GetCacheViewVirtualPixels(edge_view,x,y,1,1,exception); + if (p == (const Quantum *) NULL) + continue; + status=GetMatrixElement(canny_cache,x,y,&pixel); + if (status == MagickFalse) + continue; + if ((GetPixelIntensity(edge_image,p) == 0.0) && + (pixel.intensity >= upper_threshold)) + status=TraceEdges(edge_image,edge_view,canny_cache,x,y,lower_threshold, + exception); + } + if (image->progress_monitor != (MagickProgressMonitor) NULL) + { + MagickBooleanType + proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp atomic #endif - progress++; - proceed=SetImageProgress(image,CannyEdgeImageTag,progress,image->rows); - if (proceed == MagickFalse) - status=MagickFalse; - } - } - edge_view=DestroyCacheView(edge_view); - /* - Free resources. - */ - canny_cache=DestroyMatrixInfo(canny_cache); - return(edge_image); + progress++; + proceed=SetImageProgress(image,CannyEdgeImageTag,progress,image->rows); + if (proceed == MagickFalse) + status=MagickFalse; + } + } + edge_view=DestroyCacheView(edge_view); + /* + Free resources. + */ + canny_cache=DestroyMatrixInfo(canny_cache); + return(edge_image); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% G e t I m a g e F e a t u r e s % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% GetImageFeatures() returns features for each channel in the image in -% each of four directions (horizontal, vertical, left and right diagonals) -% for the specified distance. The features include the angular second -% moment, contrast, correlation, sum of squares: variance, inverse difference -% moment, sum average, sum varience, sum entropy, entropy, difference variance,% difference entropy, information measures of correlation 1, information -% measures of correlation 2, and maximum correlation coefficient. You can -% access the red channel contrast, for example, like this: -% -% channel_features=GetImageFeatures(image,1,exception); -% contrast=channel_features[RedPixelChannel].contrast[0]; -% -% Use MagickRelinquishMemory() to free the features buffer. -% -% The format of the GetImageFeatures method is: -% -% ChannelFeatures *GetImageFeatures(const Image *image, -% const size_t distance,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image. -% -% o distance: the distance. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % G e t I m a g e F e a t u r e s % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % GetImageFeatures() returns features for each channel in the image in + % each of four directions (horizontal, vertical, left and right diagonals) + % for the specified distance. The features include the angular second + % moment, contrast, correlation, sum of squares: variance, inverse difference + % moment, sum average, sum varience, sum entropy, entropy, difference variance,% difference entropy, information measures of correlation 1, information + % measures of correlation 2, and maximum correlation coefficient. You can + % access the red channel contrast, for example, like this: + % + % channel_features=GetImageFeatures(image,1,exception); + % contrast=channel_features[RedPixelChannel].contrast[0]; + % + % Use MagickRelinquishMemory() to free the features buffer. + % + % The format of the GetImageFeatures method is: + % + % ChannelFeatures *GetImageFeatures(const Image *image, + % const size_t distance,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image. + % + % o distance: the distance. + % + % o exception: return any errors or warnings in this structure. + % + */ static inline double MagickLog10(const double x) { #define Log10Epsilon (1.0e-11) - if (fabs(x) < Log10Epsilon) - return(log10(Log10Epsilon)); - return(log10(fabs(x))); + if (fabs(x) < Log10Epsilon) + return(log10(Log10Epsilon)); + return(log10(fabs(x))); } MagickExport ChannelFeatures *GetImageFeatures(const Image *image, - const size_t distance,ExceptionInfo *exception) + const size_t distance,ExceptionInfo *exception) { - typedef struct _ChannelStatistics - { - PixelInfo - direction[4]; /* horizontal, vertical, left and right diagonals */ - } ChannelStatistics; + typedef struct _ChannelStatistics + { + PixelInfo + direction[4]; /* horizontal, vertical, left and right diagonals */ + } ChannelStatistics; - CacheView + CacheView *image_view; - ChannelFeatures + ChannelFeatures *channel_features; - ChannelStatistics + ChannelStatistics **cooccurrence, correlation, *density_x, @@ -651,1688 +651,1688 @@ MagickExport ChannelFeatures *GetImageFeatures(const Image *image, sum_squares, variance; - PixelPacket - gray, - *grays; + PixelPacket + gray, + *grays; - MagickBooleanType - status; + MagickBooleanType + status; - register ssize_t - i, - r; + register ssize_t + i, + r; - size_t - length; + size_t + length; - unsigned int - number_grays; + unsigned int + number_grays; - assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - if ((image->columns < (distance+1)) || (image->rows < (distance+1))) - return((ChannelFeatures *) NULL); - length=MaxPixelChannels+1UL; - channel_features=(ChannelFeatures *) AcquireQuantumMemory(length, - sizeof(*channel_features)); - if (channel_features == (ChannelFeatures *) NULL) - ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); - (void) memset(channel_features,0,length* - sizeof(*channel_features)); - /* - Form grays. - */ - grays=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*grays)); - if (grays == (PixelPacket *) NULL) + assert(image != (Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + if ((image->columns < (distance+1)) || (image->rows < (distance+1))) + return((ChannelFeatures *) NULL); + length=MaxPixelChannels+1UL; + channel_features=(ChannelFeatures *) AcquireQuantumMemory(length, + sizeof(*channel_features)); + if (channel_features == (ChannelFeatures *) NULL) + ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); + (void) memset(channel_features,0,length* + sizeof(*channel_features)); + /* + Form grays. + */ + grays=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*grays)); + if (grays == (PixelPacket *) NULL) { - channel_features=(ChannelFeatures *) RelinquishMagickMemory( - channel_features); - (void) ThrowMagickException(exception,GetMagickModule(), - ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); - return(channel_features); + channel_features=(ChannelFeatures *) RelinquishMagickMemory( + channel_features); + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); + return(channel_features); } - for (i=0; i <= (ssize_t) MaxMap; i++) - { - grays[i].red=(~0U); - grays[i].green=(~0U); - grays[i].blue=(~0U); - grays[i].alpha=(~0U); - grays[i].black=(~0U); - } - status=MagickTrue; - image_view=AcquireVirtualCacheView(image,exception); + for (i=0; i <= (ssize_t) MaxMap; i++) + { + grays[i].red=(~0U); + grays[i].green=(~0U); + grays[i].blue=(~0U); + grays[i].alpha=(~0U); + grays[i].black=(~0U); + } + status=MagickTrue; + image_view=AcquireVirtualCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static) shared(status) \ magick_number_threads(image,image,image->rows,1) #endif - for (r=0; r < (ssize_t) image->rows; r++) - { - register const Quantum - *magick_restrict p; + for (r=0; r < (ssize_t) image->rows; r++) + { + register const Quantum + *magick_restrict p; - register ssize_t - x; + register ssize_t + x; + if (status == MagickFalse) + continue; + p=GetCacheViewVirtualPixels(image_view,0,r,image->columns,1,exception); + if (p == (const Quantum *) NULL) + { + status=MagickFalse; + continue; + } + for (x=0; x < (ssize_t) image->columns; x++) + { + grays[ScaleQuantumToMap(GetPixelRed(image,p))].red= + ScaleQuantumToMap(GetPixelRed(image,p)); + grays[ScaleQuantumToMap(GetPixelGreen(image,p))].green= + ScaleQuantumToMap(GetPixelGreen(image,p)); + grays[ScaleQuantumToMap(GetPixelBlue(image,p))].blue= + ScaleQuantumToMap(GetPixelBlue(image,p)); + if (image->colorspace == CMYKColorspace) + grays[ScaleQuantumToMap(GetPixelBlack(image,p))].black= + ScaleQuantumToMap(GetPixelBlack(image,p)); + if (image->alpha_trait != UndefinedPixelTrait) + grays[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha= + ScaleQuantumToMap(GetPixelAlpha(image,p)); + p+=GetPixelChannels(image); + } + } + image_view=DestroyCacheView(image_view); if (status == MagickFalse) - continue; - p=GetCacheViewVirtualPixels(image_view,0,r,image->columns,1,exception); - if (p == (const Quantum *) NULL) - { - status=MagickFalse; - continue; - } - for (x=0; x < (ssize_t) image->columns; x++) { - grays[ScaleQuantumToMap(GetPixelRed(image,p))].red= - ScaleQuantumToMap(GetPixelRed(image,p)); - grays[ScaleQuantumToMap(GetPixelGreen(image,p))].green= - ScaleQuantumToMap(GetPixelGreen(image,p)); - grays[ScaleQuantumToMap(GetPixelBlue(image,p))].blue= - ScaleQuantumToMap(GetPixelBlue(image,p)); - if (image->colorspace == CMYKColorspace) - grays[ScaleQuantumToMap(GetPixelBlack(image,p))].black= - ScaleQuantumToMap(GetPixelBlack(image,p)); - if (image->alpha_trait != UndefinedPixelTrait) - grays[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha= - ScaleQuantumToMap(GetPixelAlpha(image,p)); - p+=GetPixelChannels(image); + grays=(PixelPacket *) RelinquishMagickMemory(grays); + channel_features=(ChannelFeatures *) RelinquishMagickMemory( + channel_features); + return(channel_features); } - } - image_view=DestroyCacheView(image_view); - if (status == MagickFalse) + (void) memset(&gray,0,sizeof(gray)); + for (i=0; i <= (ssize_t) MaxMap; i++) { - grays=(PixelPacket *) RelinquishMagickMemory(grays); - channel_features=(ChannelFeatures *) RelinquishMagickMemory( - channel_features); - return(channel_features); + if (grays[i].red != ~0U) + grays[gray.red++].red=grays[i].red; + if (grays[i].green != ~0U) + grays[gray.green++].green=grays[i].green; + if (grays[i].blue != ~0U) + grays[gray.blue++].blue=grays[i].blue; + if (image->colorspace == CMYKColorspace) + if (grays[i].black != ~0U) + grays[gray.black++].black=grays[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + if (grays[i].alpha != ~0U) + grays[gray.alpha++].alpha=grays[i].alpha; } - (void) memset(&gray,0,sizeof(gray)); - for (i=0; i <= (ssize_t) MaxMap; i++) - { - if (grays[i].red != ~0U) - grays[gray.red++].red=grays[i].red; - if (grays[i].green != ~0U) - grays[gray.green++].green=grays[i].green; - if (grays[i].blue != ~0U) - grays[gray.blue++].blue=grays[i].blue; + /* + Allocate spatial dependence matrix. + */ + number_grays=gray.red; + if (gray.green > number_grays) + number_grays=gray.green; + if (gray.blue > number_grays) + number_grays=gray.blue; if (image->colorspace == CMYKColorspace) - if (grays[i].black != ~0U) - grays[gray.black++].black=grays[i].black; + if (gray.black > number_grays) + number_grays=gray.black; if (image->alpha_trait != UndefinedPixelTrait) - if (grays[i].alpha != ~0U) - grays[gray.alpha++].alpha=grays[i].alpha; - } - /* - Allocate spatial dependence matrix. - */ - number_grays=gray.red; - if (gray.green > number_grays) - number_grays=gray.green; - if (gray.blue > number_grays) - number_grays=gray.blue; - if (image->colorspace == CMYKColorspace) - if (gray.black > number_grays) - number_grays=gray.black; - if (image->alpha_trait != UndefinedPixelTrait) - if (gray.alpha > number_grays) - number_grays=gray.alpha; - cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays, - sizeof(*cooccurrence)); - density_x=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), - sizeof(*density_x)); - density_xy=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), - sizeof(*density_xy)); - density_y=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), - sizeof(*density_y)); - Q=(ChannelStatistics **) AcquireQuantumMemory(number_grays,sizeof(*Q)); - sum=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(*sum)); - if ((cooccurrence == (ChannelStatistics **) NULL) || - (density_x == (ChannelStatistics *) NULL) || - (density_xy == (ChannelStatistics *) NULL) || - (density_y == (ChannelStatistics *) NULL) || - (Q == (ChannelStatistics **) NULL) || - (sum == (ChannelStatistics *) NULL)) + if (gray.alpha > number_grays) + number_grays=gray.alpha; + cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays, + sizeof(*cooccurrence)); + density_x=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), + sizeof(*density_x)); + density_xy=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), + sizeof(*density_xy)); + density_y=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), + sizeof(*density_y)); + Q=(ChannelStatistics **) AcquireQuantumMemory(number_grays,sizeof(*Q)); + sum=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(*sum)); + if ((cooccurrence == (ChannelStatistics **) NULL) || + (density_x == (ChannelStatistics *) NULL) || + (density_xy == (ChannelStatistics *) NULL) || + (density_y == (ChannelStatistics *) NULL) || + (Q == (ChannelStatistics **) NULL) || + (sum == (ChannelStatistics *) NULL)) { - if (Q != (ChannelStatistics **) NULL) + if (Q != (ChannelStatistics **) NULL) { - for (i=0; i < (ssize_t) number_grays; i++) - Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); - Q=(ChannelStatistics **) RelinquishMagickMemory(Q); + for (i=0; i < (ssize_t) number_grays; i++) + Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); + Q=(ChannelStatistics **) RelinquishMagickMemory(Q); } - if (sum != (ChannelStatistics *) NULL) + if (sum != (ChannelStatistics *) NULL) + sum=(ChannelStatistics *) RelinquishMagickMemory(sum); + if (density_y != (ChannelStatistics *) NULL) + density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); + if (density_xy != (ChannelStatistics *) NULL) + density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); + if (density_x != (ChannelStatistics *) NULL) + density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); + if (cooccurrence != (ChannelStatistics **) NULL) + { + for (i=0; i < (ssize_t) number_grays; i++) + cooccurrence[i]=(ChannelStatistics *) + RelinquishMagickMemory(cooccurrence[i]); + cooccurrence=(ChannelStatistics **) RelinquishMagickMemory( + cooccurrence); + } + grays=(PixelPacket *) RelinquishMagickMemory(grays); + channel_features=(ChannelFeatures *) RelinquishMagickMemory( + channel_features); + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); + return(channel_features); + } + (void) memset(&correlation,0,sizeof(correlation)); + (void) memset(density_x,0,2*(number_grays+1)*sizeof(*density_x)); + (void) memset(density_xy,0,2*(number_grays+1)*sizeof(*density_xy)); + (void) memset(density_y,0,2*(number_grays+1)*sizeof(*density_y)); + (void) memset(&mean,0,sizeof(mean)); + (void) memset(sum,0,number_grays*sizeof(*sum)); + (void) memset(&sum_squares,0,sizeof(sum_squares)); + (void) memset(density_xy,0,2*number_grays*sizeof(*density_xy)); + (void) memset(&entropy_x,0,sizeof(entropy_x)); + (void) memset(&entropy_xy,0,sizeof(entropy_xy)); + (void) memset(&entropy_xy1,0,sizeof(entropy_xy1)); + (void) memset(&entropy_xy2,0,sizeof(entropy_xy2)); + (void) memset(&entropy_y,0,sizeof(entropy_y)); + (void) memset(&variance,0,sizeof(variance)); + for (i=0; i < (ssize_t) number_grays; i++) + { + cooccurrence[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays, + sizeof(**cooccurrence)); + Q[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(**Q)); + if ((cooccurrence[i] == (ChannelStatistics *) NULL) || + (Q[i] == (ChannelStatistics *) NULL)) + break; + (void) memset(cooccurrence[i],0,number_grays* + sizeof(**cooccurrence)); + (void) memset(Q[i],0,number_grays*sizeof(**Q)); + } + if (i < (ssize_t) number_grays) + { + for (i--; i >= 0; i--) + { + if (Q[i] != (ChannelStatistics *) NULL) + Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); + if (cooccurrence[i] != (ChannelStatistics *) NULL) + cooccurrence[i]=(ChannelStatistics *) + RelinquishMagickMemory(cooccurrence[i]); + } + Q=(ChannelStatistics **) RelinquishMagickMemory(Q); + cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); sum=(ChannelStatistics *) RelinquishMagickMemory(sum); - if (density_y != (ChannelStatistics *) NULL) density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); - if (density_xy != (ChannelStatistics *) NULL) density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); - if (density_x != (ChannelStatistics *) NULL) density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); - if (cooccurrence != (ChannelStatistics **) NULL) + grays=(PixelPacket *) RelinquishMagickMemory(grays); + channel_features=(ChannelFeatures *) RelinquishMagickMemory( + channel_features); + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); + return(channel_features); + } + /* + Initialize spatial dependence matrix. + */ + status=MagickTrue; + image_view=AcquireVirtualCacheView(image,exception); + for (r=0; r < (ssize_t) image->rows; r++) + { + register const Quantum + *magick_restrict p; + + register ssize_t + x; + + ssize_t + offset, + u, + v; + + if (status == MagickFalse) + continue; + p=GetCacheViewVirtualPixels(image_view,-(ssize_t) distance,r,image->columns+ + 2*distance,distance+2,exception); + if (p == (const Quantum *) NULL) { - for (i=0; i < (ssize_t) number_grays; i++) - cooccurrence[i]=(ChannelStatistics *) - RelinquishMagickMemory(cooccurrence[i]); - cooccurrence=(ChannelStatistics **) RelinquishMagickMemory( - cooccurrence); + status=MagickFalse; + continue; + } + p+=distance*GetPixelChannels(image);; + for (x=0; x < (ssize_t) image->columns; x++) + { + for (i=0; i < 4; i++) + { + switch (i) + { + case 0: + default: + { + /* + Horizontal adjacency. + */ + offset=(ssize_t) distance; + break; + } + case 1: + { + /* + Vertical adjacency. + */ + offset=(ssize_t) (image->columns+2*distance); + break; + } + case 2: + { + /* + Right diagonal adjacency. + */ + offset=(ssize_t) ((image->columns+2*distance)-distance); + break; + } + case 3: + { + /* + Left diagonal adjacency. + */ + offset=(ssize_t) ((image->columns+2*distance)+distance); + break; + } + } + u=0; + v=0; + while (grays[u].red != ScaleQuantumToMap(GetPixelRed(image,p))) + u++; + while (grays[v].red != ScaleQuantumToMap(GetPixelRed(image,p+offset*GetPixelChannels(image)))) + v++; + cooccurrence[u][v].direction[i].red++; + cooccurrence[v][u].direction[i].red++; + u=0; + v=0; + while (grays[u].green != ScaleQuantumToMap(GetPixelGreen(image,p))) + u++; + while (grays[v].green != ScaleQuantumToMap(GetPixelGreen(image,p+offset*GetPixelChannels(image)))) + v++; + cooccurrence[u][v].direction[i].green++; + cooccurrence[v][u].direction[i].green++; + u=0; + v=0; + while (grays[u].blue != ScaleQuantumToMap(GetPixelBlue(image,p))) + u++; + while (grays[v].blue != ScaleQuantumToMap(GetPixelBlue(image,p+offset*GetPixelChannels(image)))) + v++; + cooccurrence[u][v].direction[i].blue++; + cooccurrence[v][u].direction[i].blue++; + if (image->colorspace == CMYKColorspace) + { + u=0; + v=0; + while (grays[u].black != ScaleQuantumToMap(GetPixelBlack(image,p))) + u++; + while (grays[v].black != ScaleQuantumToMap(GetPixelBlack(image,p+offset*GetPixelChannels(image)))) + v++; + cooccurrence[u][v].direction[i].black++; + cooccurrence[v][u].direction[i].black++; + } + if (image->alpha_trait != UndefinedPixelTrait) + { + u=0; + v=0; + while (grays[u].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p))) + u++; + while (grays[v].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p+offset*GetPixelChannels(image)))) + v++; + cooccurrence[u][v].direction[i].alpha++; + cooccurrence[v][u].direction[i].alpha++; + } + } + p+=GetPixelChannels(image); } - grays=(PixelPacket *) RelinquishMagickMemory(grays); - channel_features=(ChannelFeatures *) RelinquishMagickMemory( - channel_features); - (void) ThrowMagickException(exception,GetMagickModule(), - ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); - return(channel_features); } - (void) memset(&correlation,0,sizeof(correlation)); - (void) memset(density_x,0,2*(number_grays+1)*sizeof(*density_x)); - (void) memset(density_xy,0,2*(number_grays+1)*sizeof(*density_xy)); - (void) memset(density_y,0,2*(number_grays+1)*sizeof(*density_y)); - (void) memset(&mean,0,sizeof(mean)); - (void) memset(sum,0,number_grays*sizeof(*sum)); - (void) memset(&sum_squares,0,sizeof(sum_squares)); - (void) memset(density_xy,0,2*number_grays*sizeof(*density_xy)); - (void) memset(&entropy_x,0,sizeof(entropy_x)); - (void) memset(&entropy_xy,0,sizeof(entropy_xy)); - (void) memset(&entropy_xy1,0,sizeof(entropy_xy1)); - (void) memset(&entropy_xy2,0,sizeof(entropy_xy2)); - (void) memset(&entropy_y,0,sizeof(entropy_y)); - (void) memset(&variance,0,sizeof(variance)); - for (i=0; i < (ssize_t) number_grays; i++) - { - cooccurrence[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays, - sizeof(**cooccurrence)); - Q[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(**Q)); - if ((cooccurrence[i] == (ChannelStatistics *) NULL) || - (Q[i] == (ChannelStatistics *) NULL)) - break; - (void) memset(cooccurrence[i],0,number_grays* - sizeof(**cooccurrence)); - (void) memset(Q[i],0,number_grays*sizeof(**Q)); - } - if (i < (ssize_t) number_grays) - { - for (i--; i >= 0; i--) - { - if (Q[i] != (ChannelStatistics *) NULL) - Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); - if (cooccurrence[i] != (ChannelStatistics *) NULL) - cooccurrence[i]=(ChannelStatistics *) - RelinquishMagickMemory(cooccurrence[i]); - } - Q=(ChannelStatistics **) RelinquishMagickMemory(Q); - cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); - sum=(ChannelStatistics *) RelinquishMagickMemory(sum); - density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); - density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); - density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); - grays=(PixelPacket *) RelinquishMagickMemory(grays); - channel_features=(ChannelFeatures *) RelinquishMagickMemory( - channel_features); - (void) ThrowMagickException(exception,GetMagickModule(), - ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); - return(channel_features); - } - /* - Initialize spatial dependence matrix. - */ - status=MagickTrue; - image_view=AcquireVirtualCacheView(image,exception); - for (r=0; r < (ssize_t) image->rows; r++) - { - register const Quantum - *magick_restrict p; - - register ssize_t - x; - - ssize_t - offset, - u, - v; - + grays=(PixelPacket *) RelinquishMagickMemory(grays); + image_view=DestroyCacheView(image_view); if (status == MagickFalse) - continue; - p=GetCacheViewVirtualPixels(image_view,-(ssize_t) distance,r,image->columns+ - 2*distance,distance+2,exception); - if (p == (const Quantum *) NULL) - { - status=MagickFalse; - continue; - } - p+=distance*GetPixelChannels(image);; - for (x=0; x < (ssize_t) image->columns; x++) { - for (i=0; i < 4; i++) - { + for (i=0; i < (ssize_t) number_grays; i++) + cooccurrence[i]=(ChannelStatistics *) + RelinquishMagickMemory(cooccurrence[i]); + cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); + channel_features=(ChannelFeatures *) RelinquishMagickMemory( + channel_features); + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); + return(channel_features); + } + /* + Normalize spatial dependence matrix. + */ + for (i=0; i < 4; i++) + { + double + normalize; + + register ssize_t + y; + switch (i) { - case 0: - default: - { - /* - Horizontal adjacency. - */ - offset=(ssize_t) distance; - break; - } - case 1: - { - /* - Vertical adjacency. - */ - offset=(ssize_t) (image->columns+2*distance); - break; - } - case 2: - { - /* - Right diagonal adjacency. - */ - offset=(ssize_t) ((image->columns+2*distance)-distance); - break; - } - case 3: - { - /* - Left diagonal adjacency. - */ - offset=(ssize_t) ((image->columns+2*distance)+distance); - break; - } - } - u=0; - v=0; - while (grays[u].red != ScaleQuantumToMap(GetPixelRed(image,p))) - u++; - while (grays[v].red != ScaleQuantumToMap(GetPixelRed(image,p+offset*GetPixelChannels(image)))) - v++; - cooccurrence[u][v].direction[i].red++; - cooccurrence[v][u].direction[i].red++; - u=0; - v=0; - while (grays[u].green != ScaleQuantumToMap(GetPixelGreen(image,p))) - u++; - while (grays[v].green != ScaleQuantumToMap(GetPixelGreen(image,p+offset*GetPixelChannels(image)))) - v++; - cooccurrence[u][v].direction[i].green++; - cooccurrence[v][u].direction[i].green++; - u=0; - v=0; - while (grays[u].blue != ScaleQuantumToMap(GetPixelBlue(image,p))) - u++; - while (grays[v].blue != ScaleQuantumToMap(GetPixelBlue(image,p+offset*GetPixelChannels(image)))) - v++; - cooccurrence[u][v].direction[i].blue++; - cooccurrence[v][u].direction[i].blue++; - if (image->colorspace == CMYKColorspace) - { - u=0; - v=0; - while (grays[u].black != ScaleQuantumToMap(GetPixelBlack(image,p))) - u++; - while (grays[v].black != ScaleQuantumToMap(GetPixelBlack(image,p+offset*GetPixelChannels(image)))) - v++; - cooccurrence[u][v].direction[i].black++; - cooccurrence[v][u].direction[i].black++; - } - if (image->alpha_trait != UndefinedPixelTrait) - { - u=0; - v=0; - while (grays[u].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p))) - u++; - while (grays[v].alpha != ScaleQuantumToMap(GetPixelAlpha(image,p+offset*GetPixelChannels(image)))) - v++; - cooccurrence[u][v].direction[i].alpha++; - cooccurrence[v][u].direction[i].alpha++; - } - } - p+=GetPixelChannels(image); - } - } - grays=(PixelPacket *) RelinquishMagickMemory(grays); - image_view=DestroyCacheView(image_view); - if (status == MagickFalse) - { - for (i=0; i < (ssize_t) number_grays; i++) - cooccurrence[i]=(ChannelStatistics *) - RelinquishMagickMemory(cooccurrence[i]); - cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); - channel_features=(ChannelFeatures *) RelinquishMagickMemory( - channel_features); - (void) ThrowMagickException(exception,GetMagickModule(), - ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); - return(channel_features); - } - /* - Normalize spatial dependence matrix. - */ - for (i=0; i < 4; i++) - { - double - normalize; - - register ssize_t - y; - - switch (i) - { - case 0: - default: - { - /* - Horizontal adjacency. - */ - normalize=2.0*image->rows*(image->columns-distance); - break; - } - case 1: - { - /* - Vertical adjacency. - */ - normalize=2.0*(image->rows-distance)*image->columns; - break; - } - case 2: - { - /* - Right diagonal adjacency. - */ - normalize=2.0*(image->rows-distance)*(image->columns-distance); - break; - } - case 3: - { - /* - Left diagonal adjacency. - */ - normalize=2.0*(image->rows-distance)*(image->columns-distance); - break; - } - } - normalize=PerceptibleReciprocal(normalize); - for (y=0; y < (ssize_t) number_grays; y++) - { - register ssize_t - x; - - for (x=0; x < (ssize_t) number_grays; x++) - { - cooccurrence[x][y].direction[i].red*=normalize; - cooccurrence[x][y].direction[i].green*=normalize; - cooccurrence[x][y].direction[i].blue*=normalize; - if (image->colorspace == CMYKColorspace) - cooccurrence[x][y].direction[i].black*=normalize; - if (image->alpha_trait != UndefinedPixelTrait) - cooccurrence[x][y].direction[i].alpha*=normalize; - } - } - } - /* - Compute texture features. - */ -#if defined(MAGICKCORE_OPENMP_SUPPORT) - #pragma omp parallel for schedule(static) shared(status) \ - magick_number_threads(image,image,number_grays,1) -#endif - for (i=0; i < 4; i++) - { - register ssize_t - y; - - for (y=0; y < (ssize_t) number_grays; y++) - { - register ssize_t - x; - - for (x=0; x < (ssize_t) number_grays; x++) - { - /* - Angular second moment: measure of homogeneity of the image. - */ - channel_features[RedPixelChannel].angular_second_moment[i]+= - cooccurrence[x][y].direction[i].red* - cooccurrence[x][y].direction[i].red; - channel_features[GreenPixelChannel].angular_second_moment[i]+= - cooccurrence[x][y].direction[i].green* - cooccurrence[x][y].direction[i].green; - channel_features[BluePixelChannel].angular_second_moment[i]+= - cooccurrence[x][y].direction[i].blue* - cooccurrence[x][y].direction[i].blue; - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].angular_second_moment[i]+= - cooccurrence[x][y].direction[i].black* - cooccurrence[x][y].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].angular_second_moment[i]+= - cooccurrence[x][y].direction[i].alpha* - cooccurrence[x][y].direction[i].alpha; - /* - Correlation: measure of linear-dependencies in the image. - */ - sum[y].direction[i].red+=cooccurrence[x][y].direction[i].red; - sum[y].direction[i].green+=cooccurrence[x][y].direction[i].green; - sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; - if (image->colorspace == CMYKColorspace) - sum[y].direction[i].black+=cooccurrence[x][y].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - sum[y].direction[i].alpha+=cooccurrence[x][y].direction[i].alpha; - correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red; - correlation.direction[i].green+=x*y* - cooccurrence[x][y].direction[i].green; - correlation.direction[i].blue+=x*y* - cooccurrence[x][y].direction[i].blue; - if (image->colorspace == CMYKColorspace) - correlation.direction[i].black+=x*y* - cooccurrence[x][y].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - correlation.direction[i].alpha+=x*y* - cooccurrence[x][y].direction[i].alpha; - /* - Inverse Difference Moment. - */ - channel_features[RedPixelChannel].inverse_difference_moment[i]+= - cooccurrence[x][y].direction[i].red/((y-x)*(y-x)+1); - channel_features[GreenPixelChannel].inverse_difference_moment[i]+= - cooccurrence[x][y].direction[i].green/((y-x)*(y-x)+1); - channel_features[BluePixelChannel].inverse_difference_moment[i]+= - cooccurrence[x][y].direction[i].blue/((y-x)*(y-x)+1); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].inverse_difference_moment[i]+= - cooccurrence[x][y].direction[i].black/((y-x)*(y-x)+1); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].inverse_difference_moment[i]+= - cooccurrence[x][y].direction[i].alpha/((y-x)*(y-x)+1); - /* - Sum average. - */ - density_xy[y+x+2].direction[i].red+= - cooccurrence[x][y].direction[i].red; - density_xy[y+x+2].direction[i].green+= - cooccurrence[x][y].direction[i].green; - density_xy[y+x+2].direction[i].blue+= - cooccurrence[x][y].direction[i].blue; - if (image->colorspace == CMYKColorspace) - density_xy[y+x+2].direction[i].black+= - cooccurrence[x][y].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - density_xy[y+x+2].direction[i].alpha+= - cooccurrence[x][y].direction[i].alpha; - /* - Entropy. - */ - channel_features[RedPixelChannel].entropy[i]-= - cooccurrence[x][y].direction[i].red* - MagickLog10(cooccurrence[x][y].direction[i].red); - channel_features[GreenPixelChannel].entropy[i]-= - cooccurrence[x][y].direction[i].green* - MagickLog10(cooccurrence[x][y].direction[i].green); - channel_features[BluePixelChannel].entropy[i]-= - cooccurrence[x][y].direction[i].blue* - MagickLog10(cooccurrence[x][y].direction[i].blue); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].entropy[i]-= - cooccurrence[x][y].direction[i].black* - MagickLog10(cooccurrence[x][y].direction[i].black); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].entropy[i]-= - cooccurrence[x][y].direction[i].alpha* - MagickLog10(cooccurrence[x][y].direction[i].alpha); - /* - Information Measures of Correlation. - */ - density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red; - density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green; - density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue; - if (image->alpha_trait != UndefinedPixelTrait) - density_x[x].direction[i].alpha+= - cooccurrence[x][y].direction[i].alpha; - if (image->colorspace == CMYKColorspace) - density_x[x].direction[i].black+= - cooccurrence[x][y].direction[i].black; - density_y[y].direction[i].red+=cooccurrence[x][y].direction[i].red; - density_y[y].direction[i].green+=cooccurrence[x][y].direction[i].green; - density_y[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; - if (image->colorspace == CMYKColorspace) - density_y[y].direction[i].black+= - cooccurrence[x][y].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - density_y[y].direction[i].alpha+= - cooccurrence[x][y].direction[i].alpha; - } - mean.direction[i].red+=y*sum[y].direction[i].red; - sum_squares.direction[i].red+=y*y*sum[y].direction[i].red; - mean.direction[i].green+=y*sum[y].direction[i].green; - sum_squares.direction[i].green+=y*y*sum[y].direction[i].green; - mean.direction[i].blue+=y*sum[y].direction[i].blue; - sum_squares.direction[i].blue+=y*y*sum[y].direction[i].blue; - if (image->colorspace == CMYKColorspace) + case 0: + default: { - mean.direction[i].black+=y*sum[y].direction[i].black; - sum_squares.direction[i].black+=y*y*sum[y].direction[i].black; + /* + Horizontal adjacency. + */ + normalize=2.0*image->rows*(image->columns-distance); + break; } - if (image->alpha_trait != UndefinedPixelTrait) + case 1: { - mean.direction[i].alpha+=y*sum[y].direction[i].alpha; - sum_squares.direction[i].alpha+=y*y*sum[y].direction[i].alpha; + /* + Vertical adjacency. + */ + normalize=2.0*(image->rows-distance)*image->columns; + break; + } + case 2: + { + /* + Right diagonal adjacency. + */ + normalize=2.0*(image->rows-distance)*(image->columns-distance); + break; + } + case 3: + { + /* + Left diagonal adjacency. + */ + normalize=2.0*(image->rows-distance)*(image->columns-distance); + break; + } + } + normalize=PerceptibleReciprocal(normalize); + for (y=0; y < (ssize_t) number_grays; y++) + { + register ssize_t + x; + + for (x=0; x < (ssize_t) number_grays; x++) + { + cooccurrence[x][y].direction[i].red*=normalize; + cooccurrence[x][y].direction[i].green*=normalize; + cooccurrence[x][y].direction[i].blue*=normalize; + if (image->colorspace == CMYKColorspace) + cooccurrence[x][y].direction[i].black*=normalize; + if (image->alpha_trait != UndefinedPixelTrait) + cooccurrence[x][y].direction[i].alpha*=normalize; + } } } /* - Correlation: measure of linear-dependencies in the image. - */ - channel_features[RedPixelChannel].correlation[i]= - (correlation.direction[i].red-mean.direction[i].red* - mean.direction[i].red)/(sqrt(sum_squares.direction[i].red- - (mean.direction[i].red*mean.direction[i].red))*sqrt( - sum_squares.direction[i].red-(mean.direction[i].red* - mean.direction[i].red))); - channel_features[GreenPixelChannel].correlation[i]= - (correlation.direction[i].green-mean.direction[i].green* - mean.direction[i].green)/(sqrt(sum_squares.direction[i].green- - (mean.direction[i].green*mean.direction[i].green))*sqrt( - sum_squares.direction[i].green-(mean.direction[i].green* - mean.direction[i].green))); - channel_features[BluePixelChannel].correlation[i]= - (correlation.direction[i].blue-mean.direction[i].blue* - mean.direction[i].blue)/(sqrt(sum_squares.direction[i].blue- - (mean.direction[i].blue*mean.direction[i].blue))*sqrt( - sum_squares.direction[i].blue-(mean.direction[i].blue* - mean.direction[i].blue))); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].correlation[i]= - (correlation.direction[i].black-mean.direction[i].black* - mean.direction[i].black)/(sqrt(sum_squares.direction[i].black- - (mean.direction[i].black*mean.direction[i].black))*sqrt( - sum_squares.direction[i].black-(mean.direction[i].black* - mean.direction[i].black))); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].correlation[i]= - (correlation.direction[i].alpha-mean.direction[i].alpha* - mean.direction[i].alpha)/(sqrt(sum_squares.direction[i].alpha- - (mean.direction[i].alpha*mean.direction[i].alpha))*sqrt( - sum_squares.direction[i].alpha-(mean.direction[i].alpha* - mean.direction[i].alpha))); - } - /* - Compute more texture features. - */ + Compute texture features. + */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static) shared(status) \ magick_number_threads(image,image,number_grays,1) #endif - for (i=0; i < 4; i++) - { - register ssize_t - x; - - for (x=2; x < (ssize_t) (2*number_grays); x++) + for (i=0; i < 4; i++) { - /* - Sum average. - */ - channel_features[RedPixelChannel].sum_average[i]+= - x*density_xy[x].direction[i].red; - channel_features[GreenPixelChannel].sum_average[i]+= - x*density_xy[x].direction[i].green; - channel_features[BluePixelChannel].sum_average[i]+= - x*density_xy[x].direction[i].blue; - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].sum_average[i]+= - x*density_xy[x].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].sum_average[i]+= - x*density_xy[x].direction[i].alpha; - /* - Sum entropy. - */ - channel_features[RedPixelChannel].sum_entropy[i]-= - density_xy[x].direction[i].red* - MagickLog10(density_xy[x].direction[i].red); - channel_features[GreenPixelChannel].sum_entropy[i]-= - density_xy[x].direction[i].green* - MagickLog10(density_xy[x].direction[i].green); - channel_features[BluePixelChannel].sum_entropy[i]-= - density_xy[x].direction[i].blue* - MagickLog10(density_xy[x].direction[i].blue); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].sum_entropy[i]-= - density_xy[x].direction[i].black* - MagickLog10(density_xy[x].direction[i].black); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].sum_entropy[i]-= - density_xy[x].direction[i].alpha* - MagickLog10(density_xy[x].direction[i].alpha); - /* - Sum variance. - */ - channel_features[RedPixelChannel].sum_variance[i]+= - (x-channel_features[RedPixelChannel].sum_entropy[i])* - (x-channel_features[RedPixelChannel].sum_entropy[i])* - density_xy[x].direction[i].red; - channel_features[GreenPixelChannel].sum_variance[i]+= - (x-channel_features[GreenPixelChannel].sum_entropy[i])* - (x-channel_features[GreenPixelChannel].sum_entropy[i])* - density_xy[x].direction[i].green; - channel_features[BluePixelChannel].sum_variance[i]+= - (x-channel_features[BluePixelChannel].sum_entropy[i])* - (x-channel_features[BluePixelChannel].sum_entropy[i])* - density_xy[x].direction[i].blue; - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].sum_variance[i]+= - (x-channel_features[BlackPixelChannel].sum_entropy[i])* - (x-channel_features[BlackPixelChannel].sum_entropy[i])* - density_xy[x].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].sum_variance[i]+= - (x-channel_features[AlphaPixelChannel].sum_entropy[i])* - (x-channel_features[AlphaPixelChannel].sum_entropy[i])* - density_xy[x].direction[i].alpha; - } - } - /* - Compute more texture features. - */ -#if defined(MAGICKCORE_OPENMP_SUPPORT) - #pragma omp parallel for schedule(static) shared(status) \ - magick_number_threads(image,image,number_grays,1) -#endif - for (i=0; i < 4; i++) - { - register ssize_t - y; - - for (y=0; y < (ssize_t) number_grays; y++) - { - register ssize_t - x; - - for (x=0; x < (ssize_t) number_grays; x++) - { - /* - Sum of Squares: Variance - */ - variance.direction[i].red+=(y-mean.direction[i].red+1)* - (y-mean.direction[i].red+1)*cooccurrence[x][y].direction[i].red; - variance.direction[i].green+=(y-mean.direction[i].green+1)* - (y-mean.direction[i].green+1)*cooccurrence[x][y].direction[i].green; - variance.direction[i].blue+=(y-mean.direction[i].blue+1)* - (y-mean.direction[i].blue+1)*cooccurrence[x][y].direction[i].blue; - if (image->colorspace == CMYKColorspace) - variance.direction[i].black+=(y-mean.direction[i].black+1)* - (y-mean.direction[i].black+1)*cooccurrence[x][y].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - variance.direction[i].alpha+=(y-mean.direction[i].alpha+1)* - (y-mean.direction[i].alpha+1)* - cooccurrence[x][y].direction[i].alpha; - /* - Sum average / Difference Variance. - */ - density_xy[MagickAbsoluteValue(y-x)].direction[i].red+= - cooccurrence[x][y].direction[i].red; - density_xy[MagickAbsoluteValue(y-x)].direction[i].green+= - cooccurrence[x][y].direction[i].green; - density_xy[MagickAbsoluteValue(y-x)].direction[i].blue+= - cooccurrence[x][y].direction[i].blue; - if (image->colorspace == CMYKColorspace) - density_xy[MagickAbsoluteValue(y-x)].direction[i].black+= - cooccurrence[x][y].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - density_xy[MagickAbsoluteValue(y-x)].direction[i].alpha+= - cooccurrence[x][y].direction[i].alpha; - /* - Information Measures of Correlation. - */ - entropy_xy.direction[i].red-=cooccurrence[x][y].direction[i].red* - MagickLog10(cooccurrence[x][y].direction[i].red); - entropy_xy.direction[i].green-=cooccurrence[x][y].direction[i].green* - MagickLog10(cooccurrence[x][y].direction[i].green); - entropy_xy.direction[i].blue-=cooccurrence[x][y].direction[i].blue* - MagickLog10(cooccurrence[x][y].direction[i].blue); - if (image->colorspace == CMYKColorspace) - entropy_xy.direction[i].black-=cooccurrence[x][y].direction[i].black* - MagickLog10(cooccurrence[x][y].direction[i].black); - if (image->alpha_trait != UndefinedPixelTrait) - entropy_xy.direction[i].alpha-= - cooccurrence[x][y].direction[i].alpha*MagickLog10( - cooccurrence[x][y].direction[i].alpha); - entropy_xy1.direction[i].red-=(cooccurrence[x][y].direction[i].red* - MagickLog10(density_x[x].direction[i].red*density_y[y].direction[i].red)); - entropy_xy1.direction[i].green-=(cooccurrence[x][y].direction[i].green* - MagickLog10(density_x[x].direction[i].green* - density_y[y].direction[i].green)); - entropy_xy1.direction[i].blue-=(cooccurrence[x][y].direction[i].blue* - MagickLog10(density_x[x].direction[i].blue*density_y[y].direction[i].blue)); - if (image->colorspace == CMYKColorspace) - entropy_xy1.direction[i].black-=( - cooccurrence[x][y].direction[i].black*MagickLog10( - density_x[x].direction[i].black*density_y[y].direction[i].black)); - if (image->alpha_trait != UndefinedPixelTrait) - entropy_xy1.direction[i].alpha-=( - cooccurrence[x][y].direction[i].alpha*MagickLog10( - density_x[x].direction[i].alpha*density_y[y].direction[i].alpha)); - entropy_xy2.direction[i].red-=(density_x[x].direction[i].red* - density_y[y].direction[i].red*MagickLog10(density_x[x].direction[i].red* - density_y[y].direction[i].red)); - entropy_xy2.direction[i].green-=(density_x[x].direction[i].green* - density_y[y].direction[i].green*MagickLog10(density_x[x].direction[i].green* - density_y[y].direction[i].green)); - entropy_xy2.direction[i].blue-=(density_x[x].direction[i].blue* - density_y[y].direction[i].blue*MagickLog10(density_x[x].direction[i].blue* - density_y[y].direction[i].blue)); - if (image->colorspace == CMYKColorspace) - entropy_xy2.direction[i].black-=(density_x[x].direction[i].black* - density_y[y].direction[i].black*MagickLog10( - density_x[x].direction[i].black*density_y[y].direction[i].black)); - if (image->alpha_trait != UndefinedPixelTrait) - entropy_xy2.direction[i].alpha-=(density_x[x].direction[i].alpha* - density_y[y].direction[i].alpha*MagickLog10( - density_x[x].direction[i].alpha*density_y[y].direction[i].alpha)); - } - } - channel_features[RedPixelChannel].variance_sum_of_squares[i]= - variance.direction[i].red; - channel_features[GreenPixelChannel].variance_sum_of_squares[i]= - variance.direction[i].green; - channel_features[BluePixelChannel].variance_sum_of_squares[i]= - variance.direction[i].blue; - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].variance_sum_of_squares[i]= - variance.direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].variance_sum_of_squares[i]= - variance.direction[i].alpha; - } - /* - Compute more texture features. - */ - (void) memset(&variance,0,sizeof(variance)); - (void) memset(&sum_squares,0,sizeof(sum_squares)); -#if defined(MAGICKCORE_OPENMP_SUPPORT) - #pragma omp parallel for schedule(static) shared(status) \ - magick_number_threads(image,image,number_grays,1) -#endif - for (i=0; i < 4; i++) - { - register ssize_t - x; - - for (x=0; x < (ssize_t) number_grays; x++) - { - /* - Difference variance. - */ - variance.direction[i].red+=density_xy[x].direction[i].red; - variance.direction[i].green+=density_xy[x].direction[i].green; - variance.direction[i].blue+=density_xy[x].direction[i].blue; - if (image->colorspace == CMYKColorspace) - variance.direction[i].black+=density_xy[x].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - variance.direction[i].alpha+=density_xy[x].direction[i].alpha; - sum_squares.direction[i].red+=density_xy[x].direction[i].red* - density_xy[x].direction[i].red; - sum_squares.direction[i].green+=density_xy[x].direction[i].green* - density_xy[x].direction[i].green; - sum_squares.direction[i].blue+=density_xy[x].direction[i].blue* - density_xy[x].direction[i].blue; - if (image->colorspace == CMYKColorspace) - sum_squares.direction[i].black+=density_xy[x].direction[i].black* - density_xy[x].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - sum_squares.direction[i].alpha+=density_xy[x].direction[i].alpha* - density_xy[x].direction[i].alpha; - /* - Difference entropy. - */ - channel_features[RedPixelChannel].difference_entropy[i]-= - density_xy[x].direction[i].red* - MagickLog10(density_xy[x].direction[i].red); - channel_features[GreenPixelChannel].difference_entropy[i]-= - density_xy[x].direction[i].green* - MagickLog10(density_xy[x].direction[i].green); - channel_features[BluePixelChannel].difference_entropy[i]-= - density_xy[x].direction[i].blue* - MagickLog10(density_xy[x].direction[i].blue); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].difference_entropy[i]-= - density_xy[x].direction[i].black* - MagickLog10(density_xy[x].direction[i].black); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].difference_entropy[i]-= - density_xy[x].direction[i].alpha* - MagickLog10(density_xy[x].direction[i].alpha); - /* - Information Measures of Correlation. - */ - entropy_x.direction[i].red-=(density_x[x].direction[i].red* - MagickLog10(density_x[x].direction[i].red)); - entropy_x.direction[i].green-=(density_x[x].direction[i].green* - MagickLog10(density_x[x].direction[i].green)); - entropy_x.direction[i].blue-=(density_x[x].direction[i].blue* - MagickLog10(density_x[x].direction[i].blue)); - if (image->colorspace == CMYKColorspace) - entropy_x.direction[i].black-=(density_x[x].direction[i].black* - MagickLog10(density_x[x].direction[i].black)); - if (image->alpha_trait != UndefinedPixelTrait) - entropy_x.direction[i].alpha-=(density_x[x].direction[i].alpha* - MagickLog10(density_x[x].direction[i].alpha)); - entropy_y.direction[i].red-=(density_y[x].direction[i].red* - MagickLog10(density_y[x].direction[i].red)); - entropy_y.direction[i].green-=(density_y[x].direction[i].green* - MagickLog10(density_y[x].direction[i].green)); - entropy_y.direction[i].blue-=(density_y[x].direction[i].blue* - MagickLog10(density_y[x].direction[i].blue)); - if (image->colorspace == CMYKColorspace) - entropy_y.direction[i].black-=(density_y[x].direction[i].black* - MagickLog10(density_y[x].direction[i].black)); - if (image->alpha_trait != UndefinedPixelTrait) - entropy_y.direction[i].alpha-=(density_y[x].direction[i].alpha* - MagickLog10(density_y[x].direction[i].alpha)); - } - /* - Difference variance. - */ - channel_features[RedPixelChannel].difference_variance[i]= - (((double) number_grays*number_grays*sum_squares.direction[i].red)- - (variance.direction[i].red*variance.direction[i].red))/ - ((double) number_grays*number_grays*number_grays*number_grays); - channel_features[GreenPixelChannel].difference_variance[i]= - (((double) number_grays*number_grays*sum_squares.direction[i].green)- - (variance.direction[i].green*variance.direction[i].green))/ - ((double) number_grays*number_grays*number_grays*number_grays); - channel_features[BluePixelChannel].difference_variance[i]= - (((double) number_grays*number_grays*sum_squares.direction[i].blue)- - (variance.direction[i].blue*variance.direction[i].blue))/ - ((double) number_grays*number_grays*number_grays*number_grays); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].difference_variance[i]= - (((double) number_grays*number_grays*sum_squares.direction[i].black)- - (variance.direction[i].black*variance.direction[i].black))/ - ((double) number_grays*number_grays*number_grays*number_grays); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].difference_variance[i]= - (((double) number_grays*number_grays*sum_squares.direction[i].alpha)- - (variance.direction[i].alpha*variance.direction[i].alpha))/ - ((double) number_grays*number_grays*number_grays*number_grays); - /* - Information Measures of Correlation. - */ - channel_features[RedPixelChannel].measure_of_correlation_1[i]= - (entropy_xy.direction[i].red-entropy_xy1.direction[i].red)/ - (entropy_x.direction[i].red > entropy_y.direction[i].red ? - entropy_x.direction[i].red : entropy_y.direction[i].red); - channel_features[GreenPixelChannel].measure_of_correlation_1[i]= - (entropy_xy.direction[i].green-entropy_xy1.direction[i].green)/ - (entropy_x.direction[i].green > entropy_y.direction[i].green ? - entropy_x.direction[i].green : entropy_y.direction[i].green); - channel_features[BluePixelChannel].measure_of_correlation_1[i]= - (entropy_xy.direction[i].blue-entropy_xy1.direction[i].blue)/ - (entropy_x.direction[i].blue > entropy_y.direction[i].blue ? - entropy_x.direction[i].blue : entropy_y.direction[i].blue); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].measure_of_correlation_1[i]= - (entropy_xy.direction[i].black-entropy_xy1.direction[i].black)/ - (entropy_x.direction[i].black > entropy_y.direction[i].black ? - entropy_x.direction[i].black : entropy_y.direction[i].black); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].measure_of_correlation_1[i]= - (entropy_xy.direction[i].alpha-entropy_xy1.direction[i].alpha)/ - (entropy_x.direction[i].alpha > entropy_y.direction[i].alpha ? - entropy_x.direction[i].alpha : entropy_y.direction[i].alpha); - channel_features[RedPixelChannel].measure_of_correlation_2[i]= - (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].red- - entropy_xy.direction[i].red))))); - channel_features[GreenPixelChannel].measure_of_correlation_2[i]= - (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].green- - entropy_xy.direction[i].green))))); - channel_features[BluePixelChannel].measure_of_correlation_2[i]= - (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].blue- - entropy_xy.direction[i].blue))))); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].measure_of_correlation_2[i]= - (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].black- - entropy_xy.direction[i].black))))); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].measure_of_correlation_2[i]= - (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].alpha- - entropy_xy.direction[i].alpha))))); - } - /* - Compute more texture features. - */ -#if defined(MAGICKCORE_OPENMP_SUPPORT) - #pragma omp parallel for schedule(static) shared(status) \ - magick_number_threads(image,image,number_grays,1) -#endif - for (i=0; i < 4; i++) - { - ssize_t - z; - - for (z=0; z < (ssize_t) number_grays; z++) - { - register ssize_t - y; - - ChannelStatistics - pixel; - - (void) memset(&pixel,0,sizeof(pixel)); - for (y=0; y < (ssize_t) number_grays; y++) - { register ssize_t - x; + y; + + for (y=0; y < (ssize_t) number_grays; y++) + { + register ssize_t + x; + + for (x=0; x < (ssize_t) number_grays; x++) + { + /* + Angular second moment: measure of homogeneity of the image. + */ + channel_features[RedPixelChannel].angular_second_moment[i]+= + cooccurrence[x][y].direction[i].red* + cooccurrence[x][y].direction[i].red; + channel_features[GreenPixelChannel].angular_second_moment[i]+= + cooccurrence[x][y].direction[i].green* + cooccurrence[x][y].direction[i].green; + channel_features[BluePixelChannel].angular_second_moment[i]+= + cooccurrence[x][y].direction[i].blue* + cooccurrence[x][y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].angular_second_moment[i]+= + cooccurrence[x][y].direction[i].black* + cooccurrence[x][y].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].angular_second_moment[i]+= + cooccurrence[x][y].direction[i].alpha* + cooccurrence[x][y].direction[i].alpha; + /* + Correlation: measure of linear-dependencies in the image. + */ + sum[y].direction[i].red+=cooccurrence[x][y].direction[i].red; + sum[y].direction[i].green+=cooccurrence[x][y].direction[i].green; + sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + sum[y].direction[i].black+=cooccurrence[x][y].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + sum[y].direction[i].alpha+=cooccurrence[x][y].direction[i].alpha; + correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red; + correlation.direction[i].green+=x*y* + cooccurrence[x][y].direction[i].green; + correlation.direction[i].blue+=x*y* + cooccurrence[x][y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + correlation.direction[i].black+=x*y* + cooccurrence[x][y].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + correlation.direction[i].alpha+=x*y* + cooccurrence[x][y].direction[i].alpha; + /* + Inverse Difference Moment. + */ + channel_features[RedPixelChannel].inverse_difference_moment[i]+= + cooccurrence[x][y].direction[i].red/((y-x)*(y-x)+1); + channel_features[GreenPixelChannel].inverse_difference_moment[i]+= + cooccurrence[x][y].direction[i].green/((y-x)*(y-x)+1); + channel_features[BluePixelChannel].inverse_difference_moment[i]+= + cooccurrence[x][y].direction[i].blue/((y-x)*(y-x)+1); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].inverse_difference_moment[i]+= + cooccurrence[x][y].direction[i].black/((y-x)*(y-x)+1); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].inverse_difference_moment[i]+= + cooccurrence[x][y].direction[i].alpha/((y-x)*(y-x)+1); + /* + Sum average. + */ + density_xy[y+x+2].direction[i].red+= + cooccurrence[x][y].direction[i].red; + density_xy[y+x+2].direction[i].green+= + cooccurrence[x][y].direction[i].green; + density_xy[y+x+2].direction[i].blue+= + cooccurrence[x][y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + density_xy[y+x+2].direction[i].black+= + cooccurrence[x][y].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + density_xy[y+x+2].direction[i].alpha+= + cooccurrence[x][y].direction[i].alpha; + /* + Entropy. + */ + channel_features[RedPixelChannel].entropy[i]-= + cooccurrence[x][y].direction[i].red* + MagickLog10(cooccurrence[x][y].direction[i].red); + channel_features[GreenPixelChannel].entropy[i]-= + cooccurrence[x][y].direction[i].green* + MagickLog10(cooccurrence[x][y].direction[i].green); + channel_features[BluePixelChannel].entropy[i]-= + cooccurrence[x][y].direction[i].blue* + MagickLog10(cooccurrence[x][y].direction[i].blue); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].entropy[i]-= + cooccurrence[x][y].direction[i].black* + MagickLog10(cooccurrence[x][y].direction[i].black); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].entropy[i]-= + cooccurrence[x][y].direction[i].alpha* + MagickLog10(cooccurrence[x][y].direction[i].alpha); + /* + Information Measures of Correlation. + */ + density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red; + density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green; + density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue; + if (image->alpha_trait != UndefinedPixelTrait) + density_x[x].direction[i].alpha+= + cooccurrence[x][y].direction[i].alpha; + if (image->colorspace == CMYKColorspace) + density_x[x].direction[i].black+= + cooccurrence[x][y].direction[i].black; + density_y[y].direction[i].red+=cooccurrence[x][y].direction[i].red; + density_y[y].direction[i].green+=cooccurrence[x][y].direction[i].green; + density_y[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + density_y[y].direction[i].black+= + cooccurrence[x][y].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + density_y[y].direction[i].alpha+= + cooccurrence[x][y].direction[i].alpha; + } + mean.direction[i].red+=y*sum[y].direction[i].red; + sum_squares.direction[i].red+=y*y*sum[y].direction[i].red; + mean.direction[i].green+=y*sum[y].direction[i].green; + sum_squares.direction[i].green+=y*y*sum[y].direction[i].green; + mean.direction[i].blue+=y*sum[y].direction[i].blue; + sum_squares.direction[i].blue+=y*y*sum[y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + { + mean.direction[i].black+=y*sum[y].direction[i].black; + sum_squares.direction[i].black+=y*y*sum[y].direction[i].black; + } + if (image->alpha_trait != UndefinedPixelTrait) + { + mean.direction[i].alpha+=y*sum[y].direction[i].alpha; + sum_squares.direction[i].alpha+=y*y*sum[y].direction[i].alpha; + } + } + /* + Correlation: measure of linear-dependencies in the image. + */ + channel_features[RedPixelChannel].correlation[i]= + (correlation.direction[i].red-mean.direction[i].red* + mean.direction[i].red)/(sqrt(sum_squares.direction[i].red- + (mean.direction[i].red*mean.direction[i].red))*sqrt( + sum_squares.direction[i].red-(mean.direction[i].red* + mean.direction[i].red))); + channel_features[GreenPixelChannel].correlation[i]= + (correlation.direction[i].green-mean.direction[i].green* + mean.direction[i].green)/(sqrt(sum_squares.direction[i].green- + (mean.direction[i].green*mean.direction[i].green))*sqrt( + sum_squares.direction[i].green-(mean.direction[i].green* + mean.direction[i].green))); + channel_features[BluePixelChannel].correlation[i]= + (correlation.direction[i].blue-mean.direction[i].blue* + mean.direction[i].blue)/(sqrt(sum_squares.direction[i].blue- + (mean.direction[i].blue*mean.direction[i].blue))*sqrt( + sum_squares.direction[i].blue-(mean.direction[i].blue* + mean.direction[i].blue))); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].correlation[i]= + (correlation.direction[i].black-mean.direction[i].black* + mean.direction[i].black)/(sqrt(sum_squares.direction[i].black- + (mean.direction[i].black*mean.direction[i].black))*sqrt( + sum_squares.direction[i].black-(mean.direction[i].black* + mean.direction[i].black))); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].correlation[i]= + (correlation.direction[i].alpha-mean.direction[i].alpha* + mean.direction[i].alpha)/(sqrt(sum_squares.direction[i].alpha- + (mean.direction[i].alpha*mean.direction[i].alpha))*sqrt( + sum_squares.direction[i].alpha-(mean.direction[i].alpha* + mean.direction[i].alpha))); + } + /* + Compute more texture features. + */ +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(static) shared(status) \ + magick_number_threads(image,image,number_grays,1) +#endif + for (i=0; i < 4; i++) + { + register ssize_t + x; + + for (x=2; x < (ssize_t) (2*number_grays); x++) + { + /* + Sum average. + */ + channel_features[RedPixelChannel].sum_average[i]+= + x*density_xy[x].direction[i].red; + channel_features[GreenPixelChannel].sum_average[i]+= + x*density_xy[x].direction[i].green; + channel_features[BluePixelChannel].sum_average[i]+= + x*density_xy[x].direction[i].blue; + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].sum_average[i]+= + x*density_xy[x].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].sum_average[i]+= + x*density_xy[x].direction[i].alpha; + /* + Sum entropy. + */ + channel_features[RedPixelChannel].sum_entropy[i]-= + density_xy[x].direction[i].red* + MagickLog10(density_xy[x].direction[i].red); + channel_features[GreenPixelChannel].sum_entropy[i]-= + density_xy[x].direction[i].green* + MagickLog10(density_xy[x].direction[i].green); + channel_features[BluePixelChannel].sum_entropy[i]-= + density_xy[x].direction[i].blue* + MagickLog10(density_xy[x].direction[i].blue); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].sum_entropy[i]-= + density_xy[x].direction[i].black* + MagickLog10(density_xy[x].direction[i].black); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].sum_entropy[i]-= + density_xy[x].direction[i].alpha* + MagickLog10(density_xy[x].direction[i].alpha); + /* + Sum variance. + */ + channel_features[RedPixelChannel].sum_variance[i]+= + (x-channel_features[RedPixelChannel].sum_entropy[i])* + (x-channel_features[RedPixelChannel].sum_entropy[i])* + density_xy[x].direction[i].red; + channel_features[GreenPixelChannel].sum_variance[i]+= + (x-channel_features[GreenPixelChannel].sum_entropy[i])* + (x-channel_features[GreenPixelChannel].sum_entropy[i])* + density_xy[x].direction[i].green; + channel_features[BluePixelChannel].sum_variance[i]+= + (x-channel_features[BluePixelChannel].sum_entropy[i])* + (x-channel_features[BluePixelChannel].sum_entropy[i])* + density_xy[x].direction[i].blue; + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].sum_variance[i]+= + (x-channel_features[BlackPixelChannel].sum_entropy[i])* + (x-channel_features[BlackPixelChannel].sum_entropy[i])* + density_xy[x].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].sum_variance[i]+= + (x-channel_features[AlphaPixelChannel].sum_entropy[i])* + (x-channel_features[AlphaPixelChannel].sum_entropy[i])* + density_xy[x].direction[i].alpha; + } + } + /* + Compute more texture features. + */ +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(static) shared(status) \ + magick_number_threads(image,image,number_grays,1) +#endif + for (i=0; i < 4; i++) + { + register ssize_t + y; + + for (y=0; y < (ssize_t) number_grays; y++) + { + register ssize_t + x; + + for (x=0; x < (ssize_t) number_grays; x++) + { + /* + Sum of Squares: Variance + */ + variance.direction[i].red+=(y-mean.direction[i].red+1)* + (y-mean.direction[i].red+1)*cooccurrence[x][y].direction[i].red; + variance.direction[i].green+=(y-mean.direction[i].green+1)* + (y-mean.direction[i].green+1)*cooccurrence[x][y].direction[i].green; + variance.direction[i].blue+=(y-mean.direction[i].blue+1)* + (y-mean.direction[i].blue+1)*cooccurrence[x][y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + variance.direction[i].black+=(y-mean.direction[i].black+1)* + (y-mean.direction[i].black+1)*cooccurrence[x][y].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + variance.direction[i].alpha+=(y-mean.direction[i].alpha+1)* + (y-mean.direction[i].alpha+1)* + cooccurrence[x][y].direction[i].alpha; + /* + Sum average / Difference Variance. + */ + density_xy[MagickAbsoluteValue(y-x)].direction[i].red+= + cooccurrence[x][y].direction[i].red; + density_xy[MagickAbsoluteValue(y-x)].direction[i].green+= + cooccurrence[x][y].direction[i].green; + density_xy[MagickAbsoluteValue(y-x)].direction[i].blue+= + cooccurrence[x][y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + density_xy[MagickAbsoluteValue(y-x)].direction[i].black+= + cooccurrence[x][y].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + density_xy[MagickAbsoluteValue(y-x)].direction[i].alpha+= + cooccurrence[x][y].direction[i].alpha; + /* + Information Measures of Correlation. + */ + entropy_xy.direction[i].red-=cooccurrence[x][y].direction[i].red* + MagickLog10(cooccurrence[x][y].direction[i].red); + entropy_xy.direction[i].green-=cooccurrence[x][y].direction[i].green* + MagickLog10(cooccurrence[x][y].direction[i].green); + entropy_xy.direction[i].blue-=cooccurrence[x][y].direction[i].blue* + MagickLog10(cooccurrence[x][y].direction[i].blue); + if (image->colorspace == CMYKColorspace) + entropy_xy.direction[i].black-=cooccurrence[x][y].direction[i].black* + MagickLog10(cooccurrence[x][y].direction[i].black); + if (image->alpha_trait != UndefinedPixelTrait) + entropy_xy.direction[i].alpha-= + cooccurrence[x][y].direction[i].alpha*MagickLog10( + cooccurrence[x][y].direction[i].alpha); + entropy_xy1.direction[i].red-=(cooccurrence[x][y].direction[i].red* + MagickLog10(density_x[x].direction[i].red*density_y[y].direction[i].red)); + entropy_xy1.direction[i].green-=(cooccurrence[x][y].direction[i].green* + MagickLog10(density_x[x].direction[i].green* + density_y[y].direction[i].green)); + entropy_xy1.direction[i].blue-=(cooccurrence[x][y].direction[i].blue* + MagickLog10(density_x[x].direction[i].blue*density_y[y].direction[i].blue)); + if (image->colorspace == CMYKColorspace) + entropy_xy1.direction[i].black-=( + cooccurrence[x][y].direction[i].black*MagickLog10( + density_x[x].direction[i].black*density_y[y].direction[i].black)); + if (image->alpha_trait != UndefinedPixelTrait) + entropy_xy1.direction[i].alpha-=( + cooccurrence[x][y].direction[i].alpha*MagickLog10( + density_x[x].direction[i].alpha*density_y[y].direction[i].alpha)); + entropy_xy2.direction[i].red-=(density_x[x].direction[i].red* + density_y[y].direction[i].red*MagickLog10(density_x[x].direction[i].red* + density_y[y].direction[i].red)); + entropy_xy2.direction[i].green-=(density_x[x].direction[i].green* + density_y[y].direction[i].green*MagickLog10(density_x[x].direction[i].green* + density_y[y].direction[i].green)); + entropy_xy2.direction[i].blue-=(density_x[x].direction[i].blue* + density_y[y].direction[i].blue*MagickLog10(density_x[x].direction[i].blue* + density_y[y].direction[i].blue)); + if (image->colorspace == CMYKColorspace) + entropy_xy2.direction[i].black-=(density_x[x].direction[i].black* + density_y[y].direction[i].black*MagickLog10( + density_x[x].direction[i].black*density_y[y].direction[i].black)); + if (image->alpha_trait != UndefinedPixelTrait) + entropy_xy2.direction[i].alpha-=(density_x[x].direction[i].alpha* + density_y[y].direction[i].alpha*MagickLog10( + density_x[x].direction[i].alpha*density_y[y].direction[i].alpha)); + } + } + channel_features[RedPixelChannel].variance_sum_of_squares[i]= + variance.direction[i].red; + channel_features[GreenPixelChannel].variance_sum_of_squares[i]= + variance.direction[i].green; + channel_features[BluePixelChannel].variance_sum_of_squares[i]= + variance.direction[i].blue; + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].variance_sum_of_squares[i]= + variance.direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].variance_sum_of_squares[i]= + variance.direction[i].alpha; + } + /* + Compute more texture features. + */ + (void) memset(&variance,0,sizeof(variance)); + (void) memset(&sum_squares,0,sizeof(sum_squares)); +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(static) shared(status) \ + magick_number_threads(image,image,number_grays,1) +#endif + for (i=0; i < 4; i++) + { + register ssize_t + x; for (x=0; x < (ssize_t) number_grays; x++) { - /* - Contrast: amount of local variations present in an image. - */ - if (((y-x) == z) || ((x-y) == z)) - { - pixel.direction[i].red+=cooccurrence[x][y].direction[i].red; - pixel.direction[i].green+=cooccurrence[x][y].direction[i].green; - pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue; - if (image->colorspace == CMYKColorspace) - pixel.direction[i].black+=cooccurrence[x][y].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - pixel.direction[i].alpha+= - cooccurrence[x][y].direction[i].alpha; - } - /* - Maximum Correlation Coefficient. - */ - Q[z][y].direction[i].red+=cooccurrence[z][x].direction[i].red* - cooccurrence[y][x].direction[i].red/density_x[z].direction[i].red/ - density_y[x].direction[i].red; - Q[z][y].direction[i].green+=cooccurrence[z][x].direction[i].green* - cooccurrence[y][x].direction[i].green/ - density_x[z].direction[i].green/density_y[x].direction[i].red; - Q[z][y].direction[i].blue+=cooccurrence[z][x].direction[i].blue* - cooccurrence[y][x].direction[i].blue/density_x[z].direction[i].blue/ - density_y[x].direction[i].blue; - if (image->colorspace == CMYKColorspace) - Q[z][y].direction[i].black+=cooccurrence[z][x].direction[i].black* - cooccurrence[y][x].direction[i].black/ - density_x[z].direction[i].black/density_y[x].direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - Q[z][y].direction[i].alpha+= - cooccurrence[z][x].direction[i].alpha* - cooccurrence[y][x].direction[i].alpha/ - density_x[z].direction[i].alpha/ - density_y[x].direction[i].alpha; + /* + Difference variance. + */ + variance.direction[i].red+=density_xy[x].direction[i].red; + variance.direction[i].green+=density_xy[x].direction[i].green; + variance.direction[i].blue+=density_xy[x].direction[i].blue; + if (image->colorspace == CMYKColorspace) + variance.direction[i].black+=density_xy[x].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + variance.direction[i].alpha+=density_xy[x].direction[i].alpha; + sum_squares.direction[i].red+=density_xy[x].direction[i].red* + density_xy[x].direction[i].red; + sum_squares.direction[i].green+=density_xy[x].direction[i].green* + density_xy[x].direction[i].green; + sum_squares.direction[i].blue+=density_xy[x].direction[i].blue* + density_xy[x].direction[i].blue; + if (image->colorspace == CMYKColorspace) + sum_squares.direction[i].black+=density_xy[x].direction[i].black* + density_xy[x].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + sum_squares.direction[i].alpha+=density_xy[x].direction[i].alpha* + density_xy[x].direction[i].alpha; + /* + Difference entropy. + */ + channel_features[RedPixelChannel].difference_entropy[i]-= + density_xy[x].direction[i].red* + MagickLog10(density_xy[x].direction[i].red); + channel_features[GreenPixelChannel].difference_entropy[i]-= + density_xy[x].direction[i].green* + MagickLog10(density_xy[x].direction[i].green); + channel_features[BluePixelChannel].difference_entropy[i]-= + density_xy[x].direction[i].blue* + MagickLog10(density_xy[x].direction[i].blue); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].difference_entropy[i]-= + density_xy[x].direction[i].black* + MagickLog10(density_xy[x].direction[i].black); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].difference_entropy[i]-= + density_xy[x].direction[i].alpha* + MagickLog10(density_xy[x].direction[i].alpha); + /* + Information Measures of Correlation. + */ + entropy_x.direction[i].red-=(density_x[x].direction[i].red* + MagickLog10(density_x[x].direction[i].red)); + entropy_x.direction[i].green-=(density_x[x].direction[i].green* + MagickLog10(density_x[x].direction[i].green)); + entropy_x.direction[i].blue-=(density_x[x].direction[i].blue* + MagickLog10(density_x[x].direction[i].blue)); + if (image->colorspace == CMYKColorspace) + entropy_x.direction[i].black-=(density_x[x].direction[i].black* + MagickLog10(density_x[x].direction[i].black)); + if (image->alpha_trait != UndefinedPixelTrait) + entropy_x.direction[i].alpha-=(density_x[x].direction[i].alpha* + MagickLog10(density_x[x].direction[i].alpha)); + entropy_y.direction[i].red-=(density_y[x].direction[i].red* + MagickLog10(density_y[x].direction[i].red)); + entropy_y.direction[i].green-=(density_y[x].direction[i].green* + MagickLog10(density_y[x].direction[i].green)); + entropy_y.direction[i].blue-=(density_y[x].direction[i].blue* + MagickLog10(density_y[x].direction[i].blue)); + if (image->colorspace == CMYKColorspace) + entropy_y.direction[i].black-=(density_y[x].direction[i].black* + MagickLog10(density_y[x].direction[i].black)); + if (image->alpha_trait != UndefinedPixelTrait) + entropy_y.direction[i].alpha-=(density_y[x].direction[i].alpha* + MagickLog10(density_y[x].direction[i].alpha)); } - } - channel_features[RedPixelChannel].contrast[i]+=z*z* - pixel.direction[i].red; - channel_features[GreenPixelChannel].contrast[i]+=z*z* - pixel.direction[i].green; - channel_features[BluePixelChannel].contrast[i]+=z*z* - pixel.direction[i].blue; - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].contrast[i]+=z*z* - pixel.direction[i].black; - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].contrast[i]+=z*z* - pixel.direction[i].alpha; + /* + Difference variance. + */ + channel_features[RedPixelChannel].difference_variance[i]= + (((double) number_grays*number_grays*sum_squares.direction[i].red)- + (variance.direction[i].red*variance.direction[i].red))/ + ((double) number_grays*number_grays*number_grays*number_grays); + channel_features[GreenPixelChannel].difference_variance[i]= + (((double) number_grays*number_grays*sum_squares.direction[i].green)- + (variance.direction[i].green*variance.direction[i].green))/ + ((double) number_grays*number_grays*number_grays*number_grays); + channel_features[BluePixelChannel].difference_variance[i]= + (((double) number_grays*number_grays*sum_squares.direction[i].blue)- + (variance.direction[i].blue*variance.direction[i].blue))/ + ((double) number_grays*number_grays*number_grays*number_grays); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].difference_variance[i]= + (((double) number_grays*number_grays*sum_squares.direction[i].black)- + (variance.direction[i].black*variance.direction[i].black))/ + ((double) number_grays*number_grays*number_grays*number_grays); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].difference_variance[i]= + (((double) number_grays*number_grays*sum_squares.direction[i].alpha)- + (variance.direction[i].alpha*variance.direction[i].alpha))/ + ((double) number_grays*number_grays*number_grays*number_grays); + /* + Information Measures of Correlation. + */ + channel_features[RedPixelChannel].measure_of_correlation_1[i]= + (entropy_xy.direction[i].red-entropy_xy1.direction[i].red)/ + (entropy_x.direction[i].red > entropy_y.direction[i].red ? + entropy_x.direction[i].red : entropy_y.direction[i].red); + channel_features[GreenPixelChannel].measure_of_correlation_1[i]= + (entropy_xy.direction[i].green-entropy_xy1.direction[i].green)/ + (entropy_x.direction[i].green > entropy_y.direction[i].green ? + entropy_x.direction[i].green : entropy_y.direction[i].green); + channel_features[BluePixelChannel].measure_of_correlation_1[i]= + (entropy_xy.direction[i].blue-entropy_xy1.direction[i].blue)/ + (entropy_x.direction[i].blue > entropy_y.direction[i].blue ? + entropy_x.direction[i].blue : entropy_y.direction[i].blue); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].measure_of_correlation_1[i]= + (entropy_xy.direction[i].black-entropy_xy1.direction[i].black)/ + (entropy_x.direction[i].black > entropy_y.direction[i].black ? + entropy_x.direction[i].black : entropy_y.direction[i].black); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].measure_of_correlation_1[i]= + (entropy_xy.direction[i].alpha-entropy_xy1.direction[i].alpha)/ + (entropy_x.direction[i].alpha > entropy_y.direction[i].alpha ? + entropy_x.direction[i].alpha : entropy_y.direction[i].alpha); + channel_features[RedPixelChannel].measure_of_correlation_2[i]= + (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].red- + entropy_xy.direction[i].red))))); + channel_features[GreenPixelChannel].measure_of_correlation_2[i]= + (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].green- + entropy_xy.direction[i].green))))); + channel_features[BluePixelChannel].measure_of_correlation_2[i]= + (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].blue- + entropy_xy.direction[i].blue))))); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].measure_of_correlation_2[i]= + (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].black- + entropy_xy.direction[i].black))))); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].measure_of_correlation_2[i]= + (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].alpha- + entropy_xy.direction[i].alpha))))); } /* - Maximum Correlation Coefficient. - Future: return second largest eigenvalue of Q. - */ - channel_features[RedPixelChannel].maximum_correlation_coefficient[i]= - sqrt((double) -1.0); - channel_features[GreenPixelChannel].maximum_correlation_coefficient[i]= - sqrt((double) -1.0); - channel_features[BluePixelChannel].maximum_correlation_coefficient[i]= - sqrt((double) -1.0); - if (image->colorspace == CMYKColorspace) - channel_features[BlackPixelChannel].maximum_correlation_coefficient[i]= - sqrt((double) -1.0); - if (image->alpha_trait != UndefinedPixelTrait) - channel_features[AlphaPixelChannel].maximum_correlation_coefficient[i]= - sqrt((double) -1.0); - } - /* - Relinquish resources. - */ - sum=(ChannelStatistics *) RelinquishMagickMemory(sum); - for (i=0; i < (ssize_t) number_grays; i++) - Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); - Q=(ChannelStatistics **) RelinquishMagickMemory(Q); - density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); - density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); - density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); - for (i=0; i < (ssize_t) number_grays; i++) - cooccurrence[i]=(ChannelStatistics *) - RelinquishMagickMemory(cooccurrence[i]); - cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); - return(channel_features); + Compute more texture features. + */ +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(static) shared(status) \ + magick_number_threads(image,image,number_grays,1) +#endif + for (i=0; i < 4; i++) + { + ssize_t + z; + + for (z=0; z < (ssize_t) number_grays; z++) + { + register ssize_t + y; + + ChannelStatistics + pixel; + + (void) memset(&pixel,0,sizeof(pixel)); + for (y=0; y < (ssize_t) number_grays; y++) + { + register ssize_t + x; + + for (x=0; x < (ssize_t) number_grays; x++) + { + /* + Contrast: amount of local variations present in an image. + */ + if (((y-x) == z) || ((x-y) == z)) + { + pixel.direction[i].red+=cooccurrence[x][y].direction[i].red; + pixel.direction[i].green+=cooccurrence[x][y].direction[i].green; + pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue; + if (image->colorspace == CMYKColorspace) + pixel.direction[i].black+=cooccurrence[x][y].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + pixel.direction[i].alpha+= + cooccurrence[x][y].direction[i].alpha; + } + /* + Maximum Correlation Coefficient. + */ + Q[z][y].direction[i].red+=cooccurrence[z][x].direction[i].red* + cooccurrence[y][x].direction[i].red/density_x[z].direction[i].red/ + density_y[x].direction[i].red; + Q[z][y].direction[i].green+=cooccurrence[z][x].direction[i].green* + cooccurrence[y][x].direction[i].green/ + density_x[z].direction[i].green/density_y[x].direction[i].red; + Q[z][y].direction[i].blue+=cooccurrence[z][x].direction[i].blue* + cooccurrence[y][x].direction[i].blue/density_x[z].direction[i].blue/ + density_y[x].direction[i].blue; + if (image->colorspace == CMYKColorspace) + Q[z][y].direction[i].black+=cooccurrence[z][x].direction[i].black* + cooccurrence[y][x].direction[i].black/ + density_x[z].direction[i].black/density_y[x].direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + Q[z][y].direction[i].alpha+= + cooccurrence[z][x].direction[i].alpha* + cooccurrence[y][x].direction[i].alpha/ + density_x[z].direction[i].alpha/ + density_y[x].direction[i].alpha; + } + } + channel_features[RedPixelChannel].contrast[i]+=z*z* + pixel.direction[i].red; + channel_features[GreenPixelChannel].contrast[i]+=z*z* + pixel.direction[i].green; + channel_features[BluePixelChannel].contrast[i]+=z*z* + pixel.direction[i].blue; + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].contrast[i]+=z*z* + pixel.direction[i].black; + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].contrast[i]+=z*z* + pixel.direction[i].alpha; + } + /* + Maximum Correlation Coefficient. + Future: return second largest eigenvalue of Q. + */ + channel_features[RedPixelChannel].maximum_correlation_coefficient[i]= + sqrt((double) -1.0); + channel_features[GreenPixelChannel].maximum_correlation_coefficient[i]= + sqrt((double) -1.0); + channel_features[BluePixelChannel].maximum_correlation_coefficient[i]= + sqrt((double) -1.0); + if (image->colorspace == CMYKColorspace) + channel_features[BlackPixelChannel].maximum_correlation_coefficient[i]= + sqrt((double) -1.0); + if (image->alpha_trait != UndefinedPixelTrait) + channel_features[AlphaPixelChannel].maximum_correlation_coefficient[i]= + sqrt((double) -1.0); + } + /* + Relinquish resources. + */ + sum=(ChannelStatistics *) RelinquishMagickMemory(sum); + for (i=0; i < (ssize_t) number_grays; i++) + Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); + Q=(ChannelStatistics **) RelinquishMagickMemory(Q); + density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); + density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); + density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); + for (i=0; i < (ssize_t) number_grays; i++) + cooccurrence[i]=(ChannelStatistics *) + RelinquishMagickMemory(cooccurrence[i]); + cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); + return(channel_features); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% H o u g h L i n e I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% Use HoughLineImage() in conjunction with any binary edge extracted image (we -% recommand Canny) to identify lines in the image. The algorithm accumulates -% counts for every white pixel for every possible orientation (for angles from -% 0 to 179 in 1 degree increments) and distance from the center of the image to -% the corner (in 1 px increments) and stores the counts in an accumulator -% matrix of angle vs distance. The size of the accumulator is 180x(diagonal/2). -% Next it searches this space for peaks in counts and converts the locations -% of the peaks to slope and intercept in the normal x,y input image space. Use -% the slope/intercepts to find the endpoints clipped to the bounds of the -% image. The lines are then drawn. The counts are a measure of the length of -% the lines. -% -% The format of the HoughLineImage method is: -% -% Image *HoughLineImage(const Image *image,const size_t width, -% const size_t height,const size_t threshold,ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image. -% -% o width, height: find line pairs as local maxima in this neighborhood. -% -% o threshold: the line count threshold. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % H o u g h L i n e I m a g e % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % Use HoughLineImage() in conjunction with any binary edge extracted image (we + % recommand Canny) to identify lines in the image. The algorithm accumulates + % counts for every white pixel for every possible orientation (for angles from + % 0 to 179 in 1 degree increments) and distance from the center of the image to + % the corner (in 1 px increments) and stores the counts in an accumulator + % matrix of angle vs distance. The size of the accumulator is 180x(diagonal/2). + % Next it searches this space for peaks in counts and converts the locations + % of the peaks to slope and intercept in the normal x,y input image space. Use + % the slope/intercepts to find the endpoints clipped to the bounds of the + % image. The lines are then drawn. The counts are a measure of the length of + % the lines. + % + % The format of the HoughLineImage method is: + % + % Image *HoughLineImage(const Image *image,const size_t width, + % const size_t height,const size_t threshold,ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image. + % + % o width, height: find line pairs as local maxima in this neighborhood. + % + % o threshold: the line count threshold. + % + % o exception: return any errors or warnings in this structure. + % + */ static inline double MagickRound(double x) { - /* - Round the fraction to nearest integer. - */ - if ((x-floor(x)) < (ceil(x)-x)) - return(floor(x)); - return(ceil(x)); + /* + Round the fraction to nearest integer. + */ + if ((x-floor(x)) < (ceil(x)-x)) + return(floor(x)); + return(ceil(x)); } static Image *RenderHoughLines(const ImageInfo *image_info,const size_t columns, - const size_t rows,ExceptionInfo *exception) + const size_t rows,ExceptionInfo *exception) { #define BoundingBox "viewbox" - DrawInfo + DrawInfo *draw_info; - Image + Image *image; - MagickBooleanType - status; + MagickBooleanType + status; - /* - Open image. - */ - image=AcquireImage(image_info,exception); - status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); - if (status == MagickFalse) + /* + Open image. + */ + image=AcquireImage(image_info,exception); + status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); + if (status == MagickFalse) { - image=DestroyImageList(image); - return((Image *) NULL); + image=DestroyImageList(image); + return((Image *) NULL); } - image->columns=columns; - image->rows=rows; - draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); - draw_info->affine.sx=image->resolution.x == 0.0 ? 1.0 : image->resolution.x/ - DefaultResolution; - draw_info->affine.sy=image->resolution.y == 0.0 ? 1.0 : image->resolution.y/ - DefaultResolution; - image->columns=(size_t) (draw_info->affine.sx*image->columns); - image->rows=(size_t) (draw_info->affine.sy*image->rows); - status=SetImageExtent(image,image->columns,image->rows,exception); - if (status == MagickFalse) - return(DestroyImageList(image)); - if (SetImageBackgroundColor(image,exception) == MagickFalse) + image->columns=columns; + image->rows=rows; + draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); + draw_info->affine.sx=image->resolution.x == 0.0 ? 1.0 : image->resolution.x/ + DefaultResolution; + draw_info->affine.sy=image->resolution.y == 0.0 ? 1.0 : image->resolution.y/ + DefaultResolution; + image->columns=(size_t) (draw_info->affine.sx*image->columns); + image->rows=(size_t) (draw_info->affine.sy*image->rows); + status=SetImageExtent(image,image->columns,image->rows,exception); + if (status == MagickFalse) + return(DestroyImageList(image)); + if (SetImageBackgroundColor(image,exception) == MagickFalse) { - image=DestroyImageList(image); - return((Image *) NULL); + image=DestroyImageList(image); + return((Image *) NULL); } - /* - Render drawing. - */ - if (GetBlobStreamData(image) == (unsigned char *) NULL) - draw_info->primitive=FileToString(image->filename,~0UL,exception); - else + /* + Render drawing. + */ + if (GetBlobStreamData(image) == (unsigned char *) NULL) + draw_info->primitive=FileToString(image->filename,~0UL,exception); + else { - draw_info->primitive=(char *) AcquireMagickMemory((size_t) - GetBlobSize(image)+1); - if (draw_info->primitive != (char *) NULL) + draw_info->primitive=(char *) AcquireMagickMemory((size_t) + GetBlobSize(image)+1); + if (draw_info->primitive != (char *) NULL) { - (void) memcpy(draw_info->primitive,GetBlobStreamData(image), - (size_t) GetBlobSize(image)); - draw_info->primitive[GetBlobSize(image)]='\0'; + (void) memcpy(draw_info->primitive,GetBlobStreamData(image), + (size_t) GetBlobSize(image)); + draw_info->primitive[GetBlobSize(image)]='\0'; } - } - (void) DrawImage(image,draw_info,exception); - draw_info=DestroyDrawInfo(draw_info); - (void) CloseBlob(image); - return(GetFirstImageInList(image)); + } + (void) DrawImage(image,draw_info,exception); + draw_info=DestroyDrawInfo(draw_info); + (void) CloseBlob(image); + return(GetFirstImageInList(image)); } MagickExport Image *HoughLineImage(const Image *image,const size_t width, - const size_t height,const size_t threshold,ExceptionInfo *exception) + const size_t height,const size_t threshold,ExceptionInfo *exception) { #define HoughLineImageTag "HoughLine/Image" - CacheView + CacheView *image_view; - char - message[MagickPathExtent], - path[MagickPathExtent]; + char + message[MagickPathExtent], + path[MagickPathExtent]; - const char + const char *artifact; - double - hough_height; + double + hough_height; - Image + Image *lines_image = NULL; - ImageInfo + ImageInfo *image_info; - int - file; + int + file; - MagickBooleanType - status; + MagickBooleanType + status; - MagickOffsetType - progress; + MagickOffsetType + progress; - MatrixInfo + MatrixInfo *accumulator; - PointInfo - center; - - register ssize_t - y; - - size_t - accumulator_height, - accumulator_width, - line_count; - - /* - Create the accumulator. - */ - assert(image != (const Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - accumulator_width=180; - hough_height=((sqrt(2.0)*(double) (image->rows > image->columns ? - image->rows : image->columns))/2.0); - accumulator_height=(size_t) (2.0*hough_height); - accumulator=AcquireMatrixInfo(accumulator_width,accumulator_height, - sizeof(double),exception); - if (accumulator == (MatrixInfo *) NULL) - ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); - if (NullMatrix(accumulator) == MagickFalse) - { - accumulator=DestroyMatrixInfo(accumulator); - ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); - } - /* - Populate the accumulator. - */ - status=MagickTrue; - progress=0; - center.x=(double) image->columns/2.0; - center.y=(double) image->rows/2.0; - image_view=AcquireVirtualCacheView(image,exception); - for (y=0; y < (ssize_t) image->rows; y++) - { - register const Quantum - *magick_restrict p; + PointInfo + center; register ssize_t - x; + y; - if (status == MagickFalse) - continue; - p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); - if (p == (Quantum *) NULL) - { - status=MagickFalse; - continue; - } - for (x=0; x < (ssize_t) image->columns; x++) + size_t + accumulator_height, + accumulator_width, + line_count; + + /* + Create the accumulator. + */ + assert(image != (const Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + accumulator_width=180; + hough_height=((sqrt(2.0)*(double) (image->rows > image->columns ? + image->rows : image->columns))/2.0); + accumulator_height=(size_t) (2.0*hough_height); + accumulator=AcquireMatrixInfo(accumulator_width,accumulator_height, + sizeof(double),exception); + if (accumulator == (MatrixInfo *) NULL) + ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); + if (NullMatrix(accumulator) == MagickFalse) { - if (GetPixelIntensity(image,p) > (QuantumRange/2.0)) - { - register ssize_t - i; - - for (i=0; i < 180; i++) - { - double - count, - radius; - - radius=(((double) x-center.x)*cos(DegreesToRadians((double) i)))+ - (((double) y-center.y)*sin(DegreesToRadians((double) i))); - (void) GetMatrixElement(accumulator,i,(ssize_t) - MagickRound(radius+hough_height),&count); - count++; - (void) SetMatrixElement(accumulator,i,(ssize_t) - MagickRound(radius+hough_height),&count); - } - } - p+=GetPixelChannels(image); + accumulator=DestroyMatrixInfo(accumulator); + ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); } - if (image->progress_monitor != (MagickProgressMonitor) NULL) - { - MagickBooleanType - proceed; + /* + Populate the accumulator. + */ + status=MagickTrue; + progress=0; + center.x=(double) image->columns/2.0; + center.y=(double) image->rows/2.0; + image_view=AcquireVirtualCacheView(image,exception); + for (y=0; y < (ssize_t) image->rows; y++) + { + register const Quantum + *magick_restrict p; + + register ssize_t + x; + + if (status == MagickFalse) + continue; + p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); + if (p == (Quantum *) NULL) + { + status=MagickFalse; + continue; + } + for (x=0; x < (ssize_t) image->columns; x++) + { + if (GetPixelIntensity(image,p) > (QuantumRange/2.0)) + { + register ssize_t + i; + + for (i=0; i < 180; i++) + { + double + count, + radius; + + radius=(((double) x-center.x)*cos(DegreesToRadians((double) i)))+ + (((double) y-center.y)*sin(DegreesToRadians((double) i))); + (void) GetMatrixElement(accumulator,i,(ssize_t) + MagickRound(radius+hough_height),&count); + count++; + (void) SetMatrixElement(accumulator,i,(ssize_t) + MagickRound(radius+hough_height),&count); + } + } + p+=GetPixelChannels(image); + } + if (image->progress_monitor != (MagickProgressMonitor) NULL) + { + MagickBooleanType + proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp atomic #endif - progress++; - proceed=SetImageProgress(image,CannyEdgeImageTag,progress,image->rows); - if (proceed == MagickFalse) - status=MagickFalse; - } - } - image_view=DestroyCacheView(image_view); - if (status == MagickFalse) - { - accumulator=DestroyMatrixInfo(accumulator); - return((Image *) NULL); - } - /* - Generate line segments from accumulator. - */ - file=AcquireUniqueFileResource(path); - if (file == -1) - { - accumulator=DestroyMatrixInfo(accumulator); - return((Image *) NULL); - } - (void) FormatLocaleString(message,MagickPathExtent, - "# Hough line transform: %.20gx%.20g%+.20g\n",(double) width, - (double) height,(double) threshold); - if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) - status=MagickFalse; - (void) FormatLocaleString(message,MagickPathExtent, - "viewbox 0 0 %.20g %.20g\n",(double) image->columns,(double) image->rows); - if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) - status=MagickFalse; - (void) FormatLocaleString(message,MagickPathExtent, - "# x1,y1 x2,y2 # count angle distance\n"); - if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) - status=MagickFalse; - line_count=image->columns > image->rows ? image->columns/4 : image->rows/4; - if (threshold != 0) - line_count=threshold; - for (y=0; y < (ssize_t) accumulator_height; y++) - { - register ssize_t - x; - - for (x=0; x < (ssize_t) accumulator_width; x++) - { - double - count; - - (void) GetMatrixElement(accumulator,x,y,&count); - if (count >= (double) line_count) - { - double - maxima; - - SegmentInfo - line; - - ssize_t - v; - - /* - Is point a local maxima? - */ - maxima=count; - for (v=(-((ssize_t) height/2)); v <= (((ssize_t) height/2)); v++) - { - ssize_t - u; - - for (u=(-((ssize_t) width/2)); u <= (((ssize_t) width/2)); u++) - { - if ((u != 0) || (v !=0)) - { - (void) GetMatrixElement(accumulator,x+u,y+v,&count); - if (count > maxima) - { - maxima=count; - break; - } - } - } - if (u < (ssize_t) (width/2)) - break; - } - (void) GetMatrixElement(accumulator,x,y,&count); - if (maxima > count) - continue; - if ((x >= 45) && (x <= 135)) - { - /* - y = (r-x cos(t))/sin(t) - */ - line.x1=0.0; - line.y1=((double) (y-(accumulator_height/2.0))-((line.x1- - (image->columns/2.0))*cos(DegreesToRadians((double) x))))/ - sin(DegreesToRadians((double) x))+(image->rows/2.0); - line.x2=(double) image->columns; - line.y2=((double) (y-(accumulator_height/2.0))-((line.x2- - (image->columns/2.0))*cos(DegreesToRadians((double) x))))/ - sin(DegreesToRadians((double) x))+(image->rows/2.0); - } - else - { - /* - x = (r-y cos(t))/sin(t) - */ - line.y1=0.0; - line.x1=((double) (y-(accumulator_height/2.0))-((line.y1- - (image->rows/2.0))*sin(DegreesToRadians((double) x))))/ - cos(DegreesToRadians((double) x))+(image->columns/2.0); - line.y2=(double) image->rows; - line.x2=((double) (y-(accumulator_height/2.0))-((line.y2- - (image->rows/2.0))*sin(DegreesToRadians((double) x))))/ - cos(DegreesToRadians((double) x))+(image->columns/2.0); - } - (void) FormatLocaleString(message,MagickPathExtent, - "line %g,%g %g,%g # %g %g %g\n",line.x1,line.y1,line.x2,line.y2, - maxima,(double) x,(double) y); - if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) - status=MagickFalse; + progress++; + proceed=SetImageProgress(image,CannyEdgeImageTag,progress,image->rows); + if (proceed == MagickFalse) + status=MagickFalse; } } - } - (void) close(file); - /* - Render lines to image canvas. - */ - image_info=AcquireImageInfo(); - image_info->background_color=image->background_color; - (void) FormatLocaleString(image_info->filename,MagickPathExtent,"%s",path); - artifact=GetImageArtifact(image,"background"); - if (artifact != (const char *) NULL) - (void) SetImageOption(image_info,"background",artifact); - artifact=GetImageArtifact(image,"fill"); - if (artifact != (const char *) NULL) - (void) SetImageOption(image_info,"fill",artifact); - artifact=GetImageArtifact(image,"stroke"); - if (artifact != (const char *) NULL) - (void) SetImageOption(image_info,"stroke",artifact); - artifact=GetImageArtifact(image,"strokewidth"); - if (artifact != (const char *) NULL) - (void) SetImageOption(image_info,"strokewidth",artifact); - lines_image=RenderHoughLines(image_info,image->columns,image->rows,exception); - artifact=GetImageArtifact(image,"hough-lines:accumulator"); - if ((lines_image != (Image *) NULL) && - (IsStringTrue(artifact) != MagickFalse)) + image_view=DestroyCacheView(image_view); + if (status == MagickFalse) { - Image + accumulator=DestroyMatrixInfo(accumulator); + return((Image *) NULL); + } + /* + Generate line segments from accumulator. + */ + file=AcquireUniqueFileResource(path); + if (file == -1) + { + accumulator=DestroyMatrixInfo(accumulator); + return((Image *) NULL); + } + (void) FormatLocaleString(message,MagickPathExtent, + "# Hough line transform: %.20gx%.20g%+.20g\n",(double) width, + (double) height,(double) threshold); + if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) + status=MagickFalse; + (void) FormatLocaleString(message,MagickPathExtent, + "viewbox 0 0 %.20g %.20g\n",(double) image->columns,(double) image->rows); + if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) + status=MagickFalse; + (void) FormatLocaleString(message,MagickPathExtent, + "# x1,y1 x2,y2 # count angle distance\n"); + if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) + status=MagickFalse; + line_count=image->columns > image->rows ? image->columns/4 : image->rows/4; + if (threshold != 0) + line_count=threshold; + for (y=0; y < (ssize_t) accumulator_height; y++) + { + register ssize_t + x; + + for (x=0; x < (ssize_t) accumulator_width; x++) + { + double + count; + + (void) GetMatrixElement(accumulator,x,y,&count); + if (count >= (double) line_count) + { + double + maxima; + + SegmentInfo + line; + + ssize_t + v; + + /* + Is point a local maxima? + */ + maxima=count; + for (v=(-((ssize_t) height/2)); v <= (((ssize_t) height/2)); v++) + { + ssize_t + u; + + for (u=(-((ssize_t) width/2)); u <= (((ssize_t) width/2)); u++) + { + if ((u != 0) || (v !=0)) + { + (void) GetMatrixElement(accumulator,x+u,y+v,&count); + if (count > maxima) + { + maxima=count; + break; + } + } + } + if (u < (ssize_t) (width/2)) + break; + } + (void) GetMatrixElement(accumulator,x,y,&count); + if (maxima > count) + continue; + if ((x >= 45) && (x <= 135)) + { + /* + y = (r-x cos(t))/sin(t) + */ + line.x1=0.0; + line.y1=((double) (y-(accumulator_height/2.0))-((line.x1- + (image->columns/2.0))*cos(DegreesToRadians((double) x))))/ + sin(DegreesToRadians((double) x))+(image->rows/2.0); + line.x2=(double) image->columns; + line.y2=((double) (y-(accumulator_height/2.0))-((line.x2- + (image->columns/2.0))*cos(DegreesToRadians((double) x))))/ + sin(DegreesToRadians((double) x))+(image->rows/2.0); + } + else + { + /* + x = (r-y cos(t))/sin(t) + */ + line.y1=0.0; + line.x1=((double) (y-(accumulator_height/2.0))-((line.y1- + (image->rows/2.0))*sin(DegreesToRadians((double) x))))/ + cos(DegreesToRadians((double) x))+(image->columns/2.0); + line.y2=(double) image->rows; + line.x2=((double) (y-(accumulator_height/2.0))-((line.y2- + (image->rows/2.0))*sin(DegreesToRadians((double) x))))/ + cos(DegreesToRadians((double) x))+(image->columns/2.0); + } + (void) FormatLocaleString(message,MagickPathExtent, + "line %g,%g %g,%g # %g %g %g\n",line.x1,line.y1,line.x2,line.y2, + maxima,(double) x,(double) y); + if (write(file,message,strlen(message)) != (ssize_t) strlen(message)) + status=MagickFalse; + } + } + } + (void) close(file); + /* + Render lines to image canvas. + */ + image_info=AcquireImageInfo(); + image_info->background_color=image->background_color; + (void) FormatLocaleString(image_info->filename,MagickPathExtent,"%s",path); + artifact=GetImageArtifact(image,"background"); + if (artifact != (const char *) NULL) + (void) SetImageOption(image_info,"background",artifact); + artifact=GetImageArtifact(image,"fill"); + if (artifact != (const char *) NULL) + (void) SetImageOption(image_info,"fill",artifact); + artifact=GetImageArtifact(image,"stroke"); + if (artifact != (const char *) NULL) + (void) SetImageOption(image_info,"stroke",artifact); + artifact=GetImageArtifact(image,"strokewidth"); + if (artifact != (const char *) NULL) + (void) SetImageOption(image_info,"strokewidth",artifact); + lines_image=RenderHoughLines(image_info,image->columns,image->rows,exception); + artifact=GetImageArtifact(image,"hough-lines:accumulator"); + if ((lines_image != (Image *) NULL) && + (IsStringTrue(artifact) != MagickFalse)) + { + Image *accumulator_image; - accumulator_image=MatrixToImage(accumulator,exception); - if (accumulator_image != (Image *) NULL) - AppendImageToList(&lines_image,accumulator_image); + accumulator_image=MatrixToImage(accumulator,exception); + if (accumulator_image != (Image *) NULL) + AppendImageToList(&lines_image,accumulator_image); } - /* - Free resources. - */ - accumulator=DestroyMatrixInfo(accumulator); - image_info=DestroyImageInfo(image_info); - (void) RelinquishUniqueFileResource(path); - return(GetFirstImageInList(lines_image)); + /* + Free resources. + */ + accumulator=DestroyMatrixInfo(accumulator); + image_info=DestroyImageInfo(image_info); + (void) RelinquishUniqueFileResource(path); + return(GetFirstImageInList(lines_image)); } - + /* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% M e a n S h i f t I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% MeanShiftImage() delineate arbitrarily shaped clusters in the image. For -% each pixel, it visits all the pixels in the neighborhood specified by -% the window centered at the pixel and excludes those that are outside the -% radius=(window-1)/2 surrounding the pixel. From those pixels, it finds those -% that are within the specified color distance from the current mean, and -% computes a new x,y centroid from those coordinates and a new mean. This new -% x,y centroid is used as the center for a new window. This process iterates -% until it converges and the final mean is replaces the (original window -% center) pixel value. It repeats this process for the next pixel, etc., -% until it processes all pixels in the image. Results are typically better with -% colorspaces other than sRGB. We recommend YIQ, YUV or YCbCr. -% -% The format of the MeanShiftImage method is: -% -% Image *MeanShiftImage(const Image *image,const size_t width, -% const size_t height,const double color_distance, -% ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o image: the image. -% -% o width, height: find pixels in this neighborhood. -% -% o color_distance: the color distance. -% -% o exception: return any errors or warnings in this structure. -% -*/ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % % + % % + % % + % M e a n S h i f t I m a g e % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + % MeanShiftImage() delineate arbitrarily shaped clusters in the image. For + % each pixel, it visits all the pixels in the neighborhood specified by + % the window centered at the pixel and excludes those that are outside the + % radius=(window-1)/2 surrounding the pixel. From those pixels, it finds those + % that are within the specified color distance from the current mean, and + % computes a new x,y centroid from those coordinates and a new mean. This new + % x,y centroid is used as the center for a new window. This process iterates + % until it converges and the final mean is replaces the (original window + % center) pixel value. It repeats this process for the next pixel, etc., + % until it processes all pixels in the image. Results are typically better with + % colorspaces other than sRGB. We recommend YIQ, YUV or YCbCr. + % + % The format of the MeanShiftImage method is: + % + % Image *MeanShiftImage(const Image *image,const size_t width, + % const size_t height,const double color_distance, + % ExceptionInfo *exception) + % + % A description of each parameter follows: + % + % o image: the image. + % + % o width, height: find pixels in this neighborhood. + % + % o color_distance: the color distance. + % + % o exception: return any errors or warnings in this structure. + % + */ MagickExport Image *MeanShiftImage(const Image *image,const size_t width, - const size_t height,const double color_distance,ExceptionInfo *exception) + const size_t height,const double color_distance,ExceptionInfo *exception) { #define MaxMeanShiftIterations 100 #define MeanShiftImageTag "MeanShift/Image" - CacheView + CacheView *image_view, - *mean_view, - *pixel_view; + *mean_view, + *pixel_view; - Image + Image *mean_image; - MagickBooleanType - status; + MagickBooleanType + status; - MagickOffsetType - progress; + MagickOffsetType + progress; - ssize_t - y; + ssize_t + y; - assert(image != (const Image *) NULL); - assert(image->signature == MagickCoreSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - mean_image=CloneImage(image,0,0,MagickTrue,exception); - if (mean_image == (Image *) NULL) - return((Image *) NULL); - if (SetImageStorageClass(mean_image,DirectClass,exception) == MagickFalse) + assert(image != (const Image *) NULL); + assert(image->signature == MagickCoreSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + mean_image=CloneImage(image,0,0,MagickTrue,exception); + if (mean_image == (Image *) NULL) + return((Image *) NULL); + if (SetImageStorageClass(mean_image,DirectClass,exception) == MagickFalse) { - mean_image=DestroyImage(mean_image); - return((Image *) NULL); + mean_image=DestroyImage(mean_image); + return((Image *) NULL); } - status=MagickTrue; - progress=0; - image_view=AcquireVirtualCacheView(image,exception); - pixel_view=AcquireVirtualCacheView(image,exception); - mean_view=AcquireAuthenticCacheView(mean_image,exception); + status=MagickTrue; + progress=0; + image_view=AcquireVirtualCacheView(image,exception); + pixel_view=AcquireVirtualCacheView(image,exception); + mean_view=AcquireAuthenticCacheView(mean_image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static) shared(status,progress) \ magick_number_threads(mean_image,mean_image,mean_image->rows,1) #endif - for (y=0; y < (ssize_t) mean_image->rows; y++) - { - register const Quantum - *magick_restrict p; - - register Quantum - *magick_restrict q; - - register ssize_t - x; - - if (status == MagickFalse) - continue; - p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); - q=GetCacheViewAuthenticPixels(mean_view,0,y,mean_image->columns,1, - exception); - if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) - { - status=MagickFalse; - continue; - } - for (x=0; x < (ssize_t) mean_image->columns; x++) + for (y=0; y < (ssize_t) mean_image->rows; y++) { - PixelInfo - mean_pixel, - previous_pixel; + register const Quantum + *magick_restrict p; - PointInfo - mean_location, - previous_location; + register Quantum + *magick_restrict q; - register ssize_t - i; + register ssize_t + x; - GetPixelInfo(image,&mean_pixel); - GetPixelInfoPixel(image,p,&mean_pixel); - mean_location.x=(double) x; - mean_location.y=(double) y; - for (i=0; i < MaxMeanShiftIterations; i++) - { - double - distance, - gamma; - - PixelInfo - sum_pixel; - - PointInfo - sum_location; - - ssize_t - count, - v; - - sum_location.x=0.0; - sum_location.y=0.0; - GetPixelInfo(image,&sum_pixel); - previous_location=mean_location; - previous_pixel=mean_pixel; - count=0; - for (v=(-((ssize_t) height/2)); v <= (((ssize_t) height/2)); v++) + if (status == MagickFalse) + continue; + p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); + q=GetCacheViewAuthenticPixels(mean_view,0,y,mean_image->columns,1, + exception); + if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) { - ssize_t - u; - - for (u=(-((ssize_t) width/2)); u <= (((ssize_t) width/2)); u++) - { - if ((v*v+u*u) <= (ssize_t) ((width/2)*(height/2))) - { - PixelInfo - pixel; - - status=GetOneCacheViewVirtualPixelInfo(pixel_view,(ssize_t) - MagickRound(mean_location.x+u),(ssize_t) MagickRound( - mean_location.y+v),&pixel,exception); - distance=(mean_pixel.red-pixel.red)*(mean_pixel.red-pixel.red)+ - (mean_pixel.green-pixel.green)*(mean_pixel.green-pixel.green)+ - (mean_pixel.blue-pixel.blue)*(mean_pixel.blue-pixel.blue); - if (distance <= (color_distance*color_distance)) - { - sum_location.x+=mean_location.x+u; - sum_location.y+=mean_location.y+v; - sum_pixel.red+=pixel.red; - sum_pixel.green+=pixel.green; - sum_pixel.blue+=pixel.blue; - sum_pixel.alpha+=pixel.alpha; - count++; - } - } - } + status=MagickFalse; + continue; } - gamma=1.0/count; - mean_location.x=gamma*sum_location.x; - mean_location.y=gamma*sum_location.y; - mean_pixel.red=gamma*sum_pixel.red; - mean_pixel.green=gamma*sum_pixel.green; - mean_pixel.blue=gamma*sum_pixel.blue; - mean_pixel.alpha=gamma*sum_pixel.alpha; - distance=(mean_location.x-previous_location.x)* - (mean_location.x-previous_location.x)+ - (mean_location.y-previous_location.y)* - (mean_location.y-previous_location.y)+ - 255.0*QuantumScale*(mean_pixel.red-previous_pixel.red)* - 255.0*QuantumScale*(mean_pixel.red-previous_pixel.red)+ - 255.0*QuantumScale*(mean_pixel.green-previous_pixel.green)* - 255.0*QuantumScale*(mean_pixel.green-previous_pixel.green)+ - 255.0*QuantumScale*(mean_pixel.blue-previous_pixel.blue)* - 255.0*QuantumScale*(mean_pixel.blue-previous_pixel.blue); - if (distance <= 3.0) - break; - } - SetPixelRed(mean_image,ClampToQuantum(mean_pixel.red),q); - SetPixelGreen(mean_image,ClampToQuantum(mean_pixel.green),q); - SetPixelBlue(mean_image,ClampToQuantum(mean_pixel.blue),q); - SetPixelAlpha(mean_image,ClampToQuantum(mean_pixel.alpha),q); - p+=GetPixelChannels(image); - q+=GetPixelChannels(mean_image); - } - if (SyncCacheViewAuthenticPixels(mean_view,exception) == MagickFalse) - status=MagickFalse; - if (image->progress_monitor != (MagickProgressMonitor) NULL) - { - MagickBooleanType - proceed; + for (x=0; x < (ssize_t) mean_image->columns; x++) + { + PixelInfo + mean_pixel, + previous_pixel; + + PointInfo + mean_location, + previous_location; + + register ssize_t + i; + + GetPixelInfo(image,&mean_pixel); + GetPixelInfoPixel(image,p,&mean_pixel); + mean_location.x=(double) x; + mean_location.y=(double) y; + for (i=0; i < MaxMeanShiftIterations; i++) + { + double + distance, + gamma; + + PixelInfo + sum_pixel; + + PointInfo + sum_location; + + ssize_t + count, + v; + + sum_location.x=0.0; + sum_location.y=0.0; + GetPixelInfo(image,&sum_pixel); + previous_location=mean_location; + previous_pixel=mean_pixel; + count=0; + for (v=(-((ssize_t) height/2)); v <= (((ssize_t) height/2)); v++) + { + ssize_t + u; + + for (u=(-((ssize_t) width/2)); u <= (((ssize_t) width/2)); u++) + { + if ((v*v+u*u) <= (ssize_t) ((width/2)*(height/2))) + { + PixelInfo + pixel; + + status=GetOneCacheViewVirtualPixelInfo(pixel_view,(ssize_t) + MagickRound(mean_location.x+u),(ssize_t) MagickRound( + mean_location.y+v),&pixel,exception); + distance=(mean_pixel.red-pixel.red)*(mean_pixel.red-pixel.red)+ + (mean_pixel.green-pixel.green)*(mean_pixel.green-pixel.green)+ + (mean_pixel.blue-pixel.blue)*(mean_pixel.blue-pixel.blue); + if (distance <= (color_distance*color_distance)) + { + sum_location.x+=mean_location.x+u; + sum_location.y+=mean_location.y+v; + sum_pixel.red+=pixel.red; + sum_pixel.green+=pixel.green; + sum_pixel.blue+=pixel.blue; + sum_pixel.alpha+=pixel.alpha; + count++; + } + } + } + } + gamma=1.0/count; + mean_location.x=gamma*sum_location.x; + mean_location.y=gamma*sum_location.y; + mean_pixel.red=gamma*sum_pixel.red; + mean_pixel.green=gamma*sum_pixel.green; + mean_pixel.blue=gamma*sum_pixel.blue; + mean_pixel.alpha=gamma*sum_pixel.alpha; + distance=(mean_location.x-previous_location.x)* + (mean_location.x-previous_location.x)+ + (mean_location.y-previous_location.y)* + (mean_location.y-previous_location.y)+ + 255.0*QuantumScale*(mean_pixel.red-previous_pixel.red)* + 255.0*QuantumScale*(mean_pixel.red-previous_pixel.red)+ + 255.0*QuantumScale*(mean_pixel.green-previous_pixel.green)* + 255.0*QuantumScale*(mean_pixel.green-previous_pixel.green)+ + 255.0*QuantumScale*(mean_pixel.blue-previous_pixel.blue)* + 255.0*QuantumScale*(mean_pixel.blue-previous_pixel.blue); + if (distance <= 3.0) + break; + } + SetPixelRed(mean_image,ClampToQuantum(mean_pixel.red),q); + SetPixelGreen(mean_image,ClampToQuantum(mean_pixel.green),q); + SetPixelBlue(mean_image,ClampToQuantum(mean_pixel.blue),q); + SetPixelAlpha(mean_image,ClampToQuantum(mean_pixel.alpha),q); + p+=GetPixelChannels(image); + q+=GetPixelChannels(mean_image); + } + if (SyncCacheViewAuthenticPixels(mean_view,exception) == MagickFalse) + status=MagickFalse; + if (image->progress_monitor != (MagickProgressMonitor) NULL) + { + MagickBooleanType + proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp atomic #endif - progress++; - proceed=SetImageProgress(image,MeanShiftImageTag,progress,image->rows); - if (proceed == MagickFalse) - status=MagickFalse; - } - } - mean_view=DestroyCacheView(mean_view); - pixel_view=DestroyCacheView(pixel_view); - image_view=DestroyCacheView(image_view); - return(mean_image); + progress++; + proceed=SetImageProgress(image,MeanShiftImageTag,progress,image->rows); + if (proceed == MagickFalse) + status=MagickFalse; + } + } + mean_view=DestroyCacheView(mean_view); + pixel_view=DestroyCacheView(pixel_view); + image_view=DestroyCacheView(image_view); + return(mean_image); } diff --git a/test/bug-hunting/cve/CVE-2019-15939/hog.cpp b/test/bug-hunting/cve/CVE-2019-15939/hog.cpp index b55c710dc..5a54cca37 100644 --- a/test/bug-hunting/cve/CVE-2019-15939/hog.cpp +++ b/test/bug-hunting/cve/CVE-2019-15939/hog.cpp @@ -1,44 +1,44 @@ /*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ + // + // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. + // + // By downloading, copying, installing or using the software you agree to this license. + // If you do not agree to this license, do not download, install, + // copy or use the software. + // + // + // License Agreement + // For Open Source Computer Vision Library + // + // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. + // Copyright (C) 2009, Willow Garage Inc., all rights reserved. + // Third party copyrights are property of their respective owners. + // + // Redistribution and use in source and binary forms, with or without modification, + // are permitted provided that the following conditions are met: + // + // * Redistribution's of source code must retain the above copyright notice, + // this list of conditions and the following disclaimer. + // + // * Redistribution's in binary form must reproduce the above copyright notice, + // this list of conditions and the following disclaimer in the documentation + // and/or other materials provided with the distribution. + // + // * The name of the copyright holders may not be used to endorse or promote products + // derived from this software without specific prior written permission. + // + // This software is provided by the copyright holders and contributors "as is" and + // any express or implied warranties, including, but not limited to, the implied + // warranties of merchantability and fitness for a particular purpose are disclaimed. + // In no event shall the Intel Corporation or contributors be liable for any direct, + // indirect, incidental, special, exemplary, or consequential damages + // (including, but not limited to, procurement of substitute goods or services; + // loss of use, data, or profits; or business interruption) however caused + // and on any theory of liability, whether in contract, strict liability, + // or tort (including negligence or otherwise) arising in any way out of + // the use of this software, even if advised of the possibility of such damage. + // + //M*/ #include "precomp.hpp" #include "cascadedetect.hpp" @@ -64,3556 +64,3556 @@ namespace cv #define NTHREADS 256 -enum {DESCR_FORMAT_COL_BY_COL, DESCR_FORMAT_ROW_BY_ROW}; + enum {DESCR_FORMAT_COL_BY_COL, DESCR_FORMAT_ROW_BY_ROW}; -static int numPartsWithin(int size, int part_size, int stride) -{ - CV_Assert(stride != 0); - return (size - part_size + stride) / stride; -} + static int numPartsWithin(int size, int part_size, int stride) + { + CV_Assert(stride != 0); + return (size - part_size + stride) / stride; + } -static Size numPartsWithin(cv::Size size, cv::Size part_size, - cv::Size stride) -{ - return Size(numPartsWithin(size.width, part_size.width, stride.width), - numPartsWithin(size.height, part_size.height, stride.height)); -} + static Size numPartsWithin(cv::Size size, cv::Size part_size, + cv::Size stride) + { + return Size(numPartsWithin(size.width, part_size.width, stride.width), + numPartsWithin(size.height, part_size.height, stride.height)); + } -static size_t getBlockHistogramSize(Size block_size, Size cell_size, int nbins) -{ - CV_Assert(!cell_size.empty()); - Size cells_per_block = Size(block_size.width / cell_size.width, - block_size.height / cell_size.height); - return (size_t)(nbins * cells_per_block.area()); -} + static size_t getBlockHistogramSize(Size block_size, Size cell_size, int nbins) + { + CV_Assert(!cell_size.empty()); + Size cells_per_block = Size(block_size.width / cell_size.width, + block_size.height / cell_size.height); + return (size_t)(nbins * cells_per_block.area()); + } -size_t HOGDescriptor::getDescriptorSize() const -{ - CV_Assert(blockSize.width % cellSize.width == 0 && - blockSize.height % cellSize.height == 0); - CV_Assert((winSize.width - blockSize.width) % blockStride.width == 0 && - (winSize.height - blockSize.height) % blockStride.height == 0 ); + size_t HOGDescriptor::getDescriptorSize() const + { + CV_Assert(blockSize.width % cellSize.width == 0 && + blockSize.height % cellSize.height == 0); + CV_Assert((winSize.width - blockSize.width) % blockStride.width == 0 && + (winSize.height - blockSize.height) % blockStride.height == 0 ); - return (size_t)nbins* - (blockSize.width/cellSize.width)* - (blockSize.height/cellSize.height)* - ((winSize.width - blockSize.width)/blockStride.width + 1)* - ((winSize.height - blockSize.height)/blockStride.height + 1); -} + return (size_t)nbins* + (blockSize.width/cellSize.width)* + (blockSize.height/cellSize.height)* + ((winSize.width - blockSize.width)/blockStride.width + 1)* + ((winSize.height - blockSize.height)/blockStride.height + 1); + } -double HOGDescriptor::getWinSigma() const -{ - return winSigma > 0 ? winSigma : (blockSize.width + blockSize.height)/8.; -} + double HOGDescriptor::getWinSigma() const + { + return winSigma > 0 ? winSigma : (blockSize.width + blockSize.height)/8.; + } -bool HOGDescriptor::checkDetectorSize() const -{ - size_t detectorSize = svmDetector.size(), descriptorSize = getDescriptorSize(); - return detectorSize == 0 || - detectorSize == descriptorSize || - detectorSize == descriptorSize + 1; -} + bool HOGDescriptor::checkDetectorSize() const + { + size_t detectorSize = svmDetector.size(), descriptorSize = getDescriptorSize(); + return detectorSize == 0 || + detectorSize == descriptorSize || + detectorSize == descriptorSize + 1; + } -void HOGDescriptor::setSVMDetector(InputArray _svmDetector) -{ - _svmDetector.getMat().convertTo(svmDetector, CV_32F); - CV_Assert(checkDetectorSize()); + void HOGDescriptor::setSVMDetector(InputArray _svmDetector) + { + _svmDetector.getMat().convertTo(svmDetector, CV_32F); + CV_Assert(checkDetectorSize()); - Mat detector_reordered(1, (int)svmDetector.size(), CV_32FC1); + Mat detector_reordered(1, (int)svmDetector.size(), CV_32FC1); - size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins); - cv::Size blocks_per_img = numPartsWithin(winSize, blockSize, blockStride); + size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins); + cv::Size blocks_per_img = numPartsWithin(winSize, blockSize, blockStride); - for (int i = 0; i < blocks_per_img.height; ++i) - for (int j = 0; j < blocks_per_img.width; ++j) - { - const float *src = &svmDetector[0] + (j * blocks_per_img.height + i) * block_hist_size; - float *dst = detector_reordered.ptr() + (i * blocks_per_img.width + j) * block_hist_size; - for (size_t k = 0; k < block_hist_size; ++k) - dst[k] = src[k]; - } - size_t descriptor_size = getDescriptorSize(); - free_coef = svmDetector.size() > descriptor_size ? svmDetector[descriptor_size] : 0; - detector_reordered.copyTo(oclSvmDetector); -} + for (int i = 0; i < blocks_per_img.height; ++i) + for (int j = 0; j < blocks_per_img.width; ++j) + { + const float *src = &svmDetector[0] + (j * blocks_per_img.height + i) * block_hist_size; + float *dst = detector_reordered.ptr() + (i * blocks_per_img.width + j) * block_hist_size; + for (size_t k = 0; k < block_hist_size; ++k) + dst[k] = src[k]; + } + size_t descriptor_size = getDescriptorSize(); + free_coef = svmDetector.size() > descriptor_size ? svmDetector[descriptor_size] : 0; + detector_reordered.copyTo(oclSvmDetector); + } #define CV_TYPE_NAME_HOG_DESCRIPTOR "opencv-object-detector-hog" -bool HOGDescriptor::read(FileNode& obj) -{ - CV_Assert(!obj["winSize"].empty()); - - if( !obj.isMap() ) - return false; - FileNodeIterator it = obj["winSize"].begin(); - it >> winSize.width >> winSize.height; CV_Assert(!winSize.empty()); - it = obj["blockSize"].begin(); - it >> blockSize.width >> blockSize.height; CV_Assert(!blockSize.empty()); - it = obj["blockStride"].begin(); - it >> blockStride.width >> blockStride.height; CV_Assert(!blockStride.empty()); - it = obj["cellSize"].begin(); - it >> cellSize.width >> cellSize.height; CV_Assert(!cellSize.empty()); - obj["nbins"] >> nbins; CV_Assert(nbins > 0); - obj["derivAperture"] >> derivAperture; - obj["winSigma"] >> winSigma; - obj["histogramNormType"] >> histogramNormType; - obj["L2HysThreshold"] >> L2HysThreshold; - obj["gammaCorrection"] >> gammaCorrection; - obj["nlevels"] >> nlevels; CV_Assert(nlevels > 0); - if (obj["signedGradient"].empty()) - signedGradient = false; - else - obj["signedGradient"] >> signedGradient; - - FileNode vecNode = obj["SVMDetector"]; - if( vecNode.isSeq() ) + bool HOGDescriptor::read(FileNode& obj) { - std::vector _svmDetector; - vecNode >> _svmDetector; - setSVMDetector(_svmDetector); - } - return true; -} + CV_Assert(!obj["winSize"].empty()); -void HOGDescriptor::write(FileStorage& fs, const String& objName) const -{ - if( !objName.empty() ) - fs << objName; - - fs << "{" CV_TYPE_NAME_HOG_DESCRIPTOR - << "winSize" << winSize - << "blockSize" << blockSize - << "blockStride" << blockStride - << "cellSize" << cellSize - << "nbins" << nbins - << "derivAperture" << derivAperture - << "winSigma" << getWinSigma() - << "histogramNormType" << histogramNormType - << "L2HysThreshold" << L2HysThreshold - << "gammaCorrection" << gammaCorrection - << "nlevels" << nlevels - << "signedGradient" << signedGradient; - if( !svmDetector.empty() ) - fs << "SVMDetector" << svmDetector; - fs << "}"; -} - -bool HOGDescriptor::load(const String& filename, const String& objname) -{ - FileStorage fs(filename, FileStorage::READ); - FileNode obj = !objname.empty() ? fs[objname] : fs.getFirstTopLevelNode(); - return read(obj); -} - -void HOGDescriptor::save(const String& filename, const String& objName) const -{ - FileStorage fs(filename, FileStorage::WRITE); - write(fs, !objName.empty() ? objName : FileStorage::getDefaultObjectName(filename)); -} - -void HOGDescriptor::copyTo(HOGDescriptor& c) const -{ - c.winSize = winSize; - c.blockSize = blockSize; - c.blockStride = blockStride; - c.cellSize = cellSize; - c.nbins = nbins; - c.derivAperture = derivAperture; - c.winSigma = winSigma; - c.histogramNormType = histogramNormType; - c.L2HysThreshold = L2HysThreshold; - c.gammaCorrection = gammaCorrection; - c.setSVMDetector(svmDetector); - c.nlevels = nlevels; - c.signedGradient = signedGradient; -} - -void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, - Size paddingTL, Size paddingBR) const -{ - CV_INSTRUMENT_REGION(); - - CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 ); - - Size gradsize(img.cols + paddingTL.width + paddingBR.width, - img.rows + paddingTL.height + paddingBR.height); - grad.create(gradsize, CV_32FC2); // - qangle.create(gradsize, CV_8UC2); // [0..nbins-1] - quantized gradient orientation - - Size wholeSize; - Point roiofs; - img.locateROI(wholeSize, roiofs); - - int i, x, y; - int cn = img.channels(); - - Mat_ _lut(1, 256); - const float* const lut = &_lut(0,0); -#if CV_SIMD128 - v_float32x4 idx(0.0f, 1.0f, 2.0f, 3.0f); - v_float32x4 ifour = v_setall_f32(4.0); - - float* const _data = &_lut(0, 0); - if ( gammaCorrection ) - for ( i = 0; i < 256; i += 4) - { - v_store(_data + i, v_sqrt(idx)); - idx += ifour; - } - else - for ( i = 0; i < 256; i += 4) - { - v_store(_data + i, idx); - idx += ifour; - } -#else - if( gammaCorrection ) - for( i = 0; i < 256; i++ ) - _lut(0,i) = std::sqrt((float)i); - else - for( i = 0; i < 256; i++ ) - _lut(0,i) = (float)i; -#endif - - AutoBuffer mapbuf(gradsize.width + gradsize.height + 4); - int* xmap = mapbuf.data() + 1; - int* ymap = xmap + gradsize.width + 2; - - const int borderType = (int)BORDER_REFLECT_101; - - for( x = -1; x < gradsize.width + 1; x++ ) - xmap[x] = borderInterpolate(x - paddingTL.width + roiofs.x, - wholeSize.width, borderType) - roiofs.x; - for( y = -1; y < gradsize.height + 1; y++ ) - ymap[y] = borderInterpolate(y - paddingTL.height + roiofs.y, - wholeSize.height, borderType) - roiofs.y; - - // x- & y- derivatives for the whole row - int width = gradsize.width; - AutoBuffer _dbuf(width*4); - float* const dbuf = _dbuf.data(); - Mat Dx(1, width, CV_32F, dbuf); - Mat Dy(1, width, CV_32F, dbuf + width); - Mat Mag(1, width, CV_32F, dbuf + width*2); - Mat Angle(1, width, CV_32F, dbuf + width*3); - - if (cn == 3) - { - int end = gradsize.width + 2; - xmap -= 1, x = 0; -#if CV_SIMD128 - for ( ; x <= end - 4; x += 4) - { - v_int32x4 mul_res = v_load(xmap + x); - mul_res += mul_res + mul_res; - v_store(xmap + x, mul_res); - } -#endif - for ( ; x < end; ++x) - xmap[x] *= 3; - xmap += 1; - } - - float angleScale = signedGradient ? (float)(nbins/(2.0*CV_PI)) : (float)(nbins/CV_PI); - for( y = 0; y < gradsize.height; y++ ) - { - const uchar* imgPtr = img.ptr(ymap[y]); - //In case subimage is used ptr() generates an assert for next and prev rows - //(see http://code.opencv.org/issues/4149) - const uchar* prevPtr = img.data + img.step*ymap[y-1]; - const uchar* nextPtr = img.data + img.step*ymap[y+1]; - - float* gradPtr = grad.ptr(y); - uchar* qanglePtr = qangle.ptr(y); - - if( cn == 1 ) - { - for( x = 0; x < width; x++ ) - { - int x1 = xmap[x]; - dbuf[x] = (float)(lut[imgPtr[xmap[x+1]]] - lut[imgPtr[xmap[x-1]]]); - dbuf[width + x] = (float)(lut[nextPtr[x1]] - lut[prevPtr[x1]]); - } - } + if (!obj.isMap()) + return false; + FileNodeIterator it = obj["winSize"].begin(); + it >> winSize.width >> winSize.height; CV_Assert(!winSize.empty()); + it = obj["blockSize"].begin(); + it >> blockSize.width >> blockSize.height; CV_Assert(!blockSize.empty()); + it = obj["blockStride"].begin(); + it >> blockStride.width >> blockStride.height; CV_Assert(!blockStride.empty()); + it = obj["cellSize"].begin(); + it >> cellSize.width >> cellSize.height; CV_Assert(!cellSize.empty()); + obj["nbins"] >> nbins; CV_Assert(nbins > 0); + obj["derivAperture"] >> derivAperture; + obj["winSigma"] >> winSigma; + obj["histogramNormType"] >> histogramNormType; + obj["L2HysThreshold"] >> L2HysThreshold; + obj["gammaCorrection"] >> gammaCorrection; + obj["nlevels"] >> nlevels; CV_Assert(nlevels > 0); + if (obj["signedGradient"].empty()) + signedGradient = false; else + obj["signedGradient"] >> signedGradient; + + FileNode vecNode = obj["SVMDetector"]; + if (vecNode.isSeq()) { - x = 0; -#if CV_SIMD128 - for( ; x <= width - 4; x += 4 ) - { - int x0 = xmap[x], x1 = xmap[x+1], x2 = xmap[x+2], x3 = xmap[x+3]; - typedef const uchar* const T; - T p02 = imgPtr + xmap[x+1], p00 = imgPtr + xmap[x-1]; - T p12 = imgPtr + xmap[x+2], p10 = imgPtr + xmap[x]; - T p22 = imgPtr + xmap[x+3], p20 = p02; - T p32 = imgPtr + xmap[x+4], p30 = p12; - - v_float32x4 _dx0 = v_float32x4(lut[p02[0]], lut[p12[0]], lut[p22[0]], lut[p32[0]]) - - v_float32x4(lut[p00[0]], lut[p10[0]], lut[p20[0]], lut[p30[0]]); - v_float32x4 _dx1 = v_float32x4(lut[p02[1]], lut[p12[1]], lut[p22[1]], lut[p32[1]]) - - v_float32x4(lut[p00[1]], lut[p10[1]], lut[p20[1]], lut[p30[1]]); - v_float32x4 _dx2 = v_float32x4(lut[p02[2]], lut[p12[2]], lut[p22[2]], lut[p32[2]]) - - v_float32x4(lut[p00[2]], lut[p10[2]], lut[p20[2]], lut[p30[2]]); - - v_float32x4 _dy0 = v_float32x4(lut[nextPtr[x0]], lut[nextPtr[x1]], lut[nextPtr[x2]], lut[nextPtr[x3]]) - - v_float32x4(lut[prevPtr[x0]], lut[prevPtr[x1]], lut[prevPtr[x2]], lut[prevPtr[x3]]); - v_float32x4 _dy1 = v_float32x4(lut[nextPtr[x0+1]], lut[nextPtr[x1+1]], lut[nextPtr[x2+1]], lut[nextPtr[x3+1]]) - - v_float32x4(lut[prevPtr[x0+1]], lut[prevPtr[x1+1]], lut[prevPtr[x2+1]], lut[prevPtr[x3+1]]); - v_float32x4 _dy2 = v_float32x4(lut[nextPtr[x0+2]], lut[nextPtr[x1+2]], lut[nextPtr[x2+2]], lut[nextPtr[x3+2]]) - - v_float32x4(lut[prevPtr[x0+2]], lut[prevPtr[x1+2]], lut[prevPtr[x2+2]], lut[prevPtr[x3+2]]); - - v_float32x4 _mag0 = (_dx0 * _dx0) + (_dy0 * _dy0); - v_float32x4 _mag1 = (_dx1 * _dx1) + (_dy1 * _dy1); - v_float32x4 _mag2 = (_dx2 * _dx2) + (_dy2 * _dy2); - - v_float32x4 mask = v_reinterpret_as_f32(_mag2 > _mag1); - _dx2 = v_select(mask, _dx2, _dx1); - _dy2 = v_select(mask, _dy2, _dy1); - - mask = v_reinterpret_as_f32(v_max(_mag2, _mag1) > _mag0); - _dx2 = v_select(mask, _dx2, _dx0); - _dy2 = v_select(mask, _dy2, _dy0); - - v_store(dbuf + x, _dx2); - v_store(dbuf + x + width, _dy2); - } -#endif - for( ; x < width; x++ ) - { - int x1 = xmap[x]; - float dx0, dy0, dx, dy, mag0, mag; - const uchar* p2 = imgPtr + xmap[x+1]; - const uchar* p0 = imgPtr + xmap[x-1]; - - dx0 = lut[p2[2]] - lut[p0[2]]; - dy0 = lut[nextPtr[x1+2]] - lut[prevPtr[x1+2]]; - mag0 = dx0*dx0 + dy0*dy0; - - dx = lut[p2[1]] - lut[p0[1]]; - dy = lut[nextPtr[x1+1]] - lut[prevPtr[x1+1]]; - mag = dx*dx + dy*dy; - if( mag0 < mag ) - { - dx0 = dx; - dy0 = dy; - mag0 = mag; - } - - dx = lut[p2[0]] - lut[p0[0]]; - dy = lut[nextPtr[x1]] - lut[prevPtr[x1]]; - mag = dx*dx + dy*dy; - if( mag0 < mag ) - { - dx0 = dx; - dy0 = dy; - mag0 = mag; - } - - dbuf[x] = dx0; - dbuf[x+width] = dy0; - } + std::vector _svmDetector; + vecNode >> _svmDetector; + setSVMDetector(_svmDetector); } - - // computing angles and magnidutes - cartToPolar( Dx, Dy, Mag, Angle, false ); - - // filling the result matrix - x = 0; -#if CV_SIMD128 - v_float32x4 fhalf = v_setall_f32(0.5f); - v_float32x4 _angleScale = v_setall_f32(angleScale), fone = v_setall_f32(1.0f); - v_int32x4 ione = v_setall_s32(1), _nbins = v_setall_s32(nbins), izero = v_setzero_s32(); - - for ( ; x <= width - 4; x += 4) - { - int x2 = x << 1; - v_float32x4 _mag = v_load(dbuf + x + (width << 1)); - v_float32x4 _angle = v_load(dbuf + x + width * 3); - _angle = (_angleScale * _angle) - fhalf; - - v_int32x4 _hidx = v_floor(_angle); - _angle -= v_cvt_f32(_hidx); - - v_float32x4 ft0 = _mag * (fone - _angle); - v_float32x4 ft1 = _mag * _angle; - - v_store_interleave(gradPtr + x2, ft0, ft1); - - v_int32x4 mask0 = _hidx >> 31; - v_int32x4 it0 = mask0 & _nbins; - mask0 = (_hidx >= _nbins); - v_int32x4 it1 = mask0 & _nbins; - _hidx += (it0 - it1); - - it0 = v_reinterpret_as_s32(v_pack(v_pack(_hidx, izero), v_reinterpret_as_s16(izero))); - _hidx += ione; - _hidx &= (_hidx < _nbins); - it1 = v_reinterpret_as_s32(v_pack(v_pack(_hidx, izero), v_reinterpret_as_s16(izero))); - v_uint8x16 it2, it3; - v_zip(v_reinterpret_as_u8(it0), v_reinterpret_as_u8(it1), it2, it3); - - v_store_low(qanglePtr + x2, it2); - } -#endif - for( ; x < width; x++ ) - { - float mag = dbuf[x+width*2], angle = dbuf[x+width*3]*angleScale - 0.5f; - int hidx = cvFloor(angle); - angle -= hidx; - gradPtr[x*2] = mag*(1.f - angle); - gradPtr[x*2+1] = mag*angle; - - if( hidx < 0 ) - hidx += nbins; - else if( hidx >= nbins ) - hidx -= nbins; - - CV_Assert( (unsigned)hidx < (unsigned)nbins ); - - qanglePtr[x*2] = (uchar)hidx; - hidx++; - hidx &= hidx < nbins ? -1 : 0; - qanglePtr[x*2+1] = (uchar)hidx; - } - } -} - -struct HOGCache -{ - struct BlockData - { - BlockData() : - histOfs(0), imgOffset() - { } - - int histOfs; - Point imgOffset; - }; - - struct PixData - { - size_t gradOfs, qangleOfs; - int histOfs[4]; - float histWeights[4]; - float gradWeight; - }; - - HOGCache(); - HOGCache(const HOGDescriptor* descriptor, - const Mat& img, const Size& paddingTL, const Size& paddingBR, - bool useCache, const Size& cacheStride); - virtual ~HOGCache() { } - virtual void init(const HOGDescriptor* descriptor, - const Mat& img, const Size& paddingTL, const Size& paddingBR, - bool useCache, const Size& cacheStride); - - Size windowsInImage(const Size& imageSize, const Size& winStride) const; - Rect getWindow(const Size& imageSize, const Size& winStride, int idx) const; - - const float* getBlock(Point pt, float* buf); - virtual void normalizeBlockHistogram(float* histogram) const; - - std::vector pixData; - std::vector blockData; - - bool useCache; - std::vector ymaxCached; - Size winSize; - Size cacheStride; - Size nblocks, ncells; - int blockHistogramSize; - int count1, count2, count4; - Point imgoffset; - Mat_ blockCache; - Mat_ blockCacheFlags; - - Mat grad, qangle; - const HOGDescriptor* descriptor; -}; - -HOGCache::HOGCache() : - blockHistogramSize(), count1(), count2(), count4() -{ - useCache = false; - descriptor = 0; -} - -HOGCache::HOGCache(const HOGDescriptor* _descriptor, - const Mat& _img, const Size& _paddingTL, const Size& _paddingBR, - bool _useCache, const Size& _cacheStride) -{ - init(_descriptor, _img, _paddingTL, _paddingBR, _useCache, _cacheStride); -} - -void HOGCache::init(const HOGDescriptor* _descriptor, - const Mat& _img, const Size& _paddingTL, const Size& _paddingBR, - bool _useCache, const Size& _cacheStride) -{ - descriptor = _descriptor; - cacheStride = _cacheStride; - useCache = _useCache; - - descriptor->computeGradient(_img, grad, qangle, _paddingTL, _paddingBR); - imgoffset = _paddingTL; - - winSize = descriptor->winSize; - Size blockSize = descriptor->blockSize; - Size blockStride = descriptor->blockStride; - Size cellSize = descriptor->cellSize; - int i, j, nbins = descriptor->nbins; - int rawBlockSize = blockSize.width*blockSize.height; - - nblocks = Size((winSize.width - blockSize.width)/blockStride.width + 1, - (winSize.height - blockSize.height)/blockStride.height + 1); - ncells = Size(blockSize.width/cellSize.width, blockSize.height/cellSize.height); - blockHistogramSize = ncells.width*ncells.height*nbins; - - if( useCache ) - { - Size cacheSize((grad.cols - blockSize.width)/cacheStride.width+1, - (winSize.height/cacheStride.height)+1); - - blockCache.create(cacheSize.height, cacheSize.width*blockHistogramSize); - blockCacheFlags.create(cacheSize); - - size_t cacheRows = blockCache.rows; - ymaxCached.resize(cacheRows); - for(size_t ii = 0; ii < cacheRows; ii++ ) - ymaxCached[ii] = -1; + return true; } - Mat_ weights(blockSize); - float sigma = (float)descriptor->getWinSigma(); - float scale = 1.f/(sigma*sigma*2); - + void HOGDescriptor::write(FileStorage& fs, const String& objName) const { - AutoBuffer di(blockSize.height), dj(blockSize.width); - float* _di = di.data(), *_dj = dj.data(); - float bh = blockSize.height * 0.5f, bw = blockSize.width * 0.5f; + if (!objName.empty()) + fs << objName; - i = 0; - #if CV_SIMD128 + fs << "{" CV_TYPE_NAME_HOG_DESCRIPTOR + << "winSize" << winSize + << "blockSize" << blockSize + << "blockStride" << blockStride + << "cellSize" << cellSize + << "nbins" << nbins + << "derivAperture" << derivAperture + << "winSigma" << getWinSigma() + << "histogramNormType" << histogramNormType + << "L2HysThreshold" << L2HysThreshold + << "gammaCorrection" << gammaCorrection + << "nlevels" << nlevels + << "signedGradient" << signedGradient; + if (!svmDetector.empty()) + fs << "SVMDetector" << svmDetector; + fs << "}"; + } + + bool HOGDescriptor::load(const String& filename, const String& objname) + { + FileStorage fs(filename, FileStorage::READ); + FileNode obj = !objname.empty() ? fs[objname] : fs.getFirstTopLevelNode(); + return read(obj); + } + + void HOGDescriptor::save(const String& filename, const String& objName) const + { + FileStorage fs(filename, FileStorage::WRITE); + write(fs, !objName.empty() ? objName : FileStorage::getDefaultObjectName(filename)); + } + + void HOGDescriptor::copyTo(HOGDescriptor& c) const + { + c.winSize = winSize; + c.blockSize = blockSize; + c.blockStride = blockStride; + c.cellSize = cellSize; + c.nbins = nbins; + c.derivAperture = derivAperture; + c.winSigma = winSigma; + c.histogramNormType = histogramNormType; + c.L2HysThreshold = L2HysThreshold; + c.gammaCorrection = gammaCorrection; + c.setSVMDetector(svmDetector); + c.nlevels = nlevels; + c.signedGradient = signedGradient; + } + + void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, + Size paddingTL, Size paddingBR) const + { + CV_INSTRUMENT_REGION(); + + CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 ); + + Size gradsize(img.cols + paddingTL.width + paddingBR.width, + img.rows + paddingTL.height + paddingBR.height); + grad.create(gradsize, CV_32FC2); // + qangle.create(gradsize, CV_8UC2); // [0..nbins-1] - quantized gradient orientation + + Size wholeSize; + Point roiofs; + img.locateROI(wholeSize, roiofs); + + int i, x, y; + int cn = img.channels(); + + Mat_ _lut(1, 256); + const float* const lut = &_lut(0,0); +#if CV_SIMD128 v_float32x4 idx(0.0f, 1.0f, 2.0f, 3.0f); - v_float32x4 _bw = v_setall_f32(bw), _bh = v_setall_f32(bh); v_float32x4 ifour = v_setall_f32(4.0); - for (; i <= blockSize.height - 4; i += 4) - { - v_float32x4 t = idx - _bh; - t *= t; - idx += ifour; - v_store(_di + i, t); - } - #endif - for ( ; i < blockSize.height; ++i) - { - _di[i] = i - bh; - _di[i] *= _di[i]; - } - - j = 0; - #if CV_SIMD128 - idx = v_float32x4(0.0f, 1.0f, 2.0f, 3.0f); - - for (; j <= blockSize.height - 4; j += 4) - { - v_float32x4 t = idx - _bw; - t *= t; - idx += ifour; - v_store(_dj + j, t); - } - #endif - for ( ; j < blockSize.width; ++j) - { - _dj[j] = j - bw; - _dj[j] *= _dj[j]; - } - - for(i = 0; i < blockSize.height; i++) - for(j = 0; j < blockSize.width; j++) - weights(i,j) = std::exp(-(_di[i] + _dj[j])*scale); - } - - blockData.resize(nblocks.width*nblocks.height); - pixData.resize(rawBlockSize*3); - - // Initialize 2 lookup tables, pixData & blockData. - // Here is why: - // - // The detection algorithm runs in 4 nested loops (at each pyramid layer): - // loop over the windows within the input image - // loop over the blocks within each window - // loop over the cells within each block - // loop over the pixels in each cell - // - // As each of the loops runs over a 2-dimensional array, - // we could get 8(!) nested loops in total, which is very-very slow. - // - // To speed the things up, we do the following: - // 1. loop over windows is unrolled in the HOGDescriptor::{compute|detect} methods; - // inside we compute the current search window using getWindow() method. - // Yes, it involves some overhead (function call + couple of divisions), - // but it's tiny in fact. - // 2. loop over the blocks is also unrolled. Inside we use pre-computed blockData[j] - // to set up gradient and histogram pointers. - // 3. loops over cells and pixels in each cell are merged - // (since there is no overlap between cells, each pixel in the block is processed once) - // and also unrolled. Inside we use PixData[k] to access the gradient values and - // update the histogram - // - - count1 = count2 = count4 = 0; - for( j = 0; j < blockSize.width; j++ ) - for( i = 0; i < blockSize.height; i++ ) - { - PixData* data = 0; - float cellX = (j+0.5f)/cellSize.width - 0.5f; - float cellY = (i+0.5f)/cellSize.height - 0.5f; - int icellX0 = cvFloor(cellX); - int icellY0 = cvFloor(cellY); - int icellX1 = icellX0 + 1, icellY1 = icellY0 + 1; - cellX -= icellX0; - cellY -= icellY0; - - if( (unsigned)icellX0 < (unsigned)ncells.width && - (unsigned)icellX1 < (unsigned)ncells.width ) + float* const _data = &_lut(0, 0); + if (gammaCorrection) + for (i = 0; i < 256; i += 4) { - if( (unsigned)icellY0 < (unsigned)ncells.height && - (unsigned)icellY1 < (unsigned)ncells.height ) + v_store(_data + i, v_sqrt(idx)); + idx += ifour; + } + else + for (i = 0; i < 256; i += 4) + { + v_store(_data + i, idx); + idx += ifour; + } +#else + if (gammaCorrection) + for (i = 0; i < 256; i++) + _lut(0,i) = std::sqrt((float)i); + else + for (i = 0; i < 256; i++) + _lut(0,i) = (float)i; +#endif + + AutoBuffer mapbuf(gradsize.width + gradsize.height + 4); + int* xmap = mapbuf.data() + 1; + int* ymap = xmap + gradsize.width + 2; + + const int borderType = (int)BORDER_REFLECT_101; + + for (x = -1; x < gradsize.width + 1; x++) + xmap[x] = borderInterpolate(x - paddingTL.width + roiofs.x, + wholeSize.width, borderType) - roiofs.x; + for (y = -1; y < gradsize.height + 1; y++) + ymap[y] = borderInterpolate(y - paddingTL.height + roiofs.y, + wholeSize.height, borderType) - roiofs.y; + + // x- & y- derivatives for the whole row + int width = gradsize.width; + AutoBuffer _dbuf(width*4); + float* const dbuf = _dbuf.data(); + Mat Dx(1, width, CV_32F, dbuf); + Mat Dy(1, width, CV_32F, dbuf + width); + Mat Mag(1, width, CV_32F, dbuf + width*2); + Mat Angle(1, width, CV_32F, dbuf + width*3); + + if (cn == 3) + { + int end = gradsize.width + 2; + xmap -= 1, x = 0; +#if CV_SIMD128 + for ( ; x <= end - 4; x += 4) + { + v_int32x4 mul_res = v_load(xmap + x); + mul_res += mul_res + mul_res; + v_store(xmap + x, mul_res); + } +#endif + for ( ; x < end; ++x) + xmap[x] *= 3; + xmap += 1; + } + + float angleScale = signedGradient ? (float)(nbins/(2.0*CV_PI)) : (float)(nbins/CV_PI); + for (y = 0; y < gradsize.height; y++) + { + const uchar* imgPtr = img.ptr(ymap[y]); + //In case subimage is used ptr() generates an assert for next and prev rows + //(see http://code.opencv.org/issues/4149) + const uchar* prevPtr = img.data + img.step*ymap[y-1]; + const uchar* nextPtr = img.data + img.step*ymap[y+1]; + + float* gradPtr = grad.ptr(y); + uchar* qanglePtr = qangle.ptr(y); + + if (cn == 1) + { + for (x = 0; x < width; x++) { - data = &pixData[rawBlockSize*2 + (count4++)]; - data->histOfs[0] = (icellX0*ncells.height + icellY0)*nbins; - data->histWeights[0] = (1.f - cellX)*(1.f - cellY); - data->histOfs[1] = (icellX1*ncells.height + icellY0)*nbins; - data->histWeights[1] = cellX*(1.f - cellY); - data->histOfs[2] = (icellX0*ncells.height + icellY1)*nbins; - data->histWeights[2] = (1.f - cellX)*cellY; - data->histOfs[3] = (icellX1*ncells.height + icellY1)*nbins; - data->histWeights[3] = cellX*cellY; - } - else - { - data = &pixData[rawBlockSize + (count2++)]; - if( (unsigned)icellY0 < (unsigned)ncells.height ) - { - icellY1 = icellY0; - cellY = 1.f - cellY; - } - data->histOfs[0] = (icellX0*ncells.height + icellY1)*nbins; - data->histWeights[0] = (1.f - cellX)*cellY; - data->histOfs[1] = (icellX1*ncells.height + icellY1)*nbins; - data->histWeights[1] = cellX*cellY; - data->histOfs[2] = data->histOfs[3] = 0; - data->histWeights[2] = data->histWeights[3] = 0; + int x1 = xmap[x]; + dbuf[x] = (float)(lut[imgPtr[xmap[x+1]]] - lut[imgPtr[xmap[x-1]]]); + dbuf[width + x] = (float)(lut[nextPtr[x1]] - lut[prevPtr[x1]]); } } else { - if( (unsigned)icellX0 < (unsigned)ncells.width ) + x = 0; +#if CV_SIMD128 + for ( ; x <= width - 4; x += 4) { - icellX1 = icellX0; - cellX = 1.f - cellX; - } + int x0 = xmap[x], x1 = xmap[x+1], x2 = xmap[x+2], x3 = xmap[x+3]; + typedef const uchar* const T; + T p02 = imgPtr + xmap[x+1], p00 = imgPtr + xmap[x-1]; + T p12 = imgPtr + xmap[x+2], p10 = imgPtr + xmap[x]; + T p22 = imgPtr + xmap[x+3], p20 = p02; + T p32 = imgPtr + xmap[x+4], p30 = p12; - if( (unsigned)icellY0 < (unsigned)ncells.height && - (unsigned)icellY1 < (unsigned)ncells.height ) + v_float32x4 _dx0 = v_float32x4(lut[p02[0]], lut[p12[0]], lut[p22[0]], lut[p32[0]]) - + v_float32x4(lut[p00[0]], lut[p10[0]], lut[p20[0]], lut[p30[0]]); + v_float32x4 _dx1 = v_float32x4(lut[p02[1]], lut[p12[1]], lut[p22[1]], lut[p32[1]]) - + v_float32x4(lut[p00[1]], lut[p10[1]], lut[p20[1]], lut[p30[1]]); + v_float32x4 _dx2 = v_float32x4(lut[p02[2]], lut[p12[2]], lut[p22[2]], lut[p32[2]]) - + v_float32x4(lut[p00[2]], lut[p10[2]], lut[p20[2]], lut[p30[2]]); + + v_float32x4 _dy0 = v_float32x4(lut[nextPtr[x0]], lut[nextPtr[x1]], lut[nextPtr[x2]], lut[nextPtr[x3]]) - + v_float32x4(lut[prevPtr[x0]], lut[prevPtr[x1]], lut[prevPtr[x2]], lut[prevPtr[x3]]); + v_float32x4 _dy1 = v_float32x4(lut[nextPtr[x0+1]], lut[nextPtr[x1+1]], lut[nextPtr[x2+1]], lut[nextPtr[x3+1]]) - + v_float32x4(lut[prevPtr[x0+1]], lut[prevPtr[x1+1]], lut[prevPtr[x2+1]], lut[prevPtr[x3+1]]); + v_float32x4 _dy2 = v_float32x4(lut[nextPtr[x0+2]], lut[nextPtr[x1+2]], lut[nextPtr[x2+2]], lut[nextPtr[x3+2]]) - + v_float32x4(lut[prevPtr[x0+2]], lut[prevPtr[x1+2]], lut[prevPtr[x2+2]], lut[prevPtr[x3+2]]); + + v_float32x4 _mag0 = (_dx0 * _dx0) + (_dy0 * _dy0); + v_float32x4 _mag1 = (_dx1 * _dx1) + (_dy1 * _dy1); + v_float32x4 _mag2 = (_dx2 * _dx2) + (_dy2 * _dy2); + + v_float32x4 mask = v_reinterpret_as_f32(_mag2 > _mag1); + _dx2 = v_select(mask, _dx2, _dx1); + _dy2 = v_select(mask, _dy2, _dy1); + + mask = v_reinterpret_as_f32(v_max(_mag2, _mag1) > _mag0); + _dx2 = v_select(mask, _dx2, _dx0); + _dy2 = v_select(mask, _dy2, _dy0); + + v_store(dbuf + x, _dx2); + v_store(dbuf + x + width, _dy2); + } +#endif + for ( ; x < width; x++) { - data = &pixData[rawBlockSize + (count2++)]; - data->histOfs[0] = (icellX1*ncells.height + icellY0)*nbins; - data->histWeights[0] = cellX*(1.f - cellY); - data->histOfs[1] = (icellX1*ncells.height + icellY1)*nbins; - data->histWeights[1] = cellX*cellY; - data->histOfs[2] = data->histOfs[3] = 0; - data->histWeights[2] = data->histWeights[3] = 0; + int x1 = xmap[x]; + float dx0, dy0, dx, dy, mag0, mag; + const uchar* p2 = imgPtr + xmap[x+1]; + const uchar* p0 = imgPtr + xmap[x-1]; + + dx0 = lut[p2[2]] - lut[p0[2]]; + dy0 = lut[nextPtr[x1+2]] - lut[prevPtr[x1+2]]; + mag0 = dx0*dx0 + dy0*dy0; + + dx = lut[p2[1]] - lut[p0[1]]; + dy = lut[nextPtr[x1+1]] - lut[prevPtr[x1+1]]; + mag = dx*dx + dy*dy; + if (mag0 < mag) + { + dx0 = dx; + dy0 = dy; + mag0 = mag; + } + + dx = lut[p2[0]] - lut[p0[0]]; + dy = lut[nextPtr[x1]] - lut[prevPtr[x1]]; + mag = dx*dx + dy*dy; + if (mag0 < mag) + { + dx0 = dx; + dy0 = dy; + mag0 = mag; + } + + dbuf[x] = dx0; + dbuf[x+width] = dy0; + } + } + + // computing angles and magnidutes + cartToPolar( Dx, Dy, Mag, Angle, false ); + + // filling the result matrix + x = 0; +#if CV_SIMD128 + v_float32x4 fhalf = v_setall_f32(0.5f); + v_float32x4 _angleScale = v_setall_f32(angleScale), fone = v_setall_f32(1.0f); + v_int32x4 ione = v_setall_s32(1), _nbins = v_setall_s32(nbins), izero = v_setzero_s32(); + + for ( ; x <= width - 4; x += 4) + { + int x2 = x << 1; + v_float32x4 _mag = v_load(dbuf + x + (width << 1)); + v_float32x4 _angle = v_load(dbuf + x + width * 3); + _angle = (_angleScale * _angle) - fhalf; + + v_int32x4 _hidx = v_floor(_angle); + _angle -= v_cvt_f32(_hidx); + + v_float32x4 ft0 = _mag * (fone - _angle); + v_float32x4 ft1 = _mag * _angle; + + v_store_interleave(gradPtr + x2, ft0, ft1); + + v_int32x4 mask0 = _hidx >> 31; + v_int32x4 it0 = mask0 & _nbins; + mask0 = (_hidx >= _nbins); + v_int32x4 it1 = mask0 & _nbins; + _hidx += (it0 - it1); + + it0 = v_reinterpret_as_s32(v_pack(v_pack(_hidx, izero), v_reinterpret_as_s16(izero))); + _hidx += ione; + _hidx &= (_hidx < _nbins); + it1 = v_reinterpret_as_s32(v_pack(v_pack(_hidx, izero), v_reinterpret_as_s16(izero))); + v_uint8x16 it2, it3; + v_zip(v_reinterpret_as_u8(it0), v_reinterpret_as_u8(it1), it2, it3); + + v_store_low(qanglePtr + x2, it2); + } +#endif + for ( ; x < width; x++) + { + float mag = dbuf[x+width*2], angle = dbuf[x+width*3]*angleScale - 0.5f; + int hidx = cvFloor(angle); + angle -= hidx; + gradPtr[x*2] = mag*(1.f - angle); + gradPtr[x*2+1] = mag*angle; + + if (hidx < 0) + hidx += nbins; + else if (hidx >= nbins) + hidx -= nbins; + + CV_Assert((unsigned)hidx < (unsigned)nbins ); + + qanglePtr[x*2] = (uchar)hidx; + hidx++; + hidx &= hidx < nbins ? -1 : 0; + qanglePtr[x*2+1] = (uchar)hidx; + } + } + } + + struct HOGCache + { + struct BlockData + { + BlockData() : + histOfs(0), imgOffset() + {} + + int histOfs; + Point imgOffset; + }; + + struct PixData + { + size_t gradOfs, qangleOfs; + int histOfs[4]; + float histWeights[4]; + float gradWeight; + }; + + HOGCache(); + HOGCache(const HOGDescriptor* descriptor, + const Mat& img, const Size& paddingTL, const Size& paddingBR, + bool useCache, const Size& cacheStride); + virtual ~HOGCache() {} + virtual void init(const HOGDescriptor* descriptor, + const Mat& img, const Size& paddingTL, const Size& paddingBR, + bool useCache, const Size& cacheStride); + + Size windowsInImage(const Size& imageSize, const Size& winStride) const; + Rect getWindow(const Size& imageSize, const Size& winStride, int idx) const; + + const float* getBlock(Point pt, float* buf); + virtual void normalizeBlockHistogram(float* histogram) const; + + std::vector pixData; + std::vector blockData; + + bool useCache; + std::vector ymaxCached; + Size winSize; + Size cacheStride; + Size nblocks, ncells; + int blockHistogramSize; + int count1, count2, count4; + Point imgoffset; + Mat_ blockCache; + Mat_ blockCacheFlags; + + Mat grad, qangle; + const HOGDescriptor* descriptor; + }; + + HOGCache::HOGCache() : + blockHistogramSize(), count1(), count2(), count4() + { + useCache = false; + descriptor = 0; + } + + HOGCache::HOGCache(const HOGDescriptor* _descriptor, + const Mat& _img, const Size& _paddingTL, const Size& _paddingBR, + bool _useCache, const Size& _cacheStride) + { + init(_descriptor, _img, _paddingTL, _paddingBR, _useCache, _cacheStride); + } + + void HOGCache::init(const HOGDescriptor* _descriptor, + const Mat& _img, const Size& _paddingTL, const Size& _paddingBR, + bool _useCache, const Size& _cacheStride) + { + descriptor = _descriptor; + cacheStride = _cacheStride; + useCache = _useCache; + + descriptor->computeGradient(_img, grad, qangle, _paddingTL, _paddingBR); + imgoffset = _paddingTL; + + winSize = descriptor->winSize; + Size blockSize = descriptor->blockSize; + Size blockStride = descriptor->blockStride; + Size cellSize = descriptor->cellSize; + int i, j, nbins = descriptor->nbins; + int rawBlockSize = blockSize.width*blockSize.height; + + nblocks = Size((winSize.width - blockSize.width)/blockStride.width + 1, + (winSize.height - blockSize.height)/blockStride.height + 1); + ncells = Size(blockSize.width/cellSize.width, blockSize.height/cellSize.height); + blockHistogramSize = ncells.width*ncells.height*nbins; + + if (useCache) + { + Size cacheSize((grad.cols - blockSize.width)/cacheStride.width+1, + (winSize.height/cacheStride.height)+1); + + blockCache.create(cacheSize.height, cacheSize.width*blockHistogramSize); + blockCacheFlags.create(cacheSize); + + size_t cacheRows = blockCache.rows; + ymaxCached.resize(cacheRows); + for (size_t ii = 0; ii < cacheRows; ii++) + ymaxCached[ii] = -1; + } + + Mat_ weights(blockSize); + float sigma = (float)descriptor->getWinSigma(); + float scale = 1.f/(sigma*sigma*2); + + { + AutoBuffer di(blockSize.height), dj(blockSize.width); + float* _di = di.data(), *_dj = dj.data(); + float bh = blockSize.height * 0.5f, bw = blockSize.width * 0.5f; + + i = 0; + #if CV_SIMD128 + v_float32x4 idx(0.0f, 1.0f, 2.0f, 3.0f); + v_float32x4 _bw = v_setall_f32(bw), _bh = v_setall_f32(bh); + v_float32x4 ifour = v_setall_f32(4.0); + + for (; i <= blockSize.height - 4; i += 4) + { + v_float32x4 t = idx - _bh; + t *= t; + idx += ifour; + v_store(_di + i, t); + } + #endif + for ( ; i < blockSize.height; ++i) + { + _di[i] = i - bh; + _di[i] *= _di[i]; + } + + j = 0; + #if CV_SIMD128 + idx = v_float32x4(0.0f, 1.0f, 2.0f, 3.0f); + + for (; j <= blockSize.height - 4; j += 4) + { + v_float32x4 t = idx - _bw; + t *= t; + idx += ifour; + v_store(_dj + j, t); + } + #endif + for ( ; j < blockSize.width; ++j) + { + _dj[j] = j - bw; + _dj[j] *= _dj[j]; + } + + for (i = 0; i < blockSize.height; i++) + for (j = 0; j < blockSize.width; j++) + weights(i,j) = std::exp(-(_di[i] + _dj[j])*scale); + } + + blockData.resize(nblocks.width*nblocks.height); + pixData.resize(rawBlockSize*3); + + // Initialize 2 lookup tables, pixData & blockData. + // Here is why: + // + // The detection algorithm runs in 4 nested loops (at each pyramid layer): + // loop over the windows within the input image + // loop over the blocks within each window + // loop over the cells within each block + // loop over the pixels in each cell + // + // As each of the loops runs over a 2-dimensional array, + // we could get 8(!) nested loops in total, which is very-very slow. + // + // To speed the things up, we do the following: + // 1. loop over windows is unrolled in the HOGDescriptor::{compute|detect} methods; + // inside we compute the current search window using getWindow() method. + // Yes, it involves some overhead (function call + couple of divisions), + // but it's tiny in fact. + // 2. loop over the blocks is also unrolled. Inside we use pre-computed blockData[j] + // to set up gradient and histogram pointers. + // 3. loops over cells and pixels in each cell are merged + // (since there is no overlap between cells, each pixel in the block is processed once) + // and also unrolled. Inside we use PixData[k] to access the gradient values and + // update the histogram + // + + count1 = count2 = count4 = 0; + for (j = 0; j < blockSize.width; j++) + for (i = 0; i < blockSize.height; i++) + { + PixData* data = 0; + float cellX = (j+0.5f)/cellSize.width - 0.5f; + float cellY = (i+0.5f)/cellSize.height - 0.5f; + int icellX0 = cvFloor(cellX); + int icellY0 = cvFloor(cellY); + int icellX1 = icellX0 + 1, icellY1 = icellY0 + 1; + cellX -= icellX0; + cellY -= icellY0; + + if ((unsigned)icellX0 < (unsigned)ncells.width && + (unsigned)icellX1 < (unsigned)ncells.width) + { + if ((unsigned)icellY0 < (unsigned)ncells.height && + (unsigned)icellY1 < (unsigned)ncells.height) + { + data = &pixData[rawBlockSize*2 + (count4++)]; + data->histOfs[0] = (icellX0*ncells.height + icellY0)*nbins; + data->histWeights[0] = (1.f - cellX)*(1.f - cellY); + data->histOfs[1] = (icellX1*ncells.height + icellY0)*nbins; + data->histWeights[1] = cellX*(1.f - cellY); + data->histOfs[2] = (icellX0*ncells.height + icellY1)*nbins; + data->histWeights[2] = (1.f - cellX)*cellY; + data->histOfs[3] = (icellX1*ncells.height + icellY1)*nbins; + data->histWeights[3] = cellX*cellY; + } + else + { + data = &pixData[rawBlockSize + (count2++)]; + if ((unsigned)icellY0 < (unsigned)ncells.height) + { + icellY1 = icellY0; + cellY = 1.f - cellY; + } + data->histOfs[0] = (icellX0*ncells.height + icellY1)*nbins; + data->histWeights[0] = (1.f - cellX)*cellY; + data->histOfs[1] = (icellX1*ncells.height + icellY1)*nbins; + data->histWeights[1] = cellX*cellY; + data->histOfs[2] = data->histOfs[3] = 0; + data->histWeights[2] = data->histWeights[3] = 0; + } } else { - data = &pixData[count1++]; - if( (unsigned)icellY0 < (unsigned)ncells.height ) + if ((unsigned)icellX0 < (unsigned)ncells.width) { - icellY1 = icellY0; - cellY = 1.f - cellY; + icellX1 = icellX0; + cellX = 1.f - cellX; + } + + if ((unsigned)icellY0 < (unsigned)ncells.height && + (unsigned)icellY1 < (unsigned)ncells.height) + { + data = &pixData[rawBlockSize + (count2++)]; + data->histOfs[0] = (icellX1*ncells.height + icellY0)*nbins; + data->histWeights[0] = cellX*(1.f - cellY); + data->histOfs[1] = (icellX1*ncells.height + icellY1)*nbins; + data->histWeights[1] = cellX*cellY; + data->histOfs[2] = data->histOfs[3] = 0; + data->histWeights[2] = data->histWeights[3] = 0; + } + else + { + data = &pixData[count1++]; + if ((unsigned)icellY0 < (unsigned)ncells.height) + { + icellY1 = icellY0; + cellY = 1.f - cellY; + } + data->histOfs[0] = (icellX1*ncells.height + icellY1)*nbins; + data->histWeights[0] = cellX*cellY; + data->histOfs[1] = data->histOfs[2] = data->histOfs[3] = 0; + data->histWeights[1] = data->histWeights[2] = data->histWeights[3] = 0; } - data->histOfs[0] = (icellX1*ncells.height + icellY1)*nbins; - data->histWeights[0] = cellX*cellY; - data->histOfs[1] = data->histOfs[2] = data->histOfs[3] = 0; - data->histWeights[1] = data->histWeights[2] = data->histWeights[3] = 0; } + data->gradOfs = (grad.cols*i + j)*2; + data->qangleOfs = (qangle.cols*i + j)*2; + data->gradWeight = weights(i,j); } - data->gradOfs = (grad.cols*i + j)*2; - data->qangleOfs = (qangle.cols*i + j)*2; - data->gradWeight = weights(i,j); - } - assert( count1 + count2 + count4 == rawBlockSize ); - // defragment pixData - for( j = 0; j < count2; j++ ) - pixData[j + count1] = pixData[j + rawBlockSize]; - for( j = 0; j < count4; j++ ) - pixData[j + count1 + count2] = pixData[j + rawBlockSize*2]; - count2 += count1; - count4 += count2; + assert( count1 + count2 + count4 == rawBlockSize ); + // defragment pixData + for (j = 0; j < count2; j++) + pixData[j + count1] = pixData[j + rawBlockSize]; + for (j = 0; j < count4; j++) + pixData[j + count1 + count2] = pixData[j + rawBlockSize*2]; + count2 += count1; + count4 += count2; - // initialize blockData - for( j = 0; j < nblocks.width; j++ ) - for( i = 0; i < nblocks.height; i++ ) - { - BlockData& data = blockData[j*nblocks.height + i]; - data.histOfs = (j*nblocks.height + i)*blockHistogramSize; - data.imgOffset = Point(j*blockStride.width,i*blockStride.height); - } -} + // initialize blockData + for (j = 0; j < nblocks.width; j++) + for (i = 0; i < nblocks.height; i++) + { + BlockData& data = blockData[j*nblocks.height + i]; + data.histOfs = (j*nblocks.height + i)*blockHistogramSize; + data.imgOffset = Point(j*blockStride.width,i*blockStride.height); + } + } -const float* HOGCache::getBlock(Point pt, float* buf) -{ - float* blockHist = buf; - assert(descriptor != 0); + const float* HOGCache::getBlock(Point pt, float* buf) + { + float* blockHist = buf; + assert(descriptor != 0); // Size blockSize = descriptor->blockSize; - pt += imgoffset; + pt += imgoffset; // CV_Assert( (unsigned)pt.x <= (unsigned)(grad.cols - blockSize.width) && // (unsigned)pt.y <= (unsigned)(grad.rows - blockSize.height) ); - if( useCache ) - { - CV_Assert( pt.x % cacheStride.width == 0 && - pt.y % cacheStride.height == 0 ); - Point cacheIdx(pt.x/cacheStride.width, - (pt.y/cacheStride.height) % blockCache.rows); - if( pt.y != ymaxCached[cacheIdx.y] ) + if (useCache) { - Mat_ cacheRow = blockCacheFlags.row(cacheIdx.y); - cacheRow = (uchar)0; - ymaxCached[cacheIdx.y] = pt.y; + CV_Assert( pt.x % cacheStride.width == 0 && + pt.y % cacheStride.height == 0 ); + Point cacheIdx(pt.x/cacheStride.width, + (pt.y/cacheStride.height) % blockCache.rows); + if (pt.y != ymaxCached[cacheIdx.y]) + { + Mat_ cacheRow = blockCacheFlags.row(cacheIdx.y); + cacheRow = (uchar)0; + ymaxCached[cacheIdx.y] = pt.y; + } + + blockHist = &blockCache[cacheIdx.y][cacheIdx.x*blockHistogramSize]; + uchar& computedFlag = blockCacheFlags(cacheIdx.y, cacheIdx.x); + if (computedFlag != 0) + return blockHist; + computedFlag = (uchar)1; // set it at once, before actual computing } - blockHist = &blockCache[cacheIdx.y][cacheIdx.x*blockHistogramSize]; - uchar& computedFlag = blockCacheFlags(cacheIdx.y, cacheIdx.x); - if( computedFlag != 0 ) - return blockHist; - computedFlag = (uchar)1; // set it at once, before actual computing - } - - int k, C1 = count1, C2 = count2, C4 = count4; - const float* gradPtr = grad.ptr(pt.y) + pt.x*2; - const uchar* qanglePtr = qangle.ptr(pt.y) + pt.x*2; + int k, C1 = count1, C2 = count2, C4 = count4; + const float* gradPtr = grad.ptr(pt.y) + pt.x*2; + const uchar* qanglePtr = qangle.ptr(pt.y) + pt.x*2; // CV_Assert( blockHist != 0 ); - memset(blockHist, 0, sizeof(float) * blockHistogramSize); + memset(blockHist, 0, sizeof(float) * blockHistogramSize); - const PixData* _pixData = &pixData[0]; + const PixData* _pixData = &pixData[0]; - for( k = 0; k < C1; k++ ) - { - const PixData& pk = _pixData[k]; - const float* const a = gradPtr + pk.gradOfs; - float w = pk.gradWeight*pk.histWeights[0]; - const uchar* h = qanglePtr + pk.qangleOfs; - int h0 = h[0], h1 = h[1]; + for (k = 0; k < C1; k++) + { + const PixData& pk = _pixData[k]; + const float* const a = gradPtr + pk.gradOfs; + float w = pk.gradWeight*pk.histWeights[0]; + const uchar* h = qanglePtr + pk.qangleOfs; + int h0 = h[0], h1 = h[1]; - float* hist = blockHist + pk.histOfs[0]; - float t0 = hist[h0] + a[0]*w; - float t1 = hist[h1] + a[1]*w; - hist[h0] = t0; hist[h1] = t1; - } + float* hist = blockHist + pk.histOfs[0]; + float t0 = hist[h0] + a[0]*w; + float t1 = hist[h1] + a[1]*w; + hist[h0] = t0; hist[h1] = t1; + } #if CV_SIMD128 - float hist0[4], hist1[4]; - for( ; k < C2; k++ ) - { - const PixData& pk = _pixData[k]; - const float* const a = gradPtr + pk.gradOfs; - const uchar* const h = qanglePtr + pk.qangleOfs; - int h0 = h[0], h1 = h[1]; + float hist0[4], hist1[4]; + for ( ; k < C2; k++) + { + const PixData& pk = _pixData[k]; + const float* const a = gradPtr + pk.gradOfs; + const uchar* const h = qanglePtr + pk.qangleOfs; + int h0 = h[0], h1 = h[1]; - v_float32x4 _a0 = v_setall_f32(a[0]), _a1 = v_setall_f32(a[1]); - v_float32x4 w = v_setall_f32(pk.gradWeight) * v_load(pk.histWeights); - v_float32x4 _t0 = _a0 * w, _t1 = _a1 * w; + v_float32x4 _a0 = v_setall_f32(a[0]), _a1 = v_setall_f32(a[1]); + v_float32x4 w = v_setall_f32(pk.gradWeight) * v_load(pk.histWeights); + v_float32x4 _t0 = _a0 * w, _t1 = _a1 * w; - v_store(hist0, _t0); - v_store(hist1, _t1); + v_store(hist0, _t0); + v_store(hist1, _t1); - float* hist = blockHist + pk.histOfs[0]; - float t0 = hist[h0] + hist0[0]; - float t1 = hist[h1] + hist1[0]; - hist[h0] = t0; hist[h1] = t1; + float* hist = blockHist + pk.histOfs[0]; + float t0 = hist[h0] + hist0[0]; + float t1 = hist[h1] + hist1[0]; + hist[h0] = t0; hist[h1] = t1; - hist = blockHist + pk.histOfs[1]; - t0 = hist[h0] + hist0[1]; - t1 = hist[h1] + hist1[1]; - hist[h0] = t0; hist[h1] = t1; - } + hist = blockHist + pk.histOfs[1]; + t0 = hist[h0] + hist0[1]; + t1 = hist[h1] + hist1[1]; + hist[h0] = t0; hist[h1] = t1; + } #else - for( ; k < C2; k++ ) - { - const PixData& pk = _pixData[k]; - const float* const a = gradPtr + pk.gradOfs; - float w, t0, t1, a0 = a[0], a1 = a[1]; - const uchar* const h = qanglePtr + pk.qangleOfs; - int h0 = h[0], h1 = h[1]; + for ( ; k < C2; k++) + { + const PixData& pk = _pixData[k]; + const float* const a = gradPtr + pk.gradOfs; + float w, t0, t1, a0 = a[0], a1 = a[1]; + const uchar* const h = qanglePtr + pk.qangleOfs; + int h0 = h[0], h1 = h[1]; - float* hist = blockHist + pk.histOfs[0]; - w = pk.gradWeight*pk.histWeights[0]; - t0 = hist[h0] + a0*w; - t1 = hist[h1] + a1*w; - hist[h0] = t0; hist[h1] = t1; + float* hist = blockHist + pk.histOfs[0]; + w = pk.gradWeight*pk.histWeights[0]; + t0 = hist[h0] + a0*w; + t1 = hist[h1] + a1*w; + hist[h0] = t0; hist[h1] = t1; - hist = blockHist + pk.histOfs[1]; - w = pk.gradWeight*pk.histWeights[1]; - t0 = hist[h0] + a0*w; - t1 = hist[h1] + a1*w; - hist[h0] = t0; hist[h1] = t1; - } + hist = blockHist + pk.histOfs[1]; + w = pk.gradWeight*pk.histWeights[1]; + t0 = hist[h0] + a0*w; + t1 = hist[h1] + a1*w; + hist[h0] = t0; hist[h1] = t1; + } #endif #if CV_SIMD128 - for( ; k < C4; k++ ) - { - const PixData& pk = _pixData[k]; - const float* const a = gradPtr + pk.gradOfs; - const uchar* const h = qanglePtr + pk.qangleOfs; - int h0 = h[0], h1 = h[1]; + for ( ; k < C4; k++) + { + const PixData& pk = _pixData[k]; + const float* const a = gradPtr + pk.gradOfs; + const uchar* const h = qanglePtr + pk.qangleOfs; + int h0 = h[0], h1 = h[1]; - v_float32x4 _a0 = v_setall_f32(a[0]), _a1 = v_setall_f32(a[1]); - v_float32x4 w = v_setall_f32(pk.gradWeight) * v_load(pk.histWeights); - v_float32x4 _t0 = _a0 * w, _t1 = _a1 * w; + v_float32x4 _a0 = v_setall_f32(a[0]), _a1 = v_setall_f32(a[1]); + v_float32x4 w = v_setall_f32(pk.gradWeight) * v_load(pk.histWeights); + v_float32x4 _t0 = _a0 * w, _t1 = _a1 * w; - v_store(hist0, _t0); - v_store(hist1, _t1); + v_store(hist0, _t0); + v_store(hist1, _t1); - float* hist = blockHist + pk.histOfs[0]; - float t0 = hist[h0] + hist0[0]; - float t1 = hist[h1] + hist1[0]; - hist[h0] = t0; hist[h1] = t1; + float* hist = blockHist + pk.histOfs[0]; + float t0 = hist[h0] + hist0[0]; + float t1 = hist[h1] + hist1[0]; + hist[h0] = t0; hist[h1] = t1; - hist = blockHist + pk.histOfs[1]; - t0 = hist[h0] + hist0[1]; - t1 = hist[h1] + hist1[1]; - hist[h0] = t0; hist[h1] = t1; + hist = blockHist + pk.histOfs[1]; + t0 = hist[h0] + hist0[1]; + t1 = hist[h1] + hist1[1]; + hist[h0] = t0; hist[h1] = t1; - hist = blockHist + pk.histOfs[2]; - t0 = hist[h0] + hist0[2]; - t1 = hist[h1] + hist1[2]; - hist[h0] = t0; hist[h1] = t1; + hist = blockHist + pk.histOfs[2]; + t0 = hist[h0] + hist0[2]; + t1 = hist[h1] + hist1[2]; + hist[h0] = t0; hist[h1] = t1; - hist = blockHist + pk.histOfs[3]; - t0 = hist[h0] + hist0[3]; - t1 = hist[h1] + hist1[3]; - hist[h0] = t0; hist[h1] = t1; - } + hist = blockHist + pk.histOfs[3]; + t0 = hist[h0] + hist0[3]; + t1 = hist[h1] + hist1[3]; + hist[h0] = t0; hist[h1] = t1; + } #else - for( ; k < C4; k++ ) - { - const PixData& pk = _pixData[k]; - const float* a = gradPtr + pk.gradOfs; - float w, t0, t1, a0 = a[0], a1 = a[1]; - const uchar* h = qanglePtr + pk.qangleOfs; - int h0 = h[0], h1 = h[1]; + for ( ; k < C4; k++) + { + const PixData& pk = _pixData[k]; + const float* a = gradPtr + pk.gradOfs; + float w, t0, t1, a0 = a[0], a1 = a[1]; + const uchar* h = qanglePtr + pk.qangleOfs; + int h0 = h[0], h1 = h[1]; - float* hist = blockHist + pk.histOfs[0]; - w = pk.gradWeight*pk.histWeights[0]; - t0 = hist[h0] + a0*w; - t1 = hist[h1] + a1*w; - hist[h0] = t0; hist[h1] = t1; + float* hist = blockHist + pk.histOfs[0]; + w = pk.gradWeight*pk.histWeights[0]; + t0 = hist[h0] + a0*w; + t1 = hist[h1] + a1*w; + hist[h0] = t0; hist[h1] = t1; - hist = blockHist + pk.histOfs[1]; - w = pk.gradWeight*pk.histWeights[1]; - t0 = hist[h0] + a0*w; - t1 = hist[h1] + a1*w; - hist[h0] = t0; hist[h1] = t1; + hist = blockHist + pk.histOfs[1]; + w = pk.gradWeight*pk.histWeights[1]; + t0 = hist[h0] + a0*w; + t1 = hist[h1] + a1*w; + hist[h0] = t0; hist[h1] = t1; - hist = blockHist + pk.histOfs[2]; - w = pk.gradWeight*pk.histWeights[2]; - t0 = hist[h0] + a0*w; - t1 = hist[h1] + a1*w; - hist[h0] = t0; hist[h1] = t1; + hist = blockHist + pk.histOfs[2]; + w = pk.gradWeight*pk.histWeights[2]; + t0 = hist[h0] + a0*w; + t1 = hist[h1] + a1*w; + hist[h0] = t0; hist[h1] = t1; - hist = blockHist + pk.histOfs[3]; - w = pk.gradWeight*pk.histWeights[3]; - t0 = hist[h0] + a0*w; - t1 = hist[h1] + a1*w; - hist[h0] = t0; hist[h1] = t1; - } + hist = blockHist + pk.histOfs[3]; + w = pk.gradWeight*pk.histWeights[3]; + t0 = hist[h0] + a0*w; + t1 = hist[h1] + a1*w; + hist[h0] = t0; hist[h1] = t1; + } #endif - normalizeBlockHistogram(blockHist); + normalizeBlockHistogram(blockHist); - return blockHist; -} + return blockHist; + } -void HOGCache::normalizeBlockHistogram(float* _hist) const -{ - float* hist = &_hist[0], sum = 0.0f, partSum[4]; - size_t i = 0, sz = blockHistogramSize; + void HOGCache::normalizeBlockHistogram(float* _hist) const + { + float* hist = &_hist[0], sum = 0.0f, partSum[4]; + size_t i = 0, sz = blockHistogramSize; #if CV_SIMD128 - v_float32x4 p0 = v_load(hist); - v_float32x4 s = p0 * p0; + v_float32x4 p0 = v_load(hist); + v_float32x4 s = p0 * p0; - for (i = 4; i <= sz - 4; i += 4) - { - p0 = v_load(hist + i); - s += p0 * p0; - } - v_store(partSum, s); + for (i = 4; i <= sz - 4; i += 4) + { + p0 = v_load(hist + i); + s += p0 * p0; + } + v_store(partSum, s); #else - partSum[0] = 0.0f; - partSum[1] = 0.0f; - partSum[2] = 0.0f; - partSum[3] = 0.0f; - for ( ; i <= sz - 4; i += 4) - { - partSum[0] += hist[i] * hist[i]; - partSum[1] += hist[i+1] * hist[i+1]; - partSum[2] += hist[i+2] * hist[i+2]; - partSum[3] += hist[i+3] * hist[i+3]; - } + partSum[0] = 0.0f; + partSum[1] = 0.0f; + partSum[2] = 0.0f; + partSum[3] = 0.0f; + for ( ; i <= sz - 4; i += 4) + { + partSum[0] += hist[i] * hist[i]; + partSum[1] += hist[i+1] * hist[i+1]; + partSum[2] += hist[i+2] * hist[i+2]; + partSum[3] += hist[i+3] * hist[i+3]; + } #endif - float t0 = partSum[0] + partSum[1]; - float t1 = partSum[2] + partSum[3]; - sum = t0 + t1; - for ( ; i < sz; ++i) - sum += hist[i]*hist[i]; + float t0 = partSum[0] + partSum[1]; + float t1 = partSum[2] + partSum[3]; + sum = t0 + t1; + for ( ; i < sz; ++i) + sum += hist[i]*hist[i]; - float scale = 1.f/(std::sqrt(sum)+sz*0.1f), thresh = (float)descriptor->L2HysThreshold; - i = 0, sum = 0.0f; + float scale = 1.f/(std::sqrt(sum)+sz*0.1f), thresh = (float)descriptor->L2HysThreshold; + i = 0, sum = 0.0f; #if CV_SIMD128 - v_float32x4 _scale = v_setall_f32(scale); - static v_float32x4 _threshold = v_setall_f32(thresh); + v_float32x4 _scale = v_setall_f32(scale); + static v_float32x4 _threshold = v_setall_f32(thresh); - v_float32x4 p = _scale * v_load(hist); - p = v_min(p, _threshold); - s = p * p; - v_store(hist, p); - - for(i = 4 ; i <= sz - 4; i += 4) - { - p = v_load(hist + i); - p *= _scale; + v_float32x4 p = _scale * v_load(hist); p = v_min(p, _threshold); - s += p * p; - v_store(hist + i, p); - } + s = p * p; + v_store(hist, p); - v_store(partSum, s); + for (i = 4; i <= sz - 4; i += 4) + { + p = v_load(hist + i); + p *= _scale; + p = v_min(p, _threshold); + s += p * p; + v_store(hist + i, p); + } + + v_store(partSum, s); #else - partSum[0] = 0.0f; - partSum[1] = 0.0f; - partSum[2] = 0.0f; - partSum[3] = 0.0f; - for( ; i <= sz - 4; i += 4) - { - hist[i] = std::min(hist[i]*scale, thresh); - hist[i+1] = std::min(hist[i+1]*scale, thresh); - hist[i+2] = std::min(hist[i+2]*scale, thresh); - hist[i+3] = std::min(hist[i+3]*scale, thresh); - partSum[0] += hist[i]*hist[i]; - partSum[1] += hist[i+1]*hist[i+1]; - partSum[2] += hist[i+2]*hist[i+2]; - partSum[3] += hist[i+3]*hist[i+3]; - } + partSum[0] = 0.0f; + partSum[1] = 0.0f; + partSum[2] = 0.0f; + partSum[3] = 0.0f; + for ( ; i <= sz - 4; i += 4) + { + hist[i] = std::min(hist[i]*scale, thresh); + hist[i+1] = std::min(hist[i+1]*scale, thresh); + hist[i+2] = std::min(hist[i+2]*scale, thresh); + hist[i+3] = std::min(hist[i+3]*scale, thresh); + partSum[0] += hist[i]*hist[i]; + partSum[1] += hist[i+1]*hist[i+1]; + partSum[2] += hist[i+2]*hist[i+2]; + partSum[3] += hist[i+3]*hist[i+3]; + } #endif - t0 = partSum[0] + partSum[1]; - t1 = partSum[2] + partSum[3]; - sum = t0 + t1; - for( ; i < sz; ++i) - { - hist[i] = std::min(hist[i]*scale, thresh); - sum += hist[i]*hist[i]; - } + t0 = partSum[0] + partSum[1]; + t1 = partSum[2] + partSum[3]; + sum = t0 + t1; + for ( ; i < sz; ++i) + { + hist[i] = std::min(hist[i]*scale, thresh); + sum += hist[i]*hist[i]; + } - scale = 1.f/(std::sqrt(sum)+1e-3f), i = 0; + scale = 1.f/(std::sqrt(sum)+1e-3f), i = 0; #if CV_SIMD128 - v_float32x4 _scale2 = v_setall_f32(scale); - for ( ; i <= sz - 4; i += 4) - { - v_float32x4 t = _scale2 * v_load(hist + i); - v_store(hist + i, t); - } + v_float32x4 _scale2 = v_setall_f32(scale); + for ( ; i <= sz - 4; i += 4) + { + v_float32x4 t = _scale2 * v_load(hist + i); + v_store(hist + i, t); + } #endif - for ( ; i < sz; ++i) - hist[i] *= scale; -} - -Size HOGCache::windowsInImage(const Size& imageSize, const Size& winStride) const -{ - return Size((imageSize.width - winSize.width)/winStride.width + 1, - (imageSize.height - winSize.height)/winStride.height + 1); -} - -Rect HOGCache::getWindow(const Size& imageSize, const Size& winStride, int idx) const -{ - int nwindowsX = (imageSize.width - winSize.width)/winStride.width + 1; - int y = idx / nwindowsX; - int x = idx - nwindowsX*y; - return Rect( x*winStride.width, y*winStride.height, winSize.width, winSize.height ); -} - -static inline int gcd(int a, int b) -{ - if( a < b ) - std::swap(a, b); - while( b > 0 ) - { - int r = a % b; - a = b; - b = r; + for ( ; i < sz; ++i) + hist[i] *= scale; + } + + Size HOGCache::windowsInImage(const Size& imageSize, const Size& winStride) const + { + return Size((imageSize.width - winSize.width)/winStride.width + 1, + (imageSize.height - winSize.height)/winStride.height + 1); + } + + Rect HOGCache::getWindow(const Size& imageSize, const Size& winStride, int idx) const + { + int nwindowsX = (imageSize.width - winSize.width)/winStride.width + 1; + int y = idx / nwindowsX; + int x = idx - nwindowsX*y; + return Rect( x*winStride.width, y*winStride.height, winSize.width, winSize.height ); + } + + static inline int gcd(int a, int b) + { + if (a < b) + std::swap(a, b); + while (b > 0) + { + int r = a % b; + a = b; + b = r; + } + return a; } - return a; -} #ifdef HAVE_OPENCL -static bool ocl_compute_gradients_8UC1(int height, int width, InputArray _img, float angle_scale, - UMat grad, UMat qangle, bool correct_gamma, int nbins) -{ - ocl::Kernel k("compute_gradients_8UC1_kernel", ocl::objdetect::objdetect_hog_oclsrc); - if(k.empty()) - return false; + static bool ocl_compute_gradients_8UC1(int height, int width, InputArray _img, float angle_scale, + UMat grad, UMat qangle, bool correct_gamma, int nbins) + { + ocl::Kernel k("compute_gradients_8UC1_kernel", ocl::objdetect::objdetect_hog_oclsrc); + if (k.empty()) + return false; - UMat img = _img.getUMat(); + UMat img = _img.getUMat(); - size_t localThreads[3] = { NTHREADS, 1, 1 }; - size_t globalThreads[3] = { (size_t)width, (size_t)height, 1 }; - char correctGamma = (correct_gamma) ? 1 : 0; - int grad_quadstep = (int)grad.step >> 3; - int qangle_elem_size = CV_ELEM_SIZE1(qangle.type()); - int qangle_step = (int)qangle.step / (2 * qangle_elem_size); + size_t localThreads[3] = { NTHREADS, 1, 1 }; + size_t globalThreads[3] = { (size_t)width, (size_t)height, 1 }; + char correctGamma = (correct_gamma) ? 1 : 0; + int grad_quadstep = (int)grad.step >> 3; + int qangle_elem_size = CV_ELEM_SIZE1(qangle.type()); + int qangle_step = (int)qangle.step / (2 * qangle_elem_size); - int idx = 0; - idx = k.set(idx, height); - idx = k.set(idx, width); - idx = k.set(idx, (int)img.step1()); - idx = k.set(idx, grad_quadstep); - idx = k.set(idx, qangle_step); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(img)); - idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(grad)); - idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(qangle)); - idx = k.set(idx, angle_scale); - idx = k.set(idx, correctGamma); - idx = k.set(idx, nbins); + int idx = 0; + idx = k.set(idx, height); + idx = k.set(idx, width); + idx = k.set(idx, (int)img.step1()); + idx = k.set(idx, grad_quadstep); + idx = k.set(idx, qangle_step); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(img)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(grad)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(qangle)); + idx = k.set(idx, angle_scale); + idx = k.set(idx, correctGamma); + idx = k.set(idx, nbins); - return k.run(2, globalThreads, localThreads, false); -} + return k.run(2, globalThreads, localThreads, false); + } -static bool ocl_computeGradient(InputArray img, UMat grad, UMat qangle, int nbins, Size effect_size, bool gamma_correction, bool signedGradient) -{ - float angleScale = signedGradient ? (float)(nbins/(2.0*CV_PI)) : (float)(nbins/CV_PI); + static bool ocl_computeGradient(InputArray img, UMat grad, UMat qangle, int nbins, Size effect_size, bool gamma_correction, bool signedGradient) + { + float angleScale = signedGradient ? (float)(nbins/(2.0*CV_PI)) : (float)(nbins/CV_PI); - return ocl_compute_gradients_8UC1(effect_size.height, effect_size.width, img, - angleScale, grad, qangle, gamma_correction, nbins); -} + return ocl_compute_gradients_8UC1(effect_size.height, effect_size.width, img, + angleScale, grad, qangle, gamma_correction, nbins); + } #define CELL_WIDTH 8 #define CELL_HEIGHT 8 #define CELLS_PER_BLOCK_X 2 #define CELLS_PER_BLOCK_Y 2 -static bool ocl_compute_hists(int nbins, int block_stride_x, int block_stride_y, int height, int width, - UMat grad, UMat qangle, UMat gauss_w_lut, UMat block_hists, size_t block_hist_size) -{ - ocl::Kernel k("compute_hists_lut_kernel", ocl::objdetect::objdetect_hog_oclsrc); - if(k.empty()) - return false; - bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU; - cv::String opts; - if(is_cpu) - opts = "-D CPU "; - else - opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); - k.create("compute_hists_lut_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); - if(k.empty()) - return false; - - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x)/block_stride_x; - int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y)/block_stride_y; - int blocks_total = img_block_width * img_block_height; - - int qangle_elem_size = CV_ELEM_SIZE1(qangle.type()); - int grad_quadstep = (int)grad.step >> 2; - int qangle_step = (int)qangle.step / qangle_elem_size; - - int blocks_in_group = 4; - size_t localThreads[3] = { (size_t)blocks_in_group * 24, 2, 1 }; - size_t globalThreads[3] = {((img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group) * localThreads[0], 2, 1 }; - - int hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12) * sizeof(float); - int final_hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y) * sizeof(float); - - int smem = (hists_size + final_hists_size) * blocks_in_group; - - int idx = 0; - idx = k.set(idx, block_stride_x); - idx = k.set(idx, block_stride_y); - idx = k.set(idx, nbins); - idx = k.set(idx, (int)block_hist_size); - idx = k.set(idx, img_block_width); - idx = k.set(idx, blocks_in_group); - idx = k.set(idx, blocks_total); - idx = k.set(idx, grad_quadstep); - idx = k.set(idx, qangle_step); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(grad)); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(qangle)); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(gauss_w_lut)); - idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(block_hists)); - idx = k.set(idx, (void*)NULL, (size_t)smem); - - return k.run(2, globalThreads, localThreads, false); -} - -static int power_2up(unsigned int n) -{ - for(unsigned int i = 1; i<=1024; i<<=1) - if(n < i) - return i; - return -1; // Input is too big -} - -static bool ocl_normalize_hists(int nbins, int block_stride_x, int block_stride_y, - int height, int width, UMat block_hists, float threshold) -{ - int block_hist_size = nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y; - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) - / block_stride_x; - int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y) - / block_stride_y; - int nthreads; - size_t globalThreads[3] = { 1, 1, 1 }; - size_t localThreads[3] = { 1, 1, 1 }; - - int idx = 0; - bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU; - cv::String opts; - ocl::Kernel k; - if ( nbins == 9 ) + static bool ocl_compute_hists(int nbins, int block_stride_x, int block_stride_y, int height, int width, + UMat grad, UMat qangle, UMat gauss_w_lut, UMat block_hists, size_t block_hist_size) { - k.create("normalize_hists_36_kernel", ocl::objdetect::objdetect_hog_oclsrc, ""); - if(k.empty()) + ocl::Kernel k("compute_hists_lut_kernel", ocl::objdetect::objdetect_hog_oclsrc); + if (k.empty()) return false; - if(is_cpu) - opts = "-D CPU "; + bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU; + cv::String opts; + if (is_cpu) + opts = "-D CPU "; else opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); - k.create("normalize_hists_36_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); - if(k.empty()) + k.create("compute_hists_lut_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); + if (k.empty()) return false; - int blocks_in_group = NTHREADS / block_hist_size; - nthreads = blocks_in_group * block_hist_size; - int num_groups = (img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group; - globalThreads[0] = nthreads * num_groups; - localThreads[0] = nthreads; - } - else - { - k.create("normalize_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32"); - if(k.empty()) - return false; - if(is_cpu) - opts = "-D CPU "; - else - opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); - k.create("normalize_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); - if(k.empty()) - return false; + int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x)/block_stride_x; + int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y)/block_stride_y; + int blocks_total = img_block_width * img_block_height; - nthreads = power_2up(block_hist_size); - globalThreads[0] = img_block_width * nthreads; - globalThreads[1] = img_block_height; - localThreads[0] = nthreads; + int qangle_elem_size = CV_ELEM_SIZE1(qangle.type()); + int grad_quadstep = (int)grad.step >> 2; + int qangle_step = (int)qangle.step / qangle_elem_size; - if ((nthreads < 32) || (nthreads > 512) ) - return false; + int blocks_in_group = 4; + size_t localThreads[3] = { (size_t)blocks_in_group * 24, 2, 1 }; + size_t globalThreads[3] = {((img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group) * localThreads[0], 2, 1 }; - idx = k.set(idx, nthreads); - idx = k.set(idx, block_hist_size); + int hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12) * sizeof(float); + int final_hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y) * sizeof(float); + + int smem = (hists_size + final_hists_size) * blocks_in_group; + + int idx = 0; + idx = k.set(idx, block_stride_x); + idx = k.set(idx, block_stride_y); + idx = k.set(idx, nbins); + idx = k.set(idx, (int)block_hist_size); idx = k.set(idx, img_block_width); - } - idx = k.set(idx, ocl::KernelArg::PtrReadWrite(block_hists)); - idx = k.set(idx, threshold); - idx = k.set(idx, (void*)NULL, nthreads * sizeof(float)); + idx = k.set(idx, blocks_in_group); + idx = k.set(idx, blocks_total); + idx = k.set(idx, grad_quadstep); + idx = k.set(idx, qangle_step); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(grad)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(qangle)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(gauss_w_lut)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(block_hists)); + idx = k.set(idx, (void*)NULL, (size_t)smem); - return k.run(2, globalThreads, localThreads, false); -} - -static bool ocl_extract_descrs_by_rows(int win_height, int win_width, int block_stride_y, int block_stride_x, int win_stride_y, int win_stride_x, - int height, int width, UMat block_hists, UMat descriptors, - int block_hist_size, int descr_size, int descr_width) -{ - ocl::Kernel k("extract_descrs_by_rows_kernel", ocl::objdetect::objdetect_hog_oclsrc); - if(k.empty()) - return false; - - int win_block_stride_x = win_stride_x / block_stride_x; - int win_block_stride_y = win_stride_y / block_stride_y; - int img_win_width = (width - win_width + win_stride_x) / win_stride_x; - int img_win_height = (height - win_height + win_stride_y) / win_stride_y; - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / - block_stride_x; - - int descriptors_quadstep = (int)descriptors.step >> 2; - - size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 }; - size_t localThreads[3] = { NTHREADS, 1, 1 }; - - int idx = 0; - idx = k.set(idx, block_hist_size); - idx = k.set(idx, descriptors_quadstep); - idx = k.set(idx, descr_size); - idx = k.set(idx, descr_width); - idx = k.set(idx, img_block_width); - idx = k.set(idx, win_block_stride_x); - idx = k.set(idx, win_block_stride_y); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists)); - idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(descriptors)); - - return k.run(2, globalThreads, localThreads, false); -} - -static bool ocl_extract_descrs_by_cols(int win_height, int win_width, int block_stride_y, int block_stride_x, int win_stride_y, int win_stride_x, - int height, int width, UMat block_hists, UMat descriptors, - int block_hist_size, int descr_size, int nblocks_win_x, int nblocks_win_y) -{ - ocl::Kernel k("extract_descrs_by_cols_kernel", ocl::objdetect::objdetect_hog_oclsrc); - if(k.empty()) - return false; - - int win_block_stride_x = win_stride_x / block_stride_x; - int win_block_stride_y = win_stride_y / block_stride_y; - int img_win_width = (width - win_width + win_stride_x) / win_stride_x; - int img_win_height = (height - win_height + win_stride_y) / win_stride_y; - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / - block_stride_x; - - int descriptors_quadstep = (int)descriptors.step >> 2; - - size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 }; - size_t localThreads[3] = { NTHREADS, 1, 1 }; - - int idx = 0; - idx = k.set(idx, block_hist_size); - idx = k.set(idx, descriptors_quadstep); - idx = k.set(idx, descr_size); - idx = k.set(idx, nblocks_win_x); - idx = k.set(idx, nblocks_win_y); - idx = k.set(idx, img_block_width); - idx = k.set(idx, win_block_stride_x); - idx = k.set(idx, win_block_stride_y); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists)); - idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(descriptors)); - - return k.run(2, globalThreads, localThreads, false); -} - -static bool ocl_compute(InputArray _img, Size win_stride, std::vector& _descriptors, int descr_format, Size blockSize, - Size cellSize, int nbins, Size blockStride, Size winSize, float sigma, bool gammaCorrection, double L2HysThreshold, bool signedGradient) -{ - Size imgSize = _img.size(); - Size effect_size = imgSize; - - UMat grad(imgSize, CV_32FC2); - int qangle_type = ocl::Device::getDefault().isIntel() ? CV_32SC2 : CV_8UC2; - UMat qangle(imgSize, qangle_type); - - const size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins); - const Size blocks_per_img = numPartsWithin(imgSize, blockSize, blockStride); - UMat block_hists(1, static_cast(block_hist_size * blocks_per_img.area()) + 256, CV_32F); - - Size wins_per_img = numPartsWithin(imgSize, winSize, win_stride); - UMat labels(1, wins_per_img.area(), CV_8U); - - float scale = 1.f / (2.f * sigma * sigma); - Mat gaussian_lut(1, 512, CV_32FC1); - int idx = 0; - for(int i=-8; i<8; i++) - for(int j=-8; j<8; j++) - gaussian_lut.at(idx++) = std::exp(-(j * j + i * i) * scale); - for(int i=-8; i<8; i++) - for(int j=-8; j<8; j++) - gaussian_lut.at(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f; - - if(!ocl_computeGradient(_img, grad, qangle, nbins, effect_size, gammaCorrection, signedGradient)) - return false; - - UMat gauss_w_lut; - gaussian_lut.copyTo(gauss_w_lut); - if(!ocl_compute_hists(nbins, blockStride.width, blockStride.height, effect_size.height, - effect_size.width, grad, qangle, gauss_w_lut, block_hists, block_hist_size)) - return false; - - if(!ocl_normalize_hists(nbins, blockStride.width, blockStride.height, effect_size.height, - effect_size.width, block_hists, (float)L2HysThreshold)) - return false; - - Size blocks_per_win = numPartsWithin(winSize, blockSize, blockStride); - wins_per_img = numPartsWithin(effect_size, winSize, win_stride); - - int descr_size = blocks_per_win.area()*(int)block_hist_size; - int descr_width = (int)block_hist_size*blocks_per_win.width; - - UMat descriptors(wins_per_img.area(), static_cast(blocks_per_win.area() * block_hist_size), CV_32F); - switch (descr_format) - { - case DESCR_FORMAT_ROW_BY_ROW: - if(!ocl_extract_descrs_by_rows(winSize.height, winSize.width, - blockStride.height, blockStride.width, win_stride.height, win_stride.width, effect_size.height, - effect_size.width, block_hists, descriptors, (int)block_hist_size, descr_size, descr_width)) - return false; - break; - case DESCR_FORMAT_COL_BY_COL: - if(!ocl_extract_descrs_by_cols(winSize.height, winSize.width, - blockStride.height, blockStride.width, win_stride.height, win_stride.width, effect_size.height, effect_size.width, - block_hists, descriptors, (int)block_hist_size, descr_size, blocks_per_win.width, blocks_per_win.height)) - return false; - break; - default: - return false; - } - descriptors.reshape(1, (int)descriptors.total()).getMat(ACCESS_READ).copyTo(_descriptors); - return true; -} -#endif //HAVE_OPENCL - -void HOGDescriptor::compute(InputArray _img, std::vector& descriptors, - Size winStride, Size padding, const std::vector& locations) const -{ - CV_INSTRUMENT_REGION(); - - if( winStride == Size() ) - winStride = cellSize; - Size cacheStride(gcd(winStride.width, blockStride.width), - gcd(winStride.height, blockStride.height)); - - Size imgSize = _img.size(); - - size_t nwindows = locations.size(); - padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width); - padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height); - Size paddedImgSize(imgSize.width + padding.width*2, imgSize.height + padding.height*2); - - CV_OCL_RUN(_img.dims() <= 2 && _img.type() == CV_8UC1 && _img.isUMat(), - ocl_compute(_img, winStride, descriptors, DESCR_FORMAT_COL_BY_COL, blockSize, - cellSize, nbins, blockStride, winSize, (float)getWinSigma(), gammaCorrection, L2HysThreshold, signedGradient)) - - Mat img = _img.getMat(); - HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride); - - if( !nwindows ) - nwindows = cache.windowsInImage(paddedImgSize, winStride).area(); - - const HOGCache::BlockData* blockData = &cache.blockData[0]; - - int nblocks = cache.nblocks.area(); - int blockHistogramSize = cache.blockHistogramSize; - size_t dsize = getDescriptorSize(); - descriptors.resize(dsize*nwindows); - - // for each window - for( size_t i = 0; i < nwindows; i++ ) - { - float* descriptor = &descriptors[i*dsize]; - - Point pt0; - if( !locations.empty() ) - { - pt0 = locations[i]; - if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width || - pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height ) - continue; - } - else - { - pt0 = cache.getWindow(paddedImgSize, winStride, (int)i).tl() - Point(padding); -// CV_Assert(pt0.x % cacheStride.width == 0 && pt0.y % cacheStride.height == 0); - } - - for( int j = 0; j < nblocks; j++ ) - { - const HOGCache::BlockData& bj = blockData[j]; - Point pt = pt0 + bj.imgOffset; - - float* dst = descriptor + bj.histOfs; - const float* src = cache.getBlock(pt, dst); - if( src != dst ) - memcpy(dst, src, blockHistogramSize * sizeof(float)); - } - } -} - -void HOGDescriptor::detect(const Mat& img, - std::vector& hits, std::vector& weights, double hitThreshold, - Size winStride, Size padding, const std::vector& locations) const -{ - CV_INSTRUMENT_REGION(); - - hits.clear(); - weights.clear(); - if( svmDetector.empty() ) - return; - - if( winStride == Size() ) - winStride = cellSize; - Size cacheStride(gcd(winStride.width, blockStride.width), - gcd(winStride.height, blockStride.height)); - - size_t nwindows = locations.size(); - padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width); - padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height); - Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2); - - HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride); - - if( !nwindows ) - nwindows = cache.windowsInImage(paddedImgSize, winStride).area(); - - const HOGCache::BlockData* blockData = &cache.blockData[0]; - - int nblocks = cache.nblocks.area(); - int blockHistogramSize = cache.blockHistogramSize; - size_t dsize = getDescriptorSize(); - - double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0; - std::vector blockHist(blockHistogramSize); - -#if CV_SIMD128 - float partSum[4]; -#endif - - for( size_t i = 0; i < nwindows; i++ ) - { - Point pt0; - if( !locations.empty() ) - { - pt0 = locations[i]; - if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width || - pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height ) - continue; - } - else - { - pt0 = cache.getWindow(paddedImgSize, winStride, (int)i).tl() - Point(padding); - CV_Assert(pt0.x % cacheStride.width == 0 && pt0.y % cacheStride.height == 0); - } - double s = rho; - const float* svmVec = &svmDetector[0]; - - int j, k; - for( j = 0; j < nblocks; j++, svmVec += blockHistogramSize ) - { - const HOGCache::BlockData& bj = blockData[j]; - Point pt = pt0 + bj.imgOffset; - - const float* vec = cache.getBlock(pt, &blockHist[0]); -#if CV_SIMD128 - v_float32x4 _vec = v_load(vec); - v_float32x4 _svmVec = v_load(svmVec); - v_float32x4 sum = _svmVec * _vec; - - for( k = 4; k <= blockHistogramSize - 4; k += 4 ) - { - _vec = v_load(vec + k); - _svmVec = v_load(svmVec + k); - - sum += _vec * _svmVec; - } - - v_store(partSum, sum); - double t0 = partSum[0] + partSum[1]; - double t1 = partSum[2] + partSum[3]; - s += t0 + t1; -#else - for( k = 0; k <= blockHistogramSize - 4; k += 4 ) - s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] + - vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3]; -#endif - for( ; k < blockHistogramSize; k++ ) - s += vec[k]*svmVec[k]; - } - if( s >= hitThreshold ) - { - hits.push_back(pt0); - weights.push_back(s); - } - } -} - -void HOGDescriptor::detect(const Mat& img, std::vector& hits, double hitThreshold, - Size winStride, Size padding, const std::vector& locations) const -{ - CV_INSTRUMENT_REGION(); - - std::vector weightsV; - detect(img, hits, weightsV, hitThreshold, winStride, padding, locations); -} - -class HOGInvoker : - public ParallelLoopBody -{ -public: - HOGInvoker( const HOGDescriptor* _hog, const Mat& _img, - double _hitThreshold, const Size& _winStride, const Size& _padding, - const double* _levelScale, std::vector * _vec, Mutex* _mtx, - std::vector* _weights=0, std::vector* _scales=0 ) - { - hog = _hog; - img = _img; - hitThreshold = _hitThreshold; - winStride = _winStride; - padding = _padding; - levelScale = _levelScale; - vec = _vec; - weights = _weights; - scales = _scales; - mtx = _mtx; + return k.run(2, globalThreads, localThreads, false); } - void operator()(const Range& range) const CV_OVERRIDE + static int power_2up(unsigned int n) { - int i, i1 = range.start, i2 = range.end; - double minScale = i1 > 0 ? levelScale[i1] : i2 > 1 ? levelScale[i1+1] : std::max(img.cols, img.rows); - Size maxSz(cvCeil(img.cols/minScale), cvCeil(img.rows/minScale)); - Mat smallerImgBuf(maxSz, img.type()); - std::vector locations; - std::vector hitsWeights; + for (unsigned int i = 1; i<=1024; i<<=1) + if (n < i) + return i; + return -1; // Input is too big + } - for( i = i1; i < i2; i++ ) + static bool ocl_normalize_hists(int nbins, int block_stride_x, int block_stride_y, + int height, int width, UMat block_hists, float threshold) + { + int block_hist_size = nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y; + int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) + / block_stride_x; + int img_block_height = (height - CELLS_PER_BLOCK_Y * CELL_HEIGHT + block_stride_y) + / block_stride_y; + int nthreads; + size_t globalThreads[3] = { 1, 1, 1 }; + size_t localThreads[3] = { 1, 1, 1 }; + + int idx = 0; + bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU; + cv::String opts; + ocl::Kernel k; + if (nbins == 9) { - double scale = levelScale[i]; - Size sz(cvRound(img.cols/scale), cvRound(img.rows/scale)); - Mat smallerImg(sz, img.type(), smallerImgBuf.ptr()); - if( sz == img.size() ) - smallerImg = Mat(sz, img.type(), img.data, img.step); + k.create("normalize_hists_36_kernel", ocl::objdetect::objdetect_hog_oclsrc, ""); + if (k.empty()) + return false; + if (is_cpu) + opts = "-D CPU "; else - resize(img, smallerImg, sz, 0, 0, INTER_LINEAR_EXACT); - hog->detect(smallerImg, locations, hitsWeights, hitThreshold, winStride, padding); - Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); - - mtx->lock(); - for( size_t j = 0; j < locations.size(); j++ ) - { - vec->push_back(Rect(cvRound(locations[j].x*scale), - cvRound(locations[j].y*scale), - scaledWinSize.width, scaledWinSize.height)); - if (scales) - scales->push_back(scale); - } - mtx->unlock(); - - if (weights && (!hitsWeights.empty())) - { - mtx->lock(); - for (size_t j = 0; j < locations.size(); j++) - weights->push_back(hitsWeights[j]); - mtx->unlock(); - } - } - } - -private: - const HOGDescriptor* hog; - Mat img; - double hitThreshold; - Size winStride; - Size padding; - const double* levelScale; - std::vector* vec; - std::vector* weights; - std::vector* scales; - Mutex* mtx; -}; - -#ifdef HAVE_OPENCL - -static bool ocl_classify_hists(int win_height, int win_width, int block_stride_y, int block_stride_x, - int win_stride_y, int win_stride_x, int height, int width, - const UMat& block_hists, UMat detector, - float free_coef, float threshold, UMat& labels, Size descr_size, int block_hist_size) -{ - int nthreads; - bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU; - cv::String opts; - - ocl::Kernel k; - int idx = 0; - switch (descr_size.width) - { - case 180: - nthreads = 180; - k.create("classify_hists_180_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32"); - if(k.empty()) - return false; - if(is_cpu) - opts = "-D CPU "; - else - opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); - k.create("classify_hists_180_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); - if(k.empty()) - return false; - idx = k.set(idx, descr_size.width); - idx = k.set(idx, descr_size.height); - break; - - case 252: - nthreads = 256; - k.create("classify_hists_252_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32"); - if(k.empty()) - return false; - if(is_cpu) - opts = "-D CPU "; - else - opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); - k.create("classify_hists_252_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); - if(k.empty()) - return false; - idx = k.set(idx, descr_size.width); - idx = k.set(idx, descr_size.height); - break; - - default: - nthreads = 256; - k.create("classify_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32"); - if(k.empty()) - return false; - if(is_cpu) - opts = "-D CPU "; - else - opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); - k.create("classify_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); - if(k.empty()) - return false; - idx = k.set(idx, descr_size.area()); - idx = k.set(idx, descr_size.height); - } - - int win_block_stride_x = win_stride_x / block_stride_x; - int win_block_stride_y = win_stride_y / block_stride_y; - int img_win_width = (width - win_width + win_stride_x) / win_stride_x; - int img_win_height = (height - win_height + win_stride_y) / win_stride_y; - int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / - block_stride_x; - - size_t globalThreads[3] = { (size_t)img_win_width * nthreads, (size_t)img_win_height, 1 }; - size_t localThreads[3] = { (size_t)nthreads, 1, 1 }; - - idx = k.set(idx, block_hist_size); - idx = k.set(idx, img_win_width); - idx = k.set(idx, img_block_width); - idx = k.set(idx, win_block_stride_x); - idx = k.set(idx, win_block_stride_y); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists)); - idx = k.set(idx, ocl::KernelArg::PtrReadOnly(detector)); - idx = k.set(idx, free_coef); - idx = k.set(idx, threshold); - idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(labels)); - - return k.run(2, globalThreads, localThreads, false); -} - -static bool ocl_detect(InputArray img, std::vector &hits, double hit_threshold, Size win_stride, - const UMat& oclSvmDetector, Size blockSize, Size cellSize, int nbins, Size blockStride, Size winSize, - bool gammaCorrection, double L2HysThreshold, float sigma, float free_coef, bool signedGradient) -{ - hits.clear(); - if (oclSvmDetector.empty()) - return false; - - Size imgSize = img.size(); - Size effect_size = imgSize; - UMat grad(imgSize, CV_32FC2); - int qangle_type = ocl::Device::getDefault().isIntel() ? CV_32SC2 : CV_8UC2; - UMat qangle(imgSize, qangle_type); - - const size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins); - const Size blocks_per_img = numPartsWithin(imgSize, blockSize, blockStride); - UMat block_hists(1, static_cast(block_hist_size * blocks_per_img.area()) + 256, CV_32F); - - Size wins_per_img = numPartsWithin(imgSize, winSize, win_stride); - UMat labels(1, wins_per_img.area(), CV_8U); - - float scale = 1.f / (2.f * sigma * sigma); - Mat gaussian_lut(1, 512, CV_32FC1); - int idx = 0; - for(int i=-8; i<8; i++) - for(int j=-8; j<8; j++) - gaussian_lut.at(idx++) = std::exp(-(j * j + i * i) * scale); - for(int i=-8; i<8; i++) - for(int j=-8; j<8; j++) - gaussian_lut.at(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f; - - if(!ocl_computeGradient(img, grad, qangle, nbins, effect_size, gammaCorrection, signedGradient)) - return false; - - UMat gauss_w_lut; - gaussian_lut.copyTo(gauss_w_lut); - if(!ocl_compute_hists(nbins, blockStride.width, blockStride.height, effect_size.height, - effect_size.width, grad, qangle, gauss_w_lut, block_hists, block_hist_size)) - return false; - - if(!ocl_normalize_hists(nbins, blockStride.width, blockStride.height, effect_size.height, - effect_size.width, block_hists, (float)L2HysThreshold)) - return false; - - Size blocks_per_win = numPartsWithin(winSize, blockSize, blockStride); - - Size descr_size((int)block_hist_size*blocks_per_win.width, blocks_per_win.height); - - if(!ocl_classify_hists(winSize.height, winSize.width, blockStride.height, - blockStride.width, win_stride.height, win_stride.width, - effect_size.height, effect_size.width, block_hists, oclSvmDetector, - free_coef, (float)hit_threshold, labels, descr_size, (int)block_hist_size)) - return false; - - Mat labels_host = labels.getMat(ACCESS_READ); - unsigned char *vec = labels_host.ptr(); - for (int i = 0; i < wins_per_img.area(); i++) - { - int y = i / wins_per_img.width; - int x = i - wins_per_img.width * y; - if (vec[i]) - { - hits.push_back(Point(x * win_stride.width, y * win_stride.height)); - } - } - return true; -} - -static bool ocl_detectMultiScale(InputArray _img, std::vector &found_locations, std::vector& level_scale, - double hit_threshold, Size win_stride, double group_threshold, - const UMat& oclSvmDetector, Size blockSize, Size cellSize, - int nbins, Size blockStride, Size winSize, bool gammaCorrection, - double L2HysThreshold, float sigma, float free_coef, bool signedGradient) -{ - std::vector all_candidates; - std::vector locations; - UMat image_scale; - Size imgSize = _img.size(); - image_scale.create(imgSize, _img.type()); - - for (size_t i = 0; i 512)) + return false; + + idx = k.set(idx, nthreads); + idx = k.set(idx, block_hist_size); + idx = k.set(idx, img_block_width); + } + idx = k.set(idx, ocl::KernelArg::PtrReadWrite(block_hists)); + idx = k.set(idx, threshold); + idx = k.set(idx, (void*)NULL, nthreads * sizeof(float)); + + return k.run(2, globalThreads, localThreads, false); + } + + static bool ocl_extract_descrs_by_rows(int win_height, int win_width, int block_stride_y, int block_stride_x, int win_stride_y, int win_stride_x, + int height, int width, UMat block_hists, UMat descriptors, + int block_hist_size, int descr_size, int descr_width) + { + ocl::Kernel k("extract_descrs_by_rows_kernel", ocl::objdetect::objdetect_hog_oclsrc); + if (k.empty()) + return false; + + int win_block_stride_x = win_stride_x / block_stride_x; + int win_block_stride_y = win_stride_y / block_stride_y; + int img_win_width = (width - win_width + win_stride_x) / win_stride_x; + int img_win_height = (height - win_height + win_stride_y) / win_stride_y; + int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / + block_stride_x; + + int descriptors_quadstep = (int)descriptors.step >> 2; + + size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 }; + size_t localThreads[3] = { NTHREADS, 1, 1 }; + + int idx = 0; + idx = k.set(idx, block_hist_size); + idx = k.set(idx, descriptors_quadstep); + idx = k.set(idx, descr_size); + idx = k.set(idx, descr_width); + idx = k.set(idx, img_block_width); + idx = k.set(idx, win_block_stride_x); + idx = k.set(idx, win_block_stride_y); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(descriptors)); + + return k.run(2, globalThreads, localThreads, false); + } + + static bool ocl_extract_descrs_by_cols(int win_height, int win_width, int block_stride_y, int block_stride_x, int win_stride_y, int win_stride_x, + int height, int width, UMat block_hists, UMat descriptors, + int block_hist_size, int descr_size, int nblocks_win_x, int nblocks_win_y) + { + ocl::Kernel k("extract_descrs_by_cols_kernel", ocl::objdetect::objdetect_hog_oclsrc); + if (k.empty()) + return false; + + int win_block_stride_x = win_stride_x / block_stride_x; + int win_block_stride_y = win_stride_y / block_stride_y; + int img_win_width = (width - win_width + win_stride_x) / win_stride_x; + int img_win_height = (height - win_height + win_stride_y) / win_stride_y; + int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / + block_stride_x; + + int descriptors_quadstep = (int)descriptors.step >> 2; + + size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 }; + size_t localThreads[3] = { NTHREADS, 1, 1 }; + + int idx = 0; + idx = k.set(idx, block_hist_size); + idx = k.set(idx, descriptors_quadstep); + idx = k.set(idx, descr_size); + idx = k.set(idx, nblocks_win_x); + idx = k.set(idx, nblocks_win_y); + idx = k.set(idx, img_block_width); + idx = k.set(idx, win_block_stride_x); + idx = k.set(idx, win_block_stride_y); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists)); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(descriptors)); + + return k.run(2, globalThreads, localThreads, false); + } + + static bool ocl_compute(InputArray _img, Size win_stride, std::vector& _descriptors, int descr_format, Size blockSize, + Size cellSize, int nbins, Size blockStride, Size winSize, float sigma, bool gammaCorrection, double L2HysThreshold, bool signedGradient) + { + Size imgSize = _img.size(); + Size effect_size = imgSize; + + UMat grad(imgSize, CV_32FC2); + int qangle_type = ocl::Device::getDefault().isIntel() ? CV_32SC2 : CV_8UC2; + UMat qangle(imgSize, qangle_type); + + const size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins); + const Size blocks_per_img = numPartsWithin(imgSize, blockSize, blockStride); + UMat block_hists(1, static_cast(block_hist_size * blocks_per_img.area()) + 256, CV_32F); + + Size wins_per_img = numPartsWithin(imgSize, winSize, win_stride); + UMat labels(1, wins_per_img.area(), CV_8U); + + float scale = 1.f / (2.f * sigma * sigma); + Mat gaussian_lut(1, 512, CV_32FC1); + int idx = 0; + for (int i=-8; i<8; i++) + for (int j=-8; j<8; j++) + gaussian_lut.at(idx++) = std::exp(-(j * j + i * i) * scale); + for (int i=-8; i<8; i++) + for (int j=-8; j<8; j++) + gaussian_lut.at(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f; + + if (!ocl_computeGradient(_img, grad, qangle, nbins, effect_size, gammaCorrection, signedGradient)) + return false; + + UMat gauss_w_lut; + gaussian_lut.copyTo(gauss_w_lut); + if (!ocl_compute_hists(nbins, blockStride.width, blockStride.height, effect_size.height, + effect_size.width, grad, qangle, gauss_w_lut, block_hists, block_hist_size)) + return false; + + if (!ocl_normalize_hists(nbins, blockStride.width, blockStride.height, effect_size.height, + effect_size.width, block_hists, (float)L2HysThreshold)) + return false; + + Size blocks_per_win = numPartsWithin(winSize, blockSize, blockStride); + wins_per_img = numPartsWithin(effect_size, winSize, win_stride); + + int descr_size = blocks_per_win.area()*(int)block_hist_size; + int descr_width = (int)block_hist_size*blocks_per_win.width; + + UMat descriptors(wins_per_img.area(), static_cast(blocks_per_win.area() * block_hist_size), CV_32F); + switch (descr_format) + { + case DESCR_FORMAT_ROW_BY_ROW: + if (!ocl_extract_descrs_by_rows(winSize.height, winSize.width, + blockStride.height, blockStride.width, win_stride.height, win_stride.width, effect_size.height, + effect_size.width, block_hists, descriptors, (int)block_hist_size, descr_size, descr_width)) + return false; + break; + case DESCR_FORMAT_COL_BY_COL: + if (!ocl_extract_descrs_by_cols(winSize.height, winSize.width, + blockStride.height, blockStride.width, win_stride.height, win_stride.width, effect_size.height, effect_size.width, + block_hists, descriptors, (int)block_hist_size, descr_size, blocks_per_win.width, blocks_per_win.height)) + return false; + break; + default: + return false; + } + descriptors.reshape(1, (int)descriptors.total()).getMat(ACCESS_READ).copyTo(_descriptors); + return true; + } #endif //HAVE_OPENCL -void HOGDescriptor::detectMultiScale( - InputArray _img, std::vector& foundLocations, std::vector& foundWeights, - double hitThreshold, Size winStride, Size padding, - double scale0, double finalThreshold, bool useMeanshiftGrouping) const -{ - CV_INSTRUMENT_REGION(); - - double scale = 1.; - int levels = 0; - - Size imgSize = _img.size(); - std::vector levelScale; - for( levels = 0; levels < nlevels; levels++ ) - { - levelScale.push_back(scale); - if( cvRound(imgSize.width/scale) < winSize.width || - cvRound(imgSize.height/scale) < winSize.height || - scale0 <= 1 ) - break; - scale *= scale0; - } - levels = std::max(levels, 1); - levelScale.resize(levels); - - if(winStride == Size()) - winStride = blockStride; - - CV_OCL_RUN(_img.dims() <= 2 && _img.type() == CV_8UC1 && scale0 > 1 && winStride.width % blockStride.width == 0 && - winStride.height % blockStride.height == 0 && padding == Size(0,0) && _img.isUMat(), - ocl_detectMultiScale(_img, foundLocations, levelScale, hitThreshold, winStride, finalThreshold, oclSvmDetector, - blockSize, cellSize, nbins, blockStride, winSize, gammaCorrection, L2HysThreshold, (float)getWinSigma(), free_coef, signedGradient)); - - std::vector allCandidates; - std::vector tempScales; - std::vector tempWeights; - std::vector foundScales; - - Mutex mtx; - Mat img = _img.getMat(); - Range range(0, (int)levelScale.size()); - HOGInvoker invoker(this, img, hitThreshold, winStride, padding, &levelScale[0], &allCandidates, &mtx, &tempWeights, &tempScales); - parallel_for_(range, invoker); - - std::copy(tempScales.begin(), tempScales.end(), back_inserter(foundScales)); - foundLocations.clear(); - std::copy(allCandidates.begin(), allCandidates.end(), back_inserter(foundLocations)); - foundWeights.clear(); - std::copy(tempWeights.begin(), tempWeights.end(), back_inserter(foundWeights)); - - if ( useMeanshiftGrouping ) - groupRectangles_meanshift(foundLocations, foundWeights, foundScales, finalThreshold, winSize); - else - groupRectangles(foundLocations, foundWeights, (int)finalThreshold, 0.2); - clipObjects(imgSize, foundLocations, 0, &foundWeights); -} - -void HOGDescriptor::detectMultiScale(InputArray img, std::vector& foundLocations, - double hitThreshold, Size winStride, Size padding, - double scale0, double finalThreshold, bool useMeanshiftGrouping) const -{ - CV_INSTRUMENT_REGION(); - - std::vector foundWeights; - detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride, - padding, scale0, finalThreshold, useMeanshiftGrouping); -} - -template struct RTTIImpl -{ -public: - static int isInstance(const void* ptr) - { - static _ClsName dummy; - static void* dummyp = &dummy; - union - { - const void* p; - const void** pp; - } a, b; - a.p = dummyp; - b.p = ptr; - return *a.pp == *b.pp; - } - static void release(void** dbptr) - { - if(dbptr && *dbptr) - { - delete (_ClsName*)*dbptr; - *dbptr = 0; - } - } - static void* read(CvFileStorage* fs, CvFileNode* n) - { - FileNode fn(fs, n); - _ClsName* obj = new _ClsName; - if(obj->read(fn)) - return obj; - delete obj; - return 0; - } - - static void write(CvFileStorage* _fs, const char* name, const void* ptr, CvAttrList) - { - if(ptr && _fs) - { - FileStorage fs(_fs, false); - ((const _ClsName*)ptr)->write(fs, String(name)); - } - } - - static void* clone(const void* ptr) - { - if(!ptr) - return 0; - return new _ClsName(*(const _ClsName*)ptr); - } -}; - -typedef RTTIImpl HOGRTTI; - -CvType hog_type( CV_TYPE_NAME_HOG_DESCRIPTOR, HOGRTTI::isInstance, - HOGRTTI::release, HOGRTTI::read, HOGRTTI::write, HOGRTTI::clone); - -std::vector HOGDescriptor::getDefaultPeopleDetector() -{ - static const float detector[] = { - 0.05359386f, -0.14721455f, -0.05532170f, 0.05077307f, - 0.11547081f, -0.04268804f, 0.04635834f, -0.05468199f, 0.08232084f, - 0.10424068f, -0.02294518f, 0.01108519f, 0.01378693f, 0.11193510f, - 0.01268418f, 0.08528346f, -0.06309239f, 0.13054633f, 0.08100729f, - -0.05209739f, -0.04315529f, 0.09341384f, 0.11035026f, -0.07596218f, - -0.05517511f, -0.04465296f, 0.02947334f, 0.04555536f, - -3.55954492e-003f, 0.07818956f, 0.07730991f, 0.07890715f, 0.06222893f, - 0.09001380f, -0.03574381f, 0.03414327f, 0.05677258f, -0.04773581f, - 0.03746637f, -0.03521175f, 0.06955440f, -0.03849038f, 0.01052293f, - 0.01736112f, 0.10867710f, 0.08748853f, 3.29739624e-003f, 0.10907028f, - 0.07913758f, 0.10393070f, 0.02091867f, 0.11594022f, 0.13182420f, - 0.09879354f, 0.05362710f, -0.06745391f, -7.01260753e-003f, - 5.24702156e-003f, 0.03236255f, 0.01407916f, 0.02207983f, 0.02537322f, - 0.04547948f, 0.07200756f, 0.03129894f, -0.06274468f, 0.02107014f, - 0.06035208f, 0.08636236f, 4.53164103e-003f, 0.02193363f, 0.02309801f, - 0.05568166f, -0.02645093f, 0.04448695f, 0.02837519f, 0.08975694f, - 0.04461516f, 0.08975355f, 0.07514391f, 0.02306982f, 0.10410084f, - 0.06368385f, 0.05943464f, 4.58420580e-003f, 0.05220337f, 0.06675851f, - 0.08358569f, 0.06712101f, 0.06559004f, -0.03930482f, -9.15936660e-003f, - -0.05897915f, 0.02816453f, 0.05032348f, 0.06780671f, 0.03377650f, - -6.09417039e-004f, -0.01795146f, -0.03083684f, -0.01302475f, - -0.02972313f, 7.88706727e-003f, -0.03525961f, -2.50397739e-003f, - 0.05245084f, 0.11791293f, -0.02167498f, 0.05299332f, 0.06640524f, - 0.05190265f, -8.27316567e-003f, 0.03033127f, 0.05842173f, - -4.01050318e-003f, -6.25105947e-003f, 0.05862958f, -0.02465461f, - 0.05546781f, -0.08228195f, -0.07234028f, 0.04640540f, -0.01308254f, - -0.02506191f, 0.03100746f, -0.04665651f, -0.04591486f, 0.02949927f, - 0.06035462f, 0.02244646f, -0.01698639f, 0.01040041f, 0.01131170f, - 0.05419579f, -0.02130277f, -0.04321722f, -0.03665198f, 0.01126490f, - -0.02606488f, -0.02228328f, -0.02255680f, -0.03427236f, - -7.75165204e-003f, -0.06195229f, 8.21638294e-003f, 0.09535975f, - -0.03709979f, -0.06942501f, 0.14579427f, -0.05448192f, -0.02055904f, - 0.05747357f, 0.02781788f, -0.07077577f, -0.05178314f, -0.10429011f, - -0.11235505f, 0.07529039f, -0.07559302f, -0.08786739f, 0.02983843f, - 0.02667585f, 0.01382199f, -0.01797496f, -0.03141199f, -0.02098101f, - 0.09029204f, 0.04955018f, 0.13718739f, 0.11379953f, 1.80019124e-003f, - -0.04577610f, -1.11108483e-003f, -0.09470536f, -0.11596080f, - 0.04489342f, 0.01784211f, 3.06850672e-003f, 0.10781866f, - 3.36498418e-003f, -0.10842580f, -0.07436839f, -0.10535070f, - -0.01866805f, 0.16057891f, -5.07316366e-003f, -0.04295658f, - -5.90488780e-003f, 8.82003549e-003f, -0.01492646f, -0.05029279f, - -0.12875880f, 8.78831954e-004f, -0.01297184f, -0.07592774f, - -0.02668831f, -6.93787413e-004f, 0.02406698f, -0.01773298f, - -0.03855745f, -0.05877856f, 0.03259695f, 0.12826584f, 0.06292590f, - -4.10733931e-003f, 0.10996531f, 0.01332991f, 0.02088735f, 0.04037504f, - -0.05210760f, 0.07760046f, 0.06399347f, -0.05751930f, -0.10053057f, - 0.07505023f, -0.02139782f, 0.01796176f, 2.34400877e-003f, -0.04208319f, - 0.07355055f, 0.05093350f, -0.02996780f, -0.02219072f, 0.03355330f, - 0.04418742f, -0.05580705f, -0.05037573f, -0.04548179f, 0.01379514f, - 0.02150671f, -0.02194211f, -0.13682702f, 0.05464972f, 0.01608082f, - 0.05309116f, 0.04701022f, 1.33690401e-003f, 0.07575664f, 0.09625306f, - 8.92647635e-003f, -0.02819123f, 0.10866830f, -0.03439325f, - -0.07092371f, -0.06004780f, -0.02712298f, -7.07467366e-003f, - -0.01637020f, 0.01336790f, -0.10313606f, 0.04906582f, -0.05732445f, - -0.02731079f, 0.01042235f, -0.08340668f, 0.03686501f, 0.06108340f, - 0.01322748f, -0.07809529f, 0.03774724f, -0.03413248f, -0.06096525f, - -0.04212124f, -0.07982176f, -1.25973229e-003f, -0.03045501f, - -0.01236493f, -0.06312395f, 0.04789570f, -0.04602066f, 0.08576570f, - 0.02521080f, 0.02988098f, 0.10314583f, 0.07060035f, 0.04520544f, - -0.04426654f, 0.13146530f, 0.08386490f, 0.02164590f, -2.12280243e-003f, - -0.03686353f, -0.02074944f, -0.03829959f, -0.01530596f, 0.02689708f, - 0.11867401f, -0.06043470f, -0.02785023f, -0.04775074f, 0.04878745f, - 0.06350956f, 0.03494788f, 0.01467400f, 1.17890188e-003f, 0.04379614f, - 2.03681854e-003f, -0.03958609f, -0.01072688f, 6.43705716e-003f, - 0.02996500f, -0.03418507f, -0.01960307f, -0.01219154f, - -4.37000440e-003f, -0.02549453f, 0.02646318f, -0.01632513f, - 6.46516960e-003f, -0.01929734f, 4.78711911e-003f, 0.04962371f, - 0.03809111f, 0.07265724f, 0.05758125f, -0.03741554f, 0.01648608f, - -8.45285598e-003f, 0.03996826f, -0.08185477f, 0.02638875f, - -0.04026615f, -0.02744674f, -0.04071517f, 1.05096330e-003f, - -0.04741232f, -0.06733172f, 8.70434940e-003f, -0.02192543f, - 1.35350740e-003f, -0.03056974f, -0.02975521f, -0.02887780f, - -0.01210713f, -0.04828526f, -0.09066251f, -0.09969629f, -0.03665164f, - -8.88111943e-004f, -0.06826669f, -0.01866150f, -0.03627640f, - -0.01408288f, 0.01874239f, -0.02075835f, 0.09145175f, -0.03547291f, - 0.05396780f, 0.04198981f, 0.01301925f, -0.03384354f, -0.12201976f, - 0.06830920f, -0.03715654f, 9.55848210e-003f, 5.05685573e-003f, - 0.05659294f, 3.90764466e-003f, 0.02808490f, -0.05518097f, -0.03711621f, - -0.02835565f, -0.04420464f, -0.01031947f, 0.01883466f, - -8.49525444e-003f, -0.09419250f, -0.01269387f, -0.02133371f, - -0.10190815f, -0.07844430f, 2.43644323e-003f, -4.09610150e-003f, - 0.01202551f, -0.06452291f, -0.10593818f, -0.02464746f, -0.02199699f, - -0.07401930f, 0.07285886f, 8.87513801e-004f, 9.97662079e-003f, - 8.46779719e-003f, 0.03730333f, -0.02905126f, 0.03573337f, -0.04393689f, - -0.12014472f, 0.03176554f, -2.76015815e-003f, 0.10824566f, 0.05090732f, - -3.30179278e-003f, -0.05123822f, 5.04784798e-003f, -0.05664124f, - -5.99415926e-003f, -0.05341901f, -0.01221393f, 0.01291318f, - 9.91760660e-003f, -7.56987557e-003f, -0.06193124f, -2.24549137e-003f, - 0.01987562f, -0.02018840f, -0.06975540f, -0.06601523f, -0.03349112f, - -0.08910118f, -0.03371435f, -0.07406893f, -0.02248047f, -0.06159951f, - 2.77751544e-003f, -0.05723337f, -0.04792468f, 0.07518548f, - 2.77279224e-003f, 0.04211938f, 0.03100502f, 0.05278448f, 0.03954679f, - -0.03006846f, -0.03851741f, -0.02792403f, -0.02875333f, 0.01531280f, - 0.02186953f, -0.01989829f, 2.50679464e-003f, -0.10258728f, - -0.04785743f, -0.02887216f, 3.85063468e-003f, 0.01112236f, - 8.29218887e-003f, -0.04822981f, -0.04503597f, -0.03713100f, - -0.06988008f, -0.11002295f, -2.69209221e-003f, 1.85383670e-003f, - -0.05921049f, -0.06105053f, -0.08458050f, -0.04527602f, - 8.90329306e-004f, -0.05875023f, -2.68602883e-003f, -0.01591195f, - 0.03631859f, 0.05493166f, 0.07300330f, 5.53333294e-003f, 0.06400407f, - 0.01847740f, -5.76280477e-003f, -0.03210877f, 4.25160583e-003f, - 0.01166520f, -1.44864211e-003f, 0.02253744f, -0.03367080f, 0.06983195f, - -4.22323542e-003f, -8.89401045e-003f, -0.07943393f, 0.05199728f, - 0.06065201f, 0.04133492f, 1.44032843e-003f, -0.09585235f, -0.03964731f, - 0.04232114f, 0.01750465f, -0.04487902f, -7.59733608e-003f, 0.02011171f, - 0.04673622f, 0.09011173f, -0.07869188f, -0.04682482f, -0.05080139f, - -3.99383716e-003f, -0.05346331f, 0.01085723f, -0.03599333f, - -0.07097908f, 0.03551549f, 0.02680387f, 0.03471529f, 0.01790393f, - 0.05471273f, 9.62048303e-003f, -0.03180215f, 0.05864431f, 0.02330614f, - 0.01633144f, -0.05616681f, -0.10245429f, -0.08302189f, 0.07291322f, - -0.01972590f, -0.02619633f, -0.02485327f, -0.04627592f, - 1.48853404e-003f, 0.05514185f, -0.01270860f, -0.01948900f, 0.06373586f, - 0.05002292f, -0.03009798f, 8.76216311e-003f, -0.02474238f, - -0.05504891f, 1.74034527e-003f, -0.03333667f, 0.01524987f, 0.11663762f, - -1.32344989e-003f, -0.06608453f, 0.05687166f, -6.89525274e-004f, - -0.04402352f, 0.09450210f, -0.04222684f, -0.05360983f, 0.01779531f, - 0.02561388f, -0.11075410f, -8.77790991e-003f, -0.01099504f, - -0.10380266f, 0.03103457f, -0.02105741f, -0.07371717f, 0.05146710f, - 0.10581432f, -0.08617968f, -0.02892107f, 0.01092199f, 0.14551543f, - -2.24320893e-003f, -0.05818033f, -0.07390742f, 0.05701261f, - 0.12937020f, -0.04986651f, 0.10182415f, 0.05028650f, 0.12515625f, - 0.09175041f, 0.06404983f, 0.01523394f, 0.09460562f, 0.06106631f, - -0.14266998f, -0.02926703f, 0.02762171f, 0.02164151f, - -9.58488265e-004f, -0.04231362f, -0.09866509f, 0.04322244f, - 0.05872034f, -0.04838847f, 0.06319253f, 0.02443798f, -0.03606876f, - 9.38737206e-003f, 0.04289991f, -0.01027411f, 0.08156885f, 0.08751175f, - -0.13191354f, 8.16054735e-003f, -0.01452161f, 0.02952677f, 0.03615945f, - -2.09128903e-003f, 0.02246693f, 0.09623287f, 0.09412123f, -0.02924758f, - -0.07815186f, -0.02203079f, -2.02566991e-003f, 0.01094733f, - -0.01442332f, 0.02838561f, 0.11882371f, 7.28798332e-003f, -0.10345965f, - 0.07561217f, -0.02049661f, 4.44177445e-003f, 0.01609347f, -0.04893158f, - -0.08758243f, -7.67420698e-003f, 0.08862378f, 0.06098121f, 0.06565887f, - 7.32981879e-003f, 0.03558407f, -0.03874352f, -0.02490055f, - -0.06771075f, 0.09939223f, -0.01066077f, 0.01382995f, -0.07289080f, - 7.47184316e-003f, 0.10621431f, -0.02878659f, 0.02383525f, -0.03274646f, - 0.02137008f, 0.03837290f, 0.02450992f, -0.04296818f, -0.02895143f, - 0.05327370f, 0.01499020f, 0.04998732f, 0.12938657f, 0.09391870f, - 0.04292390f, -0.03359194f, -0.06809492f, 0.01125796f, 0.17290455f, - -0.03430733f, -0.06255233f, -0.01813114f, 0.11726857f, -0.06127599f, - -0.08677909f, -0.03429872f, 0.04684938f, 0.08161420f, 0.03538774f, - 0.01833884f, 0.11321855f, 0.03261845f, -0.04826299f, 0.01752407f, - -0.01796414f, -0.10464549f, -3.30041884e-003f, 2.29343961e-004f, - 0.01457292f, -0.02132982f, -0.02602923f, -9.87351313e-003f, - 0.04273872f, -0.02103316f, -0.07994065f, 0.02614958f, -0.02111666f, - -0.06964913f, -0.13453490f, -0.06861878f, -6.09341264e-003f, - 0.08251446f, 0.15612499f, 2.46531400e-003f, 8.88424646e-003f, - -0.04152999f, 0.02054853f, 0.05277953f, -0.03087788f, 0.02817579f, - 0.13939077f, 0.07641046f, -0.03627627f, -0.03015098f, -0.04041540f, - -0.01360690f, -0.06227205f, -0.02738223f, 0.13577610f, 0.15235767f, - -0.05392922f, -0.11175954f, 0.02157129f, 0.01146481f, -0.05264937f, - -0.06595174f, -0.02749175f, 0.11812254f, 0.17404149f, -0.06137035f, - -0.11003478f, -0.01351621f, -0.01745916f, -0.08577441f, -0.04469909f, - -0.06106115f, 0.10559758f, 0.20806813f, -0.09174948f, 7.09621934e-004f, - 0.03579374f, 0.07215115f, 0.02221742f, 0.01827742f, -7.90785067e-003f, - 0.01489554f, 0.14519960f, -0.06425831f, 0.02990399f, -1.80181325e-003f, - -0.01401528f, -0.04171134f, -3.70530109e-003f, -0.09090481f, - 0.09520713f, 0.08845516f, -0.02651753f, -0.03016730f, 0.02562448f, - 0.03563816f, -0.03817881f, 0.01433385f, 0.02256983f, 0.02872120f, - 0.01001934f, -0.06332260f, 0.04338406f, 0.07001807f, -0.04705722f, - -0.07318907f, 0.02630457f, 0.03106382f, 0.06648342f, 0.10913180f, - -0.01630815f, 0.02910308f, 0.02895109f, 0.08040254f, 0.06969310f, - 0.06797734f, 6.08639978e-003f, 4.16588830e-003f, 0.08926726f, - -0.03123648f, 0.02700146f, 0.01168734f, -0.01631594f, 4.61015804e-003f, - 8.51359498e-003f, -0.03544224f, 0.03571994f, 4.29766066e-003f, - -0.01970077f, -8.79793242e-003f, 0.09607988f, 0.01544222f, - -0.03923707f, 0.07308586f, 0.06061262f, 1.31683104e-004f, - -7.98222050e-003f, 0.02399261f, -0.06084389f, -0.02743429f, - -0.05475523f, -0.04131311f, 0.03559756f, 0.03055342f, 0.02981433f, - 0.14860515f, 0.01766787f, 0.02945257f, 0.04898238f, 0.01026922f, - 0.02811658f, 0.08267091f, 0.02732154f, -0.01237693f, 0.11760156f, - 0.03802063f, -0.03309754f, 5.24957618e-003f, -0.02460510f, 0.02691451f, - 0.05399988f, -0.10133506f, 0.06385437f, -0.01818005f, 0.02259503f, - 0.03573135f, 0.01042848f, -0.04153402f, -0.04043029f, 0.01643575f, - 0.08326677f, 4.61383024e-004f, -0.05308095f, -0.08536223f, - -1.61011645e-003f, -0.02163720f, -0.01783352f, 0.03859637f, - 0.08498885f, -0.01725216f, 0.08625131f, 0.10995087f, 0.09177644f, - 0.08498347f, 0.07646490f, 0.05580502f, 0.02693516f, 0.09996913f, - 0.09070327f, 0.06667200f, 0.05873008f, -0.02247842f, 0.07772321f, - 0.12408436f, 0.12629253f, -8.41997913e-004f, 0.01477783f, 0.09165990f, - -2.98401713e-003f, -0.06466447f, -0.07057302f, 2.09516948e-004f, - 0.02210209f, -0.02158809f, -0.08602506f, -0.02284836f, - 4.01876355e-003f, 9.56660323e-003f, -0.02073978f, -0.04635138f, - -7.59423291e-003f, -0.01377393f, -0.04559359f, -0.13284740f, - -0.08671406f, -0.03654395f, 0.01142869f, 0.03287891f, -0.04392983f, - 0.06142959f, 0.17710890f, 0.10385257f, 0.01329137f, 0.10067633f, - 0.12450829f, -0.04476709f, 0.09049144f, 0.04589312f, 0.11167907f, - 0.08587538f, 0.04767583f, 1.67188141e-003f, 0.02359802f, -0.03808852f, - 0.03126272f, -0.01919029f, -0.05698918f, -0.02365112f, -0.06519032f, - -0.05599358f, -0.07097308f, -0.03301812f, -0.04719102f, -0.02566297f, - 0.01324074f, -0.09230672f, -0.05518232f, -0.04712864f, -0.03380903f, - -0.06719479f, 0.01183908f, -0.09326738f, 0.01642865f, 0.03789867f, - -6.61567831e-003f, 0.07796386f, 0.07246574f, 0.04706347f, -0.02523437f, - -0.01696830f, -0.08068866f, 0.06030888f, 0.10527060f, -0.06611756f, - 0.02977346f, 0.02621830f, 0.01913855f, -0.08479366f, -0.06322418f, - -0.13570616f, -0.07644490f, 9.31900274e-003f, -0.08095149f, - -0.10197903f, -0.05204025f, 0.01413151f, -0.07800411f, -0.01885122f, - -0.07509381f, -0.10136326f, -0.05212355f, -0.09944065f, - -1.33606605e-003f, -0.06342617f, -0.04178550f, -0.12373723f, - -0.02832736f, -0.06057501f, 0.05830070f, 0.07604282f, -0.06462587f, - 8.02447461e-003f, 0.11580125f, 0.12332212f, 0.01978462f, - -2.72378162e-003f, 0.05850752f, -0.04674481f, 0.05148062f, - -2.62542837e-003f, 0.11253355f, 0.09893716f, 0.09785093f, -0.04659257f, - -0.01102429f, -0.07002308f, 0.03088913f, -0.02565549f, -0.07671449f, - 3.17443861e-003f, -0.10783514f, -0.02314270f, -0.11089555f, - -0.01024768f, 0.03116021f, -0.04964825f, 0.02281825f, 5.50005678e-003f, - -0.08427856f, -0.14685495f, -0.07719755f, -0.13342668f, -0.04525511f, - -0.09914210f, 0.02588859f, 0.03469279f, 0.04664020f, 0.11688190f, - 0.09647275f, 0.10857815f, -0.01448726f, 0.04299758f, -0.06763151f, - 1.33257592e-003f, 0.14331576f, 0.07574340f, 0.09166205f, 0.05674926f, - 0.11325553f, -0.01106494f, 0.02062161f, -0.11484840f, -0.07492137f, - -0.02864293f, -0.01275638f, -0.06946032f, -0.10101652f, -0.04113498f, - -0.02214783f, -0.01273942f, -0.07480393f, -0.10556041f, -0.07622112f, - -0.09988393f, -0.11453961f, -0.12073903f, -0.09412795f, -0.07146588f, - -0.04054537f, -0.06127083f, 0.04221122f, 0.07688113f, 0.04099256f, - 0.12663734f, 0.14683802f, 0.21761774f, 0.12525328f, 0.18431792f, - -1.66402373e-003f, 2.37777247e-003f, 0.01445475f, 0.03509416f, - 0.02654697f, 0.01716739f, 0.05374011f, 0.02944174f, 0.11323927f, - -0.01485456f, -0.01611330f, -1.85554172e-003f, -0.01708549f, - -0.05435753f, -0.05302101f, 0.05260378f, -0.03582945f, - -3.42867890e-004f, 1.36076682e-003f, -0.04436073f, -0.04228432f, - 0.03281291f, -0.05480836f, -0.10197772f, -0.07206279f, -0.10741059f, - -0.02366946f, 0.10278475f, -2.74783419e-003f, -0.03242477f, - 0.02308955f, 0.02835869f, 0.10348799f, 0.19580358f, 0.10252027f, - 0.08039929f, 0.05525554f, -0.13250865f, -0.14395352f, 3.13586881e-003f, - -0.03387071f, 8.94669443e-003f, 0.05406157f, -4.97324532e-003f, - -0.01189114f, 2.82919413e-004f, -0.03901557f, -0.04898705f, - 0.02164520f, -0.01382906f, -0.01850416f, 0.01869347f, -0.02450060f, - 0.02291678f, 0.08196463f, 0.03309153f, -0.10629974f, 0.02473924f, - 0.05344394f, -0.02404823f, -0.03243643f, -5.55244600e-003f, - -0.08009996f, 0.02811539f, 0.04235742f, 0.01859004f, 0.04902123f, - -0.01438252f, -0.01526853f, 0.02044195f, -0.05008660f, 0.04244113f, - 0.07611816f, 0.04950470f, -0.06020549f, -4.26026015e-003f, 0.13133512f, - -0.01438738f, -0.01958807f, -0.04044152f, -0.12425045f, - 2.84353318e-003f, -0.05042776f, -0.09121484f, 7.34345755e-003f, - 0.09388847f, 0.11800314f, 4.72295098e-003f, 4.44378285e-003f, - -0.07984917f, -0.03613737f, 0.04490915f, -0.02246483f, 0.04681071f, - 0.05240871f, 0.02157206f, -0.04603431f, -0.01197929f, -0.02748779f, - 0.13621049f, 0.08812155f, -0.07802048f, 4.86458559e-003f, -0.01598836f, - 0.01024450f, -0.03463517f, -0.02304239f, -0.08692665f, 0.06655128f, - 0.05785803f, -0.12640759f, 0.02307472f, 0.07337402f, 0.07525434f, - 0.04943763f, -0.02241034f, -0.09978238f, 0.14487994f, -0.06570521f, - -0.07855482f, 0.02830222f, -5.29603509e-004f, -0.04669895f, - -0.11822784f, -0.12246452f, -0.15365660f, -0.02969127f, 0.08078201f, - 0.13512598f, 0.11505685f, 0.04740673f, 0.01376022f, -0.05852978f, - -0.01537809f, -0.05541119f, 0.02491065f, -0.02870786f, 0.02760978f, - 0.23836176f, 0.22347429f, 0.10306466f, -0.06919070f, -0.10132039f, - -0.20198342f, -0.05040560f, 0.27163076f, 0.36987007f, 0.34540465f, - 0.29095781f, 0.05649706f, 0.04125737f, 0.07505883f, -0.02737836f, - -8.43431335e-003f, 0.07368195f, 0.01653876f, -0.09402955f, - -0.09574359f, 0.01474337f, -0.07128561f, -0.03460737f, 0.11438941f, - 0.13752601f, -0.06385452f, -0.06310338f, 8.19548313e-003f, 0.11622470f, - 5.05133113e-003f, -0.07602754f, 0.06695660f, 0.25723928f, 0.09037900f, - 0.28826267f, 0.13165380f, -0.05312614f, -0.02137198f, -0.03442232f, - -0.06255679f, 0.03899667f, 0.18391028f, 0.26016650f, 0.03374462f, - 0.01860465f, 0.19077586f, 0.18160543f, 3.43634398e-003f, -0.03036782f, - 0.19683038f, 0.35378191f, 0.24968483f, -0.03222649f, 0.28972381f, - 0.43091634f, 0.30778357f, 0.02335266f, -0.09877399f, -6.85245218e-003f, - 0.08945240f, -0.08150686f, 0.02792493f, 0.24806842f, 0.17338486f, - 0.06231801f, -0.10432383f, -0.16653322f, -0.13197899f, -0.08531576f, - -0.19271527f, -0.13536365f, 0.22240199f, 0.39219588f, 0.26597717f, - -0.01231649f, 0.01016179f, 0.13379875f, 0.12018334f, -0.04852953f, - -0.07915270f, 0.07036012f, 3.87723115e-003f, -0.06126805f, - -0.15015170f, -0.11406515f, -0.08556531f, -0.07429333f, -0.16115491f, - 0.13214062f, 0.25691369f, 0.05697750f, 0.06861912f, -6.02903729e-003f, - -7.94562511e-003f, 0.04799571f, 0.06695165f, -0.01926842f, 0.06206308f, - 0.13450983f, -0.06381495f, -2.98370165e-003f, -0.03482971f, - 7.53991678e-003f, 0.03895611f, 0.11464261f, 0.01669971f, - 8.27818643e-003f, -7.49160210e-003f, -0.11712562f, -0.10650621f, - -0.10353880f, -0.04994106f, -7.65618810e-004f, 0.03023767f, - -0.04759270f, -0.07302686f, -0.05825012f, -0.13156348f, -0.10639747f, - -0.19393684f, -0.09973683f, -0.07918908f, 4.63177625e-004f, - -6.61382044e-004f, 0.15853868f, 0.08561199f, -0.07660093f, - -0.08015265f, -0.06164073f, 0.01882577f, -7.29908410e-004f, - 0.06840892f, 0.03843764f, 0.20274927f, 0.22028814f, -5.26101235e-003f, - 0.01452435f, -0.06331623f, 0.02865064f, 0.05673740f, 0.12171564f, - 0.03837196f, 0.03555467f, -0.02662914f, -0.10280123f, -0.06526285f, - -0.11066351f, -0.08988424f, -0.10103678f, 8.10526591e-003f, - 5.95238712e-003f, 0.02617721f, -0.01705742f, -0.10897956f, - -0.08004991f, -0.11271993f, -0.06185647f, -0.06103712f, 0.01597041f, - -0.05923606f, 0.09410726f, 0.22858568f, 0.03263380f, 0.06772990f, - -0.09003516f, 0.01017870f, 0.01931688f, 0.08628357f, -0.01430009f, - 0.10954945f, 0.16612452f, -0.02434544f, -0.03310068f, -0.04236627f, - 0.01212392f, -6.15046406e-003f, 0.06954194f, 0.03015283f, 0.01787957f, - 0.02781667f, -0.05561153f, -8.96244217e-003f, -0.04971489f, - 0.07510284f, 0.01775282f, 0.05889897f, -0.07981427f, 0.03647643f, - -3.73833324e-003f, -0.08894575f, -0.06429435f, -0.08068276f, - 0.03567704f, -0.07131936f, -7.21910037e-003f, -0.09566668f, - 0.17886090f, 0.14911725f, 0.02070032f, -0.05017120f, -0.04992622f, - 0.01570143f, -0.09906903f, 0.06456193f, 0.15329507f, 0.18820767f, - 0.11689861f, -0.01178513f, -0.02225163f, -0.01905318f, 0.10271224f, - -7.27029052e-003f, 0.11664233f, 0.14796902f, 0.07771893f, 0.02400013f, - -0.05361797f, -0.01972888f, 0.01376177f, 0.06740040f, -0.06525395f, - 0.05726178f, -0.02404981f, -0.14018567f, -0.02074987f, -0.04621970f, - -0.04688627f, -0.01842059f, 0.07722727f, -0.04852883f, 0.01529004f, - -0.19639495f, 0.10817073f, 0.03795860f, -0.09435206f, -0.07984378f, - -0.03383440f, 0.11081333f, 0.02237366f, 0.12703256f, 0.21613893f, - 0.02918790f, 4.66472283e-003f, -0.10274266f, -0.04854131f, - -3.46305710e-003f, 0.08652268f, 0.02251546f, 0.09636052f, 0.17180754f, - -0.09272388f, 4.59174305e-004f, -0.11723048f, -0.12210111f, - -0.15547538f, 0.07218186f, -0.05297846f, 0.03779940f, 0.05150875f, - -0.03802310f, 0.03870645f, -0.15250699f, -0.08696499f, -0.02021560f, - 0.04118926f, -0.15177974f, 0.01577647f, 0.10249301f, 7.50041893e-003f, - 0.01721806f, -0.06828983f, -0.02397596f, -0.06598977f, -0.04317593f, - -0.08064980f, 6.66632550e-003f, 0.03333484f, 0.07093620f, 0.08231064f, - -0.06577903f, -0.06698844f, -0.06984019f, -0.06508023f, -0.14145090f, - -0.02393239f, 0.06485303f, 8.83263443e-003f, 0.09251080f, -0.07557579f, - -0.05067699f, -0.09798748f, -0.06703258f, -0.14056294f, 0.03245994f, - 0.12554143f, 0.01761621f, 0.12980327f, -0.04081950f, -0.11906909f, - -0.14813015f, -0.08376863f, -0.12200681f, 0.04988137f, 0.05424247f, - -3.90952639e-003f, 0.03255733f, -0.12717837f, -0.07461493f, - -0.05703964f, -0.01736189f, -0.08026433f, -0.05433894f, -0.01719359f, - 0.02886275f, 0.01772653f, -0.09163518f, 3.57789593e-003f, -0.10129993f, - -0.02653764f, -0.08131415f, -0.03847986f, -7.62157550e-004f, - 0.06486648f, 0.19675669f, -0.04919156f, -0.07059129f, -0.04857785f, - -0.01042383f, -0.08328653f, 0.03660302f, -0.03696846f, 0.04969259f, - 0.08241162f, -0.12514858f, -0.06122676f, -0.03750202f, - 6.52989605e-003f, -0.10247213f, 0.02568346f, 4.51781414e-003f, - -0.03734229f, -0.01131264f, -0.05412074f, 8.89345480e-004f, - -0.12388977f, -0.05959237f, -0.12418608f, -0.06151643f, -0.07310260f, - 0.02441575f, 0.07023528f, -0.07548289f, -7.57147965e-004f, - -0.09061348f, -0.08112976f, -0.06920306f, 9.54394229e-003f, - -0.01219902f, 1.21273217e-003f, -8.88989680e-003f, -0.08309301f, - -0.04552661f, -0.10739882f, -0.05691034f, -0.13928030f, 0.09027749f, - 0.15123098f, 0.03175976f, 0.17763577f, 3.29913251e-004f, 0.05151888f, - -0.09844074f, -0.09475287f, -0.08571247f, 0.16241577f, 0.19336018f, - 8.57454538e-003f, 0.11474732f, -0.01493934f, 0.03352379f, -0.08966240f, - -0.02322310f, 0.02663568f, 0.05448750f, -0.03536883f, -0.07210463f, - -0.06807277f, -0.03121621f, -0.05932408f, -0.17282860f, -0.15873498f, - -0.04956378f, 0.01603377f, -0.12385946f, 0.13878587f, 0.21468069f, - 0.13510075f, 0.20992437f, 0.08845878f, 0.08104013f, 0.03754176f, - 0.12173114f, 0.11103114f, 0.10643122f, 0.13941477f, 0.11640384f, - 0.14786847f, 0.01218238f, 0.01160753f, 0.03547940f, 0.08794311f, - -0.01695384f, -0.07692261f, -0.08236158f, 6.79194089e-003f, - -0.02458403f, 0.13022894f, 0.10953187f, 0.09857773f, 0.04735930f, - -0.04353498f, -0.15173385f, -0.17904443f, -0.10450364f, -0.13418166f, - -0.06633098f, -0.03170381f, -0.06839000f, -0.11350126f, -0.06983913f, - 0.19083543f, 0.17604128f, 0.07730632f, 0.10022651f, 0.36428109f, - 0.28291923f, 0.12688625f, 0.15942036f, 0.14064661f, -0.11201853f, - -0.13969108f, -0.09088077f, -0.14107047f, 0.05117374f, - -2.63348082e-003f, -0.10794610f, -0.09715455f, -0.05284977f, - 0.01565668f, 0.05031200f, 0.07021113f, -0.02963028f, 0.01766960f, - 0.08333644f, -0.03211382f, 4.90096770e-003f, 0.05186674f, -0.05045737f, - -0.09624767f, -0.02525997f, 0.06916669f, 0.01213916f, 0.05333899f, - -0.03443280f, -0.10055527f, -0.06291115f, 5.42851724e-003f, - -6.30360236e-003f, 0.02270257f, -0.01769792f, 0.03273688f, 0.07746078f, - 7.77099328e-003f, 0.05041346f, 0.01648103f, -0.02321534f, -0.09930186f, - -0.02293853f, 0.02034990f, -0.08324204f, 0.08510064f, -0.03732836f, - -0.06465405f, -0.06086946f, 0.13680504f, -0.11469388f, -0.03896406f, - -0.07142810f, 2.67581246e-003f, -0.03639632f, -0.09849060f, - -0.11014334f, 0.17489147f, 0.17610909f, -0.16091567f, -0.07248894f, - 0.01567141f, 0.23742996f, 0.07552249f, -0.06270349f, -0.07303379f, - 0.25442186f, 0.16903116f, -0.08168741f, -0.05913896f, -0.03954096f, - 6.81776879e-003f, -0.05615319f, -0.07303037f, -0.12176382f, - 0.12385108f, 0.22084464f, -0.05543206f, -0.03310431f, 0.05731593f, - 0.19481890f, 0.04016430f, -0.06480758f, -0.12353460f, 0.18733442f, - -0.09631214f, -0.11192076f, 0.12404587f, 0.15671748f, 0.19256128f, - 0.10895617f, 0.03391477f, -0.13032004f, -0.05626907f, -0.09025607f, - 0.23485197f, 0.27812332f, 0.26725492f, 0.07255980f, 0.16565137f, - 0.22388470f, 0.07441066f, -0.21003133f, -0.08075339f, -0.15031935f, - 0.07023834f, 0.10872041f, 0.18156518f, 0.20037253f, 0.13571967f, - -0.11915682f, -0.11131983f, -0.18878011f, 0.06074620f, 0.20578890f, - 0.12413109f, 0.03930207f, 0.29176015f, 0.29502738f, 0.27856228f, - -0.01803601f, 0.16646385f, 0.19268319f, 0.01900682f, 0.06026287f, - 2.35868432e-003f, 0.01558199f, 0.02707230f, 0.11383014f, 0.12103992f, - 0.03907350f, 0.04637353f, 0.09020995f, 0.11919726f, -3.63007211e-003f, - 0.02220155f, 0.10336831f, 0.17351882f, 0.12259731f, 0.18983354f, - 0.15736865f, 0.01160725f, -0.01690723f, -9.69582412e-004f, 0.07213813f, - 0.01161613f, 0.17864859f, 0.24486147f, 0.18208991f, 0.20177495f, - 0.05972528f, -8.93934630e-003f, -0.02316955f, 0.14436610f, 0.14114498f, - 0.05520950f, 0.06353590f, -0.19124921f, 0.10174713f, 0.29414919f, - 0.26448128f, 0.09344960f, 0.15284036f, 0.19797507f, 0.11369792f, - -0.12722753f, -0.21396367f, -0.02008235f, -0.06566695f, -0.01662150f, - -0.03937003f, 0.04778343f, 0.05017274f, -0.02299062f, -0.20208496f, - -0.06395898f, 0.13721776f, 0.22544557f, 0.14888357f, 0.08687132f, - 0.27088094f, 0.32206613f, 0.09782200f, -0.18523243f, -0.17232181f, - -0.01041531f, 0.04008654f, 0.04199702f, -0.08081299f, -0.03755421f, - -0.04809646f, -0.05222081f, -0.21709201f, -0.06622940f, 0.02945281f, - -0.04600435f, -0.05256077f, -0.08432942f, 0.02848100f, 0.03490564f, - 8.28621630e-003f, -0.11051246f, -0.11210597f, -0.01998289f, - -0.05369405f, -0.08869293f, -0.18799506f, -0.05436598f, -0.05011634f, - -0.05419716f, -0.06151857f, -0.10827805f, 0.04346735f, 0.04016083f, - 0.01520820f, -0.12173316f, -0.04880285f, -0.01101406f, 0.03250847f, - -0.06009551f, -0.03082932f, -0.02295134f, -0.06856834f, -0.08775249f, - -0.23793389f, -0.09174541f, -0.05538322f, -0.04321031f, -0.11874759f, - -0.04221844f, -0.06070468f, 0.01194489f, 0.02608565f, -0.03892140f, - -0.01643151f, -0.02602034f, -0.01305472f, 0.03920100f, -0.06514261f, - 0.01126918f, -6.27710763e-003f, -0.02720047f, -0.11133634f, - 0.03300330f, 0.02398472f, 0.04079665f, -0.10564448f, 0.05966159f, - 0.01195221f, -0.03179441f, -0.01692590f, -0.06177841f, 0.01841576f, - -5.51078189e-003f, -0.06821765f, -0.03191888f, -0.09545476f, - 0.03030550f, -0.04896152f, -0.02914624f, -0.13283344f, -0.04783419f, - 6.07836898e-003f, -0.01449538f, -0.13358212f, -0.09687774f, - -0.02813793f, 0.01213498f, 0.06650011f, -0.02039067f, 0.13356198f, - 0.05986415f, -9.12760664e-003f, -0.18780160f, -0.11992817f, - -0.06342237f, 0.01229534f, 0.07143231f, 0.10713009f, 0.11085765f, - 0.06569190f, -0.02956399f, -0.16288325f, -0.13993549f, -0.01292515f, - 0.03833013f, 0.09130384f, -0.05086257f, 0.05617329f, -0.03896667f, - -0.06282311f, -0.11490010f, -0.14264110f, -0.04530499f, 0.01598189f, - 0.09167797f, 0.08663294f, 0.04885277f, -0.05741219f, -0.07565769f, - -0.17136464f, -0.02619422f, -0.02477579f, 0.02679587f, 0.11621952f, - 0.08788391f, 0.15520640f, 0.04709549f, 0.04504483f, -0.10214074f, - -0.12293372f, -0.04820546f, -0.05484834f, 0.05473754f, 0.07346445f, - 0.05577277f, -0.08209965f, 0.03462975f, -0.20962234f, -0.09324598f, - 3.79481679e-003f, 0.03617633f, 0.16742408f, 0.07058107f, 0.10204960f, - -0.06795346f, 3.22807301e-003f, -0.12589309f, -0.17496960f, - 0.02078314f, -0.07694324f, 0.12184640f, 0.08997164f, 0.04793497f, - -0.11383379f, -0.08046359f, -0.25716835f, -0.08080962f, - 6.80711539e-003f, -0.02930280f, -3.04938294e-003f, -0.11106286f, - -0.04628860f, -0.07821649f, 7.70127494e-003f, -0.10247706f, - 1.21042714e-003f, 0.20573859f, -0.03241005f, 8.42972286e-003f, - 0.01946464f, -0.01197973f, -0.14579976f, 0.04233614f, - -4.14096704e-003f, -0.06866436f, -0.02431862f, -0.13529138f, - 1.25891645e-003f, -0.11425111f, -0.04303651f, -0.01694815f, - 0.05720210f, -0.16040207f, 0.02772896f, 0.05498345f, -0.15010567f, - 0.01450866f, 0.02350303f, -0.04301004f, -0.04951802f, 0.21702233f, - -0.03159155f, -0.01963303f, 0.18232647f, -0.03263875f, - -2.88476888e-003f, 0.01587562f, -1.94303901e-003f, -0.07789494f, - 0.04674156f, -6.25576358e-003f, 0.08925962f, 0.21353747f, 0.01254677f, - -0.06999976f, -0.05931328f, -0.01884327f, -0.04306272f, 0.11794136f, - 0.03842728f, -0.03907030f, 0.05636114f, -0.09766009f, -0.02104000f, - 8.72711372e-003f, -0.02736877f, -0.05112274f, 0.16996814f, 0.02955785f, - 0.02094014f, 0.08414304f, -0.03335762f, -0.03617457f, -0.05808248f, - -0.08872101f, 0.02927705f, 0.27077839f, 0.06075108f, 0.07478261f, - 0.15282831f, -0.03908454f, -0.05101782f, -9.51998029e-003f, - -0.03272416f, -0.08735625f, 0.07633440f, -0.07185312f, 0.13841286f, - 0.07812646f, -0.12901451f, -0.05488589f, -0.05644578f, -0.03290703f, - -0.11184757f, 0.03751570f, -0.05978153f, -0.09155276f, 0.05657315f, - -0.04328186f, -0.03047933f, -0.01413135f, -0.10181040f, -0.01384013f, - 0.20132534f, -0.01536873f, -0.07641169f, 0.05906778f, -0.07833145f, - -0.01523801f, -0.07502609f, -0.09461885f, -0.15013233f, 0.16050665f, - 0.09021381f, 0.08473236f, 0.03386267f, -0.09147339f, -0.09170618f, - -0.08498498f, -0.05119187f, -0.10431040f, 0.01041618f, -0.03064913f, - 0.09340212f, 0.06448522f, -0.03881054f, -0.04985436f, -0.14794017f, - -0.05200112f, -0.02144495f, 0.04000821f, 0.12420804f, -0.01851651f, - -0.04116732f, -0.11951703f, -0.04879033f, -0.08722515f, -0.08454733f, - -0.10549165f, 0.11251976f, 0.10766345f, 0.19201984f, 0.06128913f, - -0.02734615f, -0.08834923f, -0.16999826f, -0.03548348f, - -5.36092324e-003f, 0.08297954f, 0.07226378f, 0.04194529f, 0.04668673f, - 8.73902347e-003f, 0.06980139f, 0.05652480f, 0.05879445f, 0.02477076f, - 0.02451423f, 0.12433673f, 0.05600227f, 0.06886370f, 0.03863076f, - 0.07459056f, 0.02264139f, 0.01495469f, 0.06344220f, 0.06945208f, - 0.02931899f, 0.11719371f, 0.04527427f, 0.03248192f, 2.08271481e-003f, - 0.02044626f, 0.11403449f, 0.04303892f, 0.06444661f, 0.04959024f, - 0.08174094f, 0.09240247f, 0.04894639f, 0.02252937f, -0.01652530f, - 0.07587013f, 0.06064249f, 0.13954395f, 0.02772832f, 0.07093039f, - 0.08501238f, 0.01701301f, 0.09055722f, 0.33421436f, 0.20163782f, - 0.09821030f, 0.07951369f, 0.08695120f, -0.12757730f, -0.13865978f, - -0.06610068f, -0.10985506f, 0.03406816f, -0.01116336f, -0.07281768f, - -0.13525715f, -0.12844718f, 0.08956250f, 0.09171610f, 0.10092317f, - 0.23385370f, 0.34489515f, 0.09901748f, 0.02002922f, 0.12335990f, - 0.07606190f, -0.14899330f, -0.15634622f, -0.06494618f, -0.01760547f, - 0.03404277f, -0.13208845f, -0.12101169f, -0.18294574f, -0.16560709f, - 0.02183887f, -0.02752613f, 0.01813638f, 0.02000757f, 0.01319924f, - 0.08030242f, 0.01220535f, 2.98233377e-003f, -0.01307070f, 0.05970297f, - -0.05345284f, -0.03381982f, -9.87543724e-003f, -0.06869387f, - 0.03956730f, -0.03108176f, -0.05732809f, 0.02172386f, 0.04159765f, - 2.62783933e-003f, 0.04813229f, 0.09358983f, -8.18389002e-003f, - 0.01724574f, -0.02547474f, -0.04967288f, -0.02390376f, 0.06640504f, - -0.06306566f, 0.01137518f, 0.05589378f, -0.08237787f, 0.02455001f, - -0.03059422f, -0.08953978f, 0.06851497f, 0.07190268f, -0.07610799f, - 7.87237938e-003f, -7.85830803e-003f, 0.06006952f, -0.01126728f, - -2.85743061e-003f, -0.04772895f, 0.01884944f, 0.15005857f, - -0.06268821f, -0.01989072f, 0.01138399f, 0.08760451f, 0.03879007f, - -9.66926850e-003f, -0.08012961f, 0.06414555f, -0.01362950f, - -0.09135523f, 0.01755159f, 0.04459474f, 0.09650917f, 0.05219948f, - -2.19440833e-003f, -0.07037939f, -0.01599054f, 0.13103317f, - -0.02492603f, -0.01032540f, -0.02903307f, 0.04489160f, 0.05148086f, - 0.01858173f, -0.02919228f, 0.08299296f, -0.04590359f, -0.15745632f, - -0.09068198f, -0.02972453f, 0.12985018f, 0.22320485f, 0.24261914f, - 0.03642650f, -0.05506422f, 2.67413049e-003f, -0.03834032f, 0.06449424f, - 0.03834866f, 0.03816991f, 0.25039271f, 0.34212017f, 0.32433882f, - 0.18824573f, -0.08599839f, -0.17599408f, -0.15317015f, -0.09913155f, - -0.02856072f, -0.05304699f, -1.06437842e-003f, -0.06641813f, - -0.07509298f, 0.01463361f, -0.07551918f, -0.04510373f, - -8.44620075e-003f, 0.01772176f, 0.04068235f, 0.20295307f, 0.15719447f, - 0.05712103f, 0.26296997f, 0.14657754f, 0.01547317f, -0.05052776f, - -0.03881342f, -0.01437883f, -0.04930177f, 0.11719568f, 0.24098417f, - 0.26468599f, 0.31698579f, 0.10103608f, -0.01096375f, -0.01367013f, - 0.17104232f, 0.20065314f, 2.67622480e-003f, -0.01190034f, 0.18301608f, - 0.09459770f, -0.06357619f, -0.06473801f, 0.01377906f, -0.10032775f, - -0.06388740f, 3.80393048e-003f, 0.06206078f, 0.10349120f, 0.26804337f, - 8.17918684e-003f, -0.02314351f, 9.34422202e-003f, 0.09198381f, - 0.03681326f, -8.77339672e-003f, -0.09662418f, -0.02715708f, - 0.13503517f, 0.08962728f, -6.57071499e-003f, -0.03201199f, 0.28510824f, - 0.32095715f, 0.18512695f, -0.14230858f, -0.14048551f, -0.07181299f, - -0.08575408f, -0.08661680f, -0.17416079f, 7.54326640e-004f, - 0.05601677f, 0.13585392f, -0.04960437f, -0.07708392f, 0.10676333f, - -0.04407546f, -0.07209078f, 0.03663663f, 0.28949317f, 0.41127121f, - 0.27431169f, -0.06900328f, -0.21474190f, -0.15578632f, -0.19555484f, - -0.15209621f, -0.11269179f, 0.07416003f, 0.18991330f, 0.26858172f, - 0.01952259f, 0.01017922f, 0.02159843f, -4.95165400e-003f, -0.04368168f, - -0.12721671f, -0.06673957f, -0.11275250f, 0.04413409f, 0.05578312f, - 0.03896771f, 0.03566417f, -0.05871816f, -0.07388090f, -0.17965563f, - -0.08570268f, -0.15273231f, -0.06022318f, -0.06999847f, - -6.81510568e-003f, 0.06294262f, -6.54901436e-004f, -0.01128654f, - -0.02289657f, 0.04849290f, 0.04140804f, 0.23681939f, 0.14545733f, - 0.01989965f, 0.12032662f, 3.87463090e-003f, -6.02597650e-003f, - -0.05919775f, -0.03067224f, -0.07787777f, 0.10834727f, 0.02153730f, - 0.02765649f, 0.03975543f, -0.12182906f, -0.04900113f, -0.09940100f, - -0.06453611f, -0.13757215f, -0.03721382f, 0.02827376f, -0.04351249f, - 0.01907038f, -0.10284120f, -0.05671160f, -0.10760647f, -0.09624009f, - -0.09565596f, -0.01303654f, 0.03080539f, 0.01416511f, 0.05846142f, - -5.42971538e-003f, 0.06221476f, -0.03320325f, -0.06791797f, - -0.05791342f, 0.12851369f, 0.14990346f, 0.03634374f, 0.14262885f, - 0.04330391f, 0.05032569f, -0.05631914f, 0.01606137f, 0.04387223f, - 0.22344995f, 0.15722635f, -0.04693628f, 0.03006579f, -2.52882647e-003f, - 0.05717621f, -0.07529724f, -0.02848588f, -0.06868757f, - -4.51729307e-003f, 0.06466042f, -0.05935378f, -0.04704857f, - -0.07363959f, 0.04843248f, -0.13421375f, -0.09789340f, -0.10255270f, - 0.03509852f, 0.04751543f, -0.03822323f, 0.09740467f, 0.04762916f, - 0.03940146f, -0.08283259f, 0.09552965f, 0.05038739f, 0.21258622f, - 0.09646992f, 0.03241193f, 0.05167701f, 0.04614570f, 0.04330090f, - -0.02671840f, -0.06259909f, -0.02301898f, 0.18829170f, 0.10522786f, - 0.04313190f, 0.01670948f, -0.08421925f, 0.05911417f, -0.10582602f, - -0.04855484f, -0.08373898f, 0.07775915f, 0.03723533f, -0.12047344f, - 4.86345543e-003f, -0.10520902f, 0.06571782f, -0.07528137f, - -0.03245651f, -0.09869066f, -0.02917477f, -0.18293270f, 0.14810945f, - 9.24033765e-003f, -0.04354914f, 0.02266885f, -0.11872729f, - -0.04016589f, 0.02830229f, 0.22539048f, 0.20565644f, 0.16701797f, - 0.09019924f, 0.01300652f, 0.09760600f, -0.03675831f, -0.01935448f, - -0.06894835f, 0.08077277f, 0.19047537f, 0.11312226f, 0.04106043f, - -0.11187182f, 0.04312806f, -0.18548580f, -0.11287174f, -0.08794551f, - 0.02078281f, -0.15295486f, 0.11806386f, -0.01103218f, -0.15971117f, - 0.02153538f, -0.05232147f, -0.10835317f, -0.13910367f, 0.05920752f, - -0.10122602f, 0.20174250f, 0.09105796f, -0.01881348f, 0.09559010f, - -0.03725745f, -0.09442931f, -0.09763174f, 0.05854454f, 0.08287182f, - 0.12919849f, 0.08594352f, -2.49806582e-003f, 0.02398440f, - 5.67950122e-003f, -0.06296340f, -0.12993270f, 0.03855852f, 0.05186560f, - 0.10839908f, -0.03380463f, -0.12654832f, -0.05399339f, -0.07456800f, - -0.04736232f, -0.10164231f, 0.07496139f, 0.08125214f, 0.07656177f, - -0.04999603f, -0.12823077f, -0.07692395f, -0.11317524f, -0.09118655f, - -0.05695669f, 0.10477209f, 0.07468581f, 0.01630048f, -8.00961629e-003f, - -0.06582128f, -0.04019095f, -0.04682907f, -0.01907842f, -0.10997720f, - 0.04911406f, 0.02931030f, 0.04197735f, -0.05773980f, -0.09670641f, - -0.03594951f, -0.03402121f, -0.07149299f, -0.10566200f, 0.10601286f, - 0.06340689f, -0.01518632f, -5.96402306e-003f, -0.07628012f, - -3.52779147e-003f, -0.02683854f, -0.10265494f, -0.02680815f, - 0.16338381f, 0.03103515f, 0.02296976f, 0.01624348f, -0.10831620f, - -0.02314233f, -0.04789969f, -0.05530700f, -0.06461314f, 0.10494506f, - 0.04642856f, -0.07592955f, -0.06197905f, -0.09042154f, -0.01445521f, - -0.04297818f, -0.11262015f, -0.11430512f, 0.03174541f, -0.03677487f, - -0.02963996f, -0.06610169f, -0.13292049f, -0.07059067f, -0.08444111f, - -0.02640536f, -0.07136250f, 0.04559967f, 0.01459980f, 0.17989251f, - 0.04435328f, -0.12464730f, -0.02871115f, -0.10752209f, -0.03393742f, - -0.03791408f, 0.02548251f, 0.01956050f, 0.19245651f, 0.13963254f, - -0.05904696f, -0.07424626f, -0.10411884f, 1.54176133e-003f, - 0.01797429f, 0.13025844f, 0.04547642f, -0.05710349f, -0.10697161f, - -0.13489437f, -0.06515755f, -0.06406886f, -4.08572936e-003f, - -0.01336483f, 0.04368737f, -0.11259720f, -0.05701635f, -0.06469971f, - -0.08346602f, -0.04166770f, -0.05795543f, -0.08247511f, -0.05742628f, - 0.08452254f, -0.03350224f, 0.13980860f, 0.13252275f, 0.07589617f, - 0.07539988f, 0.12155797f, 0.19087289f, 0.15050751f, 0.21250245f, - 0.14206800f, 0.01298489f, 0.07450245f, 0.06559097f, 0.01700557f, - 0.04512971f, 0.16950700f, 0.10261577f, 0.16389982f, 0.05505059f, - -0.03453077f, 0.08622462f, 0.07935954f, 0.03976260f, 0.02036091f, - 3.95744899e-003f, 0.03267065f, 0.15235919f, 0.01297494f, -0.08109194f, - 0.01407558f, 4.40693414e-003f, -0.15157418f, -0.11390478f, - -0.07487597f, -7.81322457e-003f, -0.02749545f, -0.10181408f, - 0.13755716f, 0.14007211f, 0.13482562f, 0.27517235f, 0.34251109f, - 0.07639657f, 0.07268607f, 0.19823882f, 0.16135791f, -0.04186463f, - -0.12784107f, -0.09846287f, 0.03169041f, 0.10974082f, -0.15051922f, - -0.08916726f, -0.07138767f, -0.04153349f, 6.25418453e-003f, - 0.01266654f, 0.10533249f, 0.12749144f, 0.15148053f, 0.01498513f, - 0.06305949f, -0.01247123f, -0.08778401f, -0.08551880f, -0.11955146f, - -0.08493572f, -0.02901620f, -0.02394859f, -0.13427313f, -0.11053200f, - -0.14413260f, -0.15203285f, 0.03972760f, -3.72127310e-004f, - -0.04200919f, 0.06105104f, 0.01904975f, -0.01106191f, - -7.27445772e-003f, -0.01520341f, 1.10228511e-003f, -0.04949187f, - -0.08013099f, 5.72071038e-003f, 0.08415454f, -0.06523152f, 0.03664081f, - -0.02673042f, -0.12066154f, -0.03702074f, 0.06006580f, 0.01628682f, - -6.17772620e-003f, 0.08192339f, -3.41629819e-003f, 0.02870512f, - 0.05807141f, 0.04959986f, 0.04618251f, -0.04901629f, -0.10579574f, - 0.02274442f, 0.12070961f, 2.23597488e-003f, 0.09831765f, -0.03019848f, - -0.11181970f, -0.04961075f, 0.02498928f, -0.03714991f, -0.01619653f, - 0.02643486f, -7.62964319e-003f, -0.02882290f, -0.06242594f, - -0.08439861f, 0.07220893f, 0.07263952f, 0.01561574f, 0.03091968f, - 0.01708712f, -0.03797151f, -3.18561122e-003f, 0.01624021f, - -0.02828573f, 0.11284444f, -1.32280716e-003f, -0.07784860f, - -0.07209100f, 0.03372242f, 0.12154529f, 0.02278104f, -0.05275500f, - -0.01918484f, 0.12989293f, 0.05424401f, 0.02333086f, 0.04029022f, - 0.12392918f, 0.09495489f, 0.09190340f, 0.07935889f, 8.76816828e-003f, - 0.17148446f, -8.51302687e-003f, -0.08011249f, -0.06796283f, - 0.04884845f, 0.01112272f, -0.07835306f, -1.14811445e-003f, - -0.03440760f, 0.02845243f, 0.07695542f, -0.07069533f, -0.01151784f, - -8.53884313e-003f, -0.01662786f, -0.04163864f, 0.05400505f, - 0.02859163f, 0.02921852f, 0.05003135f, -6.85718050e-003f, -0.01632611f, - 0.07780217f, 0.04042810f, -0.01216440f, 3.60914599e-003f, -0.06322435f, - 0.09516726f, 0.12877031f, -9.69162490e-003f, 0.01031179f, 0.05180895f, - -9.34659224e-003f, -0.01644533f, -0.04849347f, -0.04343236f, - 0.10514783f, 0.08046635f, -0.04615205f, -0.03975486f, -0.01485525f, - 0.13096830f, -0.01517950f, -0.06571898f, -0.04016372f, 0.01849786f, - 0.02439670f, 0.08067258f, 1.74824719e-003f, 0.07053747f, 0.08819518f, - -5.08352555e-003f, -0.06550863f, -0.08266170f, -0.07780605f, - 0.01453450f, -0.08756890f, 0.01096501f, -8.71319138e-003f, 0.10110464f, - 0.02420769f, -0.06708383f, 0.02007811f, 5.93133038e-003f, 0.05398923f, - 0.07538138f, 0.02049227f, 0.02242589f, 0.04011070f, -1.44875818e-003f, - -4.19115182e-003f, 0.06367654f, 0.02506934f, 0.02434536f, 0.05879405f, - -8.22952855e-003f, -0.01242441f, 0.04224926f, -0.01754923f, - 0.05958161f, 0.03818886f, -0.01830363f, -0.04308917f, -0.04422197f, - -0.02432721f, 0.02264866f, 2.03751423e-003f, 0.01197031f, 0.04439203f, - 0.12169247f, 0.03602713f, -0.02599251f, -1.98226492e-003f, 0.02046336f, - -0.02639058f, -1.91242550e-003f, -0.09334669f, -0.03595153f, - -9.88179818e-003f, -0.06848445f, -0.04666303f, -0.09955736f, - -0.04206430f, 0.02609075f, 9.09005292e-003f, -0.07138551f, - -4.22313227e-004f, 0.01766645f, 0.02756404f, 0.01308276f, 0.04052891f, - 0.02387515f, 0.05337298f, 0.02500631f, -0.04970853f, -0.12467445f, - 0.17604403f, 0.12256411f, -0.07512254f, 8.70451052e-003f, -0.05697548f, - -0.03626474f, -8.76623299e-003f, -0.01210897f, -0.09451522f, - 0.07490732f, -0.02008001f, -0.02681278f, -0.06463405f, -0.01517507f, - 7.33757764e-003f, 6.07147906e-003f, -0.09316964f, -0.04575328f, - 0.13261597f, 0.15424870f, -0.01655918f, -0.02772390f, -0.05243644f, - -0.02356456f, -0.02351753f, -0.10211615f, -0.12873036f, 0.14549787f, - 0.12519856f, 4.38762689e-003f, 0.02795992f, 0.05170322f, 0.09223596f, - 0.05890015f, 0.02376701f, -0.02777346f, 0.09506908f, 0.02328936f, - -0.02319928f, -0.03218696f, -0.01527841f, -0.01016694f, -0.02674719f, - 0.05137179f, 0.01980666f, 0.06544447f, -0.01746171f, 0.01026380f, - 0.01561806f, 7.97004555e-004f, 0.07601810f, 0.01907250f, -0.03083035f, - -0.05987392f, 0.09242783f, 0.14555025f, 0.01035827f, 0.03092401f, - -0.09562709f, -0.03802354f, 0.02531144f, 0.03079449f, -0.07100715f, - 0.03330721f, -2.69116857e-003f, 0.03167490f, 0.05744999f, 0.03259895f, - 1.91266940e-003f, 0.03194578f, 0.07389776f, 0.02198060f, 0.07633314f, - 0.03293105f, -0.09103648f, 0.04718142f, 0.06102672f, -0.01003063f, - 5.85481385e-003f, -0.01522574f, 0.02323526f, 0.10584345f, - 4.35879454e-003f, 0.06107873f, 0.05868603f, -0.03115531f, 0.01214679f, - 0.08567052f, 3.93926632e-003f, -0.02521488f, -1.88425183e-003f, - 0.02038053f, -6.26854831e-004f, 0.04897438f, -0.04280585f, - -0.04819689f, -0.04812867f, -0.01451186f, 0.05101469f, - -9.01125465e-003f, -0.03333859f, 0.03917955f, 0.04196448f, 0.04292135f, - 0.02809529f, 0.02999715f, 0.04081348f, 9.10039060e-003f, 0.09703232f, - 0.10379741f, 0.02348725f, -4.72756615e-003f, 0.01027325f, 0.10402658f, - 0.12071823f, 0.09817299f, -0.02612033f, 0.03638414f, 0.05896405f, - 0.04865025f, 0.04793910f, -0.03882321f, -0.02962117f, -0.01222268f, - 0.04071597f, 0.01922777f, -0.02287866f, 0.03328381f, 0.01859092f, - 0.09024994f, 0.03804455f, -0.01424510f, 0.01953739f, 0.02509617f, - -0.03390914f, -0.05663941f, -0.01641979f, 0.05848591f, 0.04639670f, - 0.02092116f, 0.12911791f, 0.19918139f, 0.07739855f, -7.25806039e-003f, - 0.04074838f, 0.03183993f, 1.39251316e-003f, -0.01428625f, 0.01865480f, - 0.08529541f, 0.13547510f, 0.11189661f, 0.03998901f, 0.09575938f, - -0.02631102f, -0.03458253f, -0.04749985f, -0.06070716f, - 4.71884012e-003f, 0.06445789f, -0.02450038f, -0.05483776f, - -0.04657237f, -0.02030717f, -0.03480766f, -0.09397731f, -0.06399718f, - -0.01804585f, 5.62348310e-003f, -6.64811488e-003f, -0.06517869f, - 6.96210237e-003f, -0.01860148f, -0.04245830f, -0.05850367f, - -3.24417115e-003f, 0.07700698f, 0.11290991f, 0.09923030f, -0.02970599f, - 0.05592411f, 0.04813979f, -0.09811195f, -0.09357996f, -0.03276114f, - 0.05218338f, 0.04141375f, 3.92977800e-003f, -0.05047480f, 0.15960084f, - 0.04612800f, -0.03114098f, -0.04650044f, -0.03249795f, -0.02425641f, - -0.04311355f, 0.04307659f, -0.09401883f, -0.04742785f, -0.01254499f, - -0.06598741f, 3.41369561e-003f, -0.05620445f, -7.28127593e-003f, - -0.05998361f, -0.03274450f, -0.07376868f, 3.19015374e-003f, - -0.07733069f, 0.05815864f, -0.02471071f, 0.03850617f, 0.13838784f, - 0.15399861f, 0.01731321f, -0.01477586f, 0.10393341f, 0.05159833f, - -0.01945555f, -0.03427503f, -0.04867341f, 0.09237480f, 0.10732719f, - 0.06071450f, -0.01355071f, 0.01844356f, -0.03480803f, -0.03796671f, - 2.15628621e-004f, -0.05440186f, 0.01889855f, -0.01443413f, - -0.02607902f, -0.02938001f, 0.02720689f, -0.06228397f, -0.02970936f, - -0.03426210f, -0.10280876f, -0.06739304f, -0.05227850f, 0.03360292f, - -0.11278441f, -0.06966180f, -0.13937433f, 9.10932291e-003f, - 2.52020749e-004f, -4.07359656e-003f, 0.12310639f, 0.09343060f, - 0.07302511f, 0.03222093f, 0.07532879f, 0.03792387f, -0.04985180f, - 0.01804602f, 0.02694195f, 0.13481498f, 0.04601225f, 0.04106982f, - 0.08511057f, 0.12314661f, 0.01320830f, 0.05044121f, -5.52943908e-003f, - -0.08992624f, -0.02249301f, -0.08181777f, 0.06165213f, -0.03256603f, - -0.01068920f, -0.01323473f, -0.11970232f, -0.04616347f, -0.12088681f, - -0.06762606f, -0.08676834f, -0.06434575f, 0.01772529f, 0.03469615f, - -0.10926618f, 0.03013873f, 0.14030397f, 0.16130108f, 0.17985588f, - 0.11281928f, 0.10530639f, 0.08905948f, 0.07733764f, 0.06695238f, - 0.02142088f, 0.06438877f, 0.09794453f, 0.05745072f, 0.02788557f, - 0.02632830f, 0.07985807f, 4.24902979e-003f, 8.47890321e-003f, - -0.02679466f, -5.28812688e-003f, -0.02162580f, -0.07490715f, - -0.08251337f, -0.02056576f, -0.01026194f, -1.15492963e-003f, - -5.75720915e-004f, -0.07210591f, -0.07320981f, -0.04883312f, - -0.10897151f, -0.07477258f, -0.08867134f, -0.09222437f, -0.10924666f, - -0.10430276f, 0.07953499f, 0.02767959f, 0.11393359f, 0.18779543f, - 0.03313421f, 0.02143700f, 0.05852016f, -2.12067598e-003f, - -3.76984011e-003f, 0.02774167f, -0.03124610f, 0.01465141f, 0.01616004f, - -0.01391913f, -0.04404102f, -0.05444227f, -0.14684731f, -0.15016587f, - 0.04509468f, 1.29563001e-003f, 0.01398350f, 0.05610404f, -0.04868806f, - -0.04776716f, -8.16873740e-003f, -2.30126386e-003f, -0.02286313f, - 0.11983398f, -0.04703261f, -0.08814441f, -0.07585249f, -0.10799607f, - -0.03232087f, 0.01509786f, -0.04843464f, -0.03967846f, 0.09589416f, - 0.01352560f, -0.01458119f, 0.01050829f, -0.03038946f, 0.01608388f, - 1.11975556e-003f, -0.01250656f, 2.86211423e-003f, 0.04333691f, - -0.14603497f, -0.01946543f, -0.02327525f, -0.01973944f, 0.07944400f, - -0.02224544f, -0.06701808f, 0.03476532f, 0.11505594f, -0.02712801f, - -0.01665113f, 0.06315716f, -0.08205860f, 0.07431999f, 0.04915778f, - -0.04468752f, -0.01490402f, 0.07400476f, -0.11650901f, 0.05102430f, - 0.04559118f, -0.05916039f, 0.08840760f, -0.01587902f, -0.14890194f, - 0.07857784f, 0.04710254f, -0.05381983f, -0.07331945f, -0.03604643f, - 0.15611970f, 0.07649943f, -0.05959348f, -0.02776607f, 0.11098688f, - 0.03758875f, -0.04446875f, 0.04933187f, 0.01345535f, 0.06921103f, - 0.07364785f, 0.05518956f, 0.02899585f, 0.09375840f, 0.10518434f, - -0.04420241f, 0.01915282f, -3.56386811e-003f, 0.14586878f, 0.10286101f, - -0.04360626f, -0.12723237f, 0.09076386f, 0.11119842f, -0.06035013f, - 0.09674817f, 0.08938243f, 0.07065924f, 0.02603180f, 5.84815582e-003f, - -0.05922065f, 0.12360309f, 3.59695964e-003f, 2.99844006e-003f, - 0.03697936f, 0.02043072f, 0.04168725f, 0.01025975f, -0.01359980f, - -0.01600920f, 0.02581056f, 0.02329250f, 2.98100687e-003f, 0.01629762f, - 0.06652115f, 0.05855627f, 0.01237463f, -0.01297135f, 0.01761587f, - 0.05090865f, 0.06549342f, -0.04425945f, 2.43203156e-003f, - 3.07327788e-003f, 0.06678630f, -0.04303836f, 0.01082393f, -0.06476044f, - 0.04077786f, 0.12441979f, 0.08237778f, 0.07424165f, 0.04065890f, - 0.06905543f, 0.09556347f, 0.12724875f, -0.02132082f, 0.08514154f, - -0.04175328f, -0.02666954f, 0.01897836f, 0.03317382f, 9.45465732e-003f, - -0.01238974f, -0.04242500f, -0.01419479f, -0.03545213f, -0.02440874f, - 0.08684119f, 0.04212951f, 0.02462858f, -0.01104825f, -5.01706870e-003f, - 0.02968982f, 0.02597476f, -0.01568939f, 0.04514892f, 0.06974549f, - 0.08670278f, 0.06828108f, 0.10238872f, 0.05405957f, 0.06548470f, - -0.03763957f, 0.01366090f, 0.07069602f, 0.05363748f, 0.04798120f, - 0.11706422f, 0.05466456f, -0.01869259f, 0.06344382f, 0.03106543f, - 0.08432506f, -0.02061096f, 0.03821088f, -6.92190882e-003f, - 6.40467042e-003f, -0.01271779f, 6.89014705e-005f, 0.04541415f, - -0.01899539f, -0.05020239f, 0.03000903f, 0.01090422f, 4.52452758e-003f, - 0.02573632f, -0.02388454f, -0.04200457f, 1.72783900e-003f, - -0.05978370f, -0.02720562f, 0.06573715f, 0.01154317f, 0.01265615f, - 0.07375994f, -9.19828378e-003f, -0.04914120f, 0.02124831f, 0.06455322f, - 0.04372910f, -0.03310043f, 0.03605788f, -6.78055827e-003f, - 9.36202332e-003f, 0.01747596f, -0.06406314f, -0.06812935f, 0.08080816f, - -0.02778088f, 0.02735260f, 0.06393493f, 0.06652229f, 0.05676993f, - 0.08640018f, -7.59188086e-003f, -0.02012847f, -0.04741159f, - -0.01657069f, -0.01624399f, 0.05547778f, -2.33309763e-003f, - 0.01120033f, 0.06141156f, -0.06285004f, -0.08732341f, -0.09313398f, - -0.04267832f, 5.57443965e-003f, 0.04809862f, 0.01773641f, - 5.37361018e-003f, 0.14842421f, -0.06298012f, -0.02935147f, 0.11443478f, - -0.05034208f, 5.65494271e-003f, 0.02076526f, -0.04577984f, - -0.04735741f, 0.02961071f, -0.09307127f, -0.04417921f, -0.04990027f, - -0.03940028f, 0.01306016f, 0.06267900f, 0.03758737f, 0.08460117f, - 0.13858789f, 0.04862388f, -0.06319809f, -0.05655516f, 0.01885816f, - -0.03285607f, 0.03371567f, -0.07040928f, -0.04514049f, 0.01392166f, - 0.08184422f, -0.07230316f, 0.02386871f, 0.02184591f, 0.02605764f, - -0.01033954f, 9.29878280e-003f, 7.67351175e-003f, 0.15189242f, - 0.02069071f, -0.09738296f, -0.08894105f, -0.07768748f, 0.02332268f, - -0.01778995f, -0.03258888f, -0.08180822f, -0.08492987f, 0.02290156f, - -0.11368170f, -0.03554465f, -0.04533844f, -0.02861580f, 0.06782424f, - 0.01113123f, 0.02453644f, 0.12721945f, 0.08084814f, -0.03607795f, - 0.01109122f, 0.04803548f, -0.03489929f, 0.03399536f, -0.05682014f, - 8.59533902e-003f, -4.27904585e-003f, 0.03230887f, -0.01300198f, - -0.01038137f, -0.07930113f, 8.33097473e-003f, 0.02296994f, - -0.01306500f, -0.01881626f, 0.04413369f, 0.05729880f, -0.03761553f, - 0.01942326f, 1.64540811e-003f, -0.03811319f, 0.04190650f, -0.14978096f, - -0.04514487f, 0.01209545f, -5.46460645e-003f, -0.01647195f, - 7.63064111e-003f, -0.07494587f, 0.08415288f, 0.10020141f, -0.01228561f, - 0.06553826f, 0.04554005f, 0.07890417f, 0.03041138f, 0.01752007f, - 0.09208256f, -3.74419295e-004f, 0.10549527f, 0.04686913f, 0.01894833f, - -0.02651412f, -4.34682379e-003f, 5.44942822e-003f, 0.01444484f, - 0.05882156f, -0.03336544f, 0.04603891f, -0.10432546f, 0.01923928f, - 0.01842845f, -0.01712168f, -0.02222766f, 0.04693324f, -0.06202956f, - -0.01422159f, 0.08732220f, -0.07706107f, 0.02661049f, -0.04300238f, - -0.03092422f, -0.03552184f, -0.01886088f, -0.04979934f, 0.03906401f, - 0.04608644f, 0.04966111f, 0.04275464f, -0.04621769f, -0.02653212f, - 8.57011229e-003f, 0.03839684f, 0.05818764f, 0.03880796f, - -2.76100676e-004f, 0.03076511f, -0.03266929f, -0.05374557f, - 0.04986527f, -9.45429131e-003f, 0.03582499f, -2.64564669e-003f, - -1.07461517e-003f, 0.02962313f, -0.01483363f, 0.03060869f, 0.02448327f, - 0.01845641f, 0.03282966f, -0.03534438f, -0.01084059f, -0.01119136f, - -1.85360224e-003f, -5.94652840e-004f, -0.04451817f, 2.98327743e-003f, - 0.06272484f, -0.02152076f, -3.05971340e-003f, -0.05070828f, - 0.01531762f, 0.01282815f, 0.05167150f, 9.46266949e-003f, - -3.34558333e-003f, 0.11442288f, -0.03906701f, -2.67325155e-003f, - 0.03069184f, -0.01134165f, 0.02949462f, 0.02879886f, 0.03855566f, - -0.03450781f, 0.09142872f, -0.02156654f, 0.06075062f, -0.06220816f, - 0.01944680f, 6.68372354e-003f, -0.06656796f, 8.70784000e-003f, - 0.03456013f, 0.02434320f, -0.13236357f, -0.04177035f, -0.02069627f, - 0.01068112f, 0.01505432f, -0.07517391f, -3.83571628e-003f, - -0.06298508f, -0.02881260f, -0.13101046f, -0.07221562f, - -5.79945277e-003f, -8.57300125e-003f, 0.03782469f, 0.02762164f, - 0.04942456f, -0.02936396f, 0.09597211f, 0.01921411f, 0.06101191f, - -0.04787507f, -0.01379578f, -7.40224449e-003f, -0.02220136f, - -0.01313756f, 7.77558051e-003f, 0.12296968f, 0.02939998f, 0.03594062f, - -0.07788624f, -0.01133144f, 3.99316690e-004f, -0.06090347f, - -0.01122066f, -4.68682544e-003f, 0.07633100f, -0.06748922f, - -0.05640298f, -0.05265681f, -0.01139122f, -0.01624347f, -0.04715714f, - -0.01099092f, 0.01048561f, 3.28499987e-003f, -0.05810167f, - -0.07699911f, -0.03330683f, 0.04185145f, 0.03478536f, 0.02275165f, - 0.02304766f, 6.66040834e-003f, 0.10968148f, -5.93013782e-003f, - -0.04858336f, -0.04203213f, -0.09316786f, -6.13074889e-003f, - -0.02544625f, 0.01366201f, 9.18555818e-003f, -0.01846578f, - -0.05622401f, -0.03989377f, -0.07810296f, 6.91275718e-003f, - 0.05957597f, -0.03901334f, 0.01572002f, -0.01193903f, - -6.89400872e-003f, -0.03093356f, -0.04136098f, -0.01562869f, - -0.04604580f, 0.02865234f, -0.08678447f, -0.03232484f, -0.05364593f, - -0.01445016f, -0.07003860f, -0.08669746f, -0.04520775f, 0.04274122f, - 0.03117515f, 0.08175703f, 0.01081109f, 0.06379741f, 0.06199206f, - 0.02865988f, 0.02360346f, 0.06725410f, -0.03248780f, -9.37702879e-003f, - 0.08265898f, -0.02245839f, 0.05125763f, -0.01862395f, 0.01973453f, - -0.01994494f, -0.10770868f, 0.03180375f, 3.23935156e-003f, - -0.02142080f, -0.04256190f, 0.04760900f, 0.04282863f, 0.05635953f, - -0.01870849f, 0.05540622f, -0.03042666f, 0.01455277f, -0.06630179f, - -0.05843807f, -0.03739681f, -0.09739155f, -0.03220233f, -0.05620182f, - -0.10381401f, 0.07400211f, 4.20676917e-003f, 0.03258535f, - 2.14308966e-003f, 0.05121966f, -0.01274337f, 0.02384761f, 0.06335578f, - -0.07905591f, 0.08375625f, -0.07898903f, -0.06508528f, -0.02498444f, - 0.06535810f, 0.03970535f, 0.04895468f, -0.01169566f, -0.03980601f, - 0.05682293f, 0.05925463f, -0.01165808f, -0.07936699f, -0.04208954f, - 0.01333987f, 0.09051196f, 0.10098671f, -0.03974256f, 0.01238771f, - -0.07501741f, -0.03655440f, -0.04301528f, 0.09216860f, - 4.63579083e-004f, 0.02851115f, 0.02142735f, 1.28244064e-004f, - 0.02879687f, -0.08554889f, -0.04838862f, 0.08135369f, -0.05756533f, - 0.01413900f, 0.03451880f, -0.06619488f, -0.03053130f, 0.02961676f, - -0.07384635f, 0.01135692f, 0.05283910f, -0.07778034f, -0.02107482f, - -0.05511716f, -0.13473752f, 0.03030157f, 0.06722020f, -0.06218817f, - -0.05826827f, 0.06254654f, 0.02895772f, -0.01664000f, -0.03620280f, - -0.01612278f, -1.46097376e-003f, 0.14013411f, -8.96181818e-003f, - -0.03250246f, 3.38630192e-003f, 2.64779478e-003f, 0.03359732f, - -0.02411991f, -0.04229729f, 0.10666174f, -6.66579151f }; - return std::vector(detector, detector + sizeof(detector)/sizeof(detector[0])); -} - -// This function renurn 1981 SVM coeffs obtained from daimler's base. -// To use these coeffs the detection window size should be (48,96) -std::vector HOGDescriptor::getDaimlerPeopleDetector() -{ - static const float detector[] = { - 0.294350f, -0.098796f, -0.129522f, 0.078753f, - 0.387527f, 0.261529f, 0.145939f, 0.061520f, - 0.328699f, 0.227148f, -0.066467f, -0.086723f, - 0.047559f, 0.106714f, 0.037897f, 0.111461f, - -0.024406f, 0.304769f, 0.254676f, -0.069235f, - 0.082566f, 0.147260f, 0.326969f, 0.148888f, - 0.055270f, -0.087985f, 0.261720f, 0.143442f, - 0.026812f, 0.238212f, 0.194020f, 0.056341f, - -0.025854f, -0.034444f, -0.156631f, 0.205174f, - 0.089008f, -0.139811f, -0.100147f, -0.037830f, - -0.029230f, -0.055641f, 0.033248f, -0.016512f, - 0.155244f, 0.247315f, -0.124694f, -0.048414f, - -0.062219f, 0.193683f, 0.004574f, 0.055089f, - 0.093565f, 0.167712f, 0.167581f, 0.018895f, - 0.215258f, 0.122609f, 0.090520f, -0.067219f, - -0.049029f, -0.099615f, 0.241804f, -0.094893f, - -0.176248f, 0.001727f, -0.134473f, 0.104442f, - 0.050942f, 0.081165f, 0.072156f, 0.121646f, - 0.002656f, -0.297974f, -0.133587f, -0.060121f, - -0.092515f, -0.048974f, -0.084754f, -0.180111f, - -0.038590f, 0.086283f, -0.134636f, -0.107249f, - 0.132890f, 0.141556f, 0.249425f, 0.130273f, - -0.030031f, 0.073212f, -0.008155f, 0.019931f, - 0.071688f, 0.000300f, -0.019525f, -0.021725f, - -0.040993f, -0.086841f, 0.070124f, 0.240033f, - 0.265350f, 0.043208f, 0.166754f, 0.091453f, - 0.060916f, -0.036972f, -0.091043f, 0.079873f, - 0.219781f, 0.158102f, -0.140618f, -0.043016f, - 0.124802f, 0.093668f, 0.103208f, 0.094872f, - 0.080541f, 0.137711f, 0.160566f, -0.169231f, - 0.013983f, 0.309508f, -0.004217f, -0.057200f, - -0.064489f, 0.014066f, 0.361009f, 0.251328f, - -0.080983f, -0.044183f, 0.061436f, -0.037381f, - -0.078786f, 0.030993f, 0.066314f, 0.037683f, - 0.152325f, -0.091683f, 0.070203f, 0.217856f, - 0.036435f, -0.076462f, 0.006254f, -0.094431f, - 0.154829f, -0.023038f, -0.196961f, -0.024594f, - 0.178465f, -0.050139f, -0.045932f, -0.000965f, - 0.109112f, 0.046165f, -0.159373f, -0.008713f, - 0.041307f, 0.097129f, -0.057211f, -0.064599f, - 0.077165f, 0.176167f, 0.138322f, 0.065753f, - -0.104950f, 0.017933f, 0.136255f, -0.011598f, - 0.047007f, 0.080550f, 0.068619f, 0.084661f, - -0.035493f, -0.091314f, -0.041411f, 0.060971f, - -0.101912f, -0.079870f, -0.085977f, -0.022686f, - 0.079788f, -0.098064f, -0.054603f, 0.040383f, - 0.300794f, 0.128603f, 0.094844f, 0.047407f, - 0.101825f, 0.061832f, -0.162160f, -0.204553f, - -0.035165f, 0.101450f, -0.016641f, -0.027140f, - -0.134392f, -0.008743f, 0.102331f, 0.114853f, - 0.009644f, 0.062823f, 0.237339f, 0.167843f, - 0.053066f, -0.012592f, 0.043158f, 0.002305f, - 0.065001f, -0.038929f, -0.020356f, 0.152343f, - 0.043469f, -0.029967f, -0.042948f, 0.032481f, - 0.068488f, -0.110840f, -0.111083f, 0.111980f, - -0.002072f, -0.005562f, 0.082926f, 0.006635f, - -0.108153f, 0.024242f, -0.086464f, -0.189884f, - -0.017492f, 0.191456f, -0.007683f, -0.128769f, - -0.038017f, -0.132380f, 0.091926f, 0.079696f, - -0.106728f, -0.007656f, 0.172744f, 0.011576f, - 0.009883f, 0.083258f, -0.026516f, 0.145534f, - 0.153924f, -0.130290f, -0.108945f, 0.124490f, - -0.003186f, -0.100485f, 0.015024f, -0.060512f, - 0.026288f, -0.086713f, -0.169012f, 0.076517f, - 0.215778f, 0.043701f, -0.131642f, -0.012585f, - -0.045181f, -0.118183f, -0.241544f, -0.167293f, - -0.020107f, -0.019917f, -0.101827f, -0.107096f, - -0.010503f, 0.044938f, 0.189680f, 0.217119f, - -0.046086f, 0.044508f, 0.199716f, -0.036004f, - -0.148927f, 0.013355f, -0.078279f, 0.030451f, - 0.056301f, -0.024609f, 0.083224f, 0.099533f, - -0.039432f, -0.138880f, 0.005482f, -0.024120f, - -0.140468f, -0.066381f, -0.017057f, 0.009260f, - -0.058004f, -0.028486f, -0.061610f, 0.007483f, - -0.158309f, -0.150687f, -0.044595f, -0.105121f, - -0.045763f, -0.006618f, -0.024419f, -0.117713f, - -0.119366f, -0.175941f, -0.071542f, 0.119027f, - 0.111362f, 0.043080f, 0.034889f, 0.093003f, - 0.007842f, 0.057368f, -0.108834f, -0.079968f, - 0.230959f, 0.020205f, 0.011470f, 0.098877f, - 0.101310f, -0.030215f, -0.018018f, -0.059552f, - -0.106157f, 0.021866f, -0.036471f, 0.080051f, - 0.041165f, -0.082101f, 0.117726f, 0.030961f, - -0.054763f, -0.084102f, -0.185778f, -0.061305f, - -0.038089f, -0.110728f, -0.264010f, 0.076675f, - -0.077111f, -0.137644f, 0.036232f, 0.277995f, - 0.019116f, 0.107738f, 0.144003f, 0.080304f, - 0.215036f, 0.228897f, 0.072713f, 0.077773f, - 0.120168f, 0.075324f, 0.062730f, 0.122478f, - -0.049008f, 0.164912f, 0.162450f, 0.041246f, - 0.009891f, -0.097827f, -0.038700f, -0.023027f, - -0.120020f, 0.203364f, 0.248474f, 0.149810f, - -0.036276f, -0.082814f, -0.090343f, -0.027143f, - -0.075689f, -0.320310f, -0.000500f, -0.143334f, - -0.065077f, -0.186936f, 0.129372f, 0.116431f, - 0.181699f, 0.170436f, 0.418854f, 0.460045f, - 0.333719f, 0.230515f, 0.047822f, -0.044954f, - -0.068086f, 0.140179f, -0.044821f, 0.085550f, - 0.092483f, -0.107296f, -0.130670f, -0.206629f, - 0.114601f, -0.317869f, -0.076663f, 0.038680f, - 0.212753f, -0.016059f, -0.126526f, -0.163602f, - 0.210154f, 0.099887f, -0.126366f, 0.118453f, - 0.019309f, -0.021611f, -0.096499f, -0.111809f, - -0.200489f, 0.142854f, 0.228840f, -0.353346f, - -0.179151f, 0.116834f, 0.252389f, -0.031728f, - -0.188135f, -0.158998f, 0.386523f, 0.122315f, - 0.209944f, 0.394023f, 0.359030f, 0.260717f, - 0.170335f, 0.013683f, -0.142596f, -0.026138f, - -0.011878f, -0.150519f, 0.047159f, -0.107062f, - -0.147347f, -0.187689f, -0.186027f, -0.208048f, - 0.058468f, -0.073026f, -0.236556f, -0.079788f, - -0.146216f, -0.058563f, -0.101361f, -0.071294f, - -0.071093f, 0.116919f, 0.234304f, 0.306781f, - 0.321866f, 0.240000f, 0.073261f, -0.012173f, - 0.026479f, 0.050173f, 0.166127f, 0.228955f, - 0.061905f, 0.156460f, 0.205990f, 0.120672f, - 0.037350f, 0.167884f, 0.290099f, 0.420900f, - -0.012601f, 0.189839f, 0.306378f, 0.118383f, - -0.095598f, -0.072360f, -0.132496f, -0.224259f, - -0.126021f, 0.022714f, 0.284039f, 0.051369f, - -0.000927f, -0.058735f, -0.083354f, -0.141254f, - -0.187578f, -0.202669f, 0.048902f, 0.246597f, - 0.441863f, 0.342519f, 0.066979f, 0.215286f, - 0.188191f, -0.072240f, -0.208142f, -0.030196f, - 0.178141f, 0.136985f, -0.043374f, -0.181098f, - 0.091815f, 0.116177f, -0.126690f, -0.386625f, - 0.368165f, 0.269149f, -0.088042f, -0.028823f, - 0.092961f, 0.024099f, 0.046112f, 0.176756f, - 0.135849f, 0.124955f, 0.195467f, -0.037218f, - 0.167217f, 0.188938f, 0.053528f, -0.066561f, - 0.133721f, -0.070565f, 0.115898f, 0.152435f, - -0.116993f, -0.110592f, -0.179005f, 0.026668f, - 0.080530f, 0.075084f, -0.070401f, 0.012497f, - 0.021849f, -0.139764f, -0.022020f, -0.096301f, - -0.064954f, -0.127446f, -0.013806f, -0.108315f, - 0.156285f, 0.149867f, -0.011382f, 0.064532f, - 0.029168f, 0.027393f, 0.069716f, 0.153735f, - 0.038459f, 0.230714f, 0.253840f, 0.059522f, - -0.045053f, 0.014083f, 0.071103f, 0.068747f, - 0.095887f, 0.005832f, 0.144887f, 0.026357f, - -0.067359f, -0.044151f, -0.123283f, -0.019911f, - 0.005318f, 0.109208f, -0.003201f, -0.021734f, - 0.142025f, -0.066907f, -0.120070f, -0.188639f, - 0.012472f, -0.048704f, -0.012366f, -0.184828f, - 0.168591f, 0.267166f, 0.058208f, -0.044101f, - 0.033500f, 0.178558f, 0.104550f, 0.122418f, - 0.080177f, 0.173246f, 0.298537f, 0.064173f, - 0.053397f, 0.174341f, 0.230984f, 0.117025f, - 0.166242f, 0.227781f, 0.120623f, 0.176952f, - -0.011393f, -0.086483f, -0.008270f, 0.051700f, - -0.153369f, -0.058837f, -0.057639f, -0.060115f, - 0.026349f, -0.160745f, -0.037894f, -0.048575f, - 0.041052f, -0.022112f, 0.060365f, 0.051906f, - 0.162657f, 0.138519f, -0.050185f, -0.005938f, - 0.071301f, 0.127686f, 0.062342f, 0.144400f, - 0.072600f, 0.198436f, 0.246219f, -0.078185f, - -0.036169f, 0.075934f, 0.047328f, -0.013601f, - 0.087205f, 0.019900f, 0.022606f, -0.015365f, - -0.092506f, 0.075275f, -0.116375f, 0.050500f, - 0.045118f, 0.166567f, 0.072073f, 0.060371f, - 0.131747f, -0.169863f, -0.039352f, -0.047486f, - -0.039797f, -0.204312f, 0.021710f, 0.129443f, - -0.021173f, 0.173416f, -0.070794f, -0.063986f, - 0.069689f, -0.064099f, -0.123201f, -0.017372f, - -0.206870f, 0.065863f, 0.113226f, 0.024707f, - -0.071341f, -0.066964f, -0.098278f, -0.062927f, - 0.075840f, 0.014716f, 0.019378f, 0.132699f, - -0.074191f, -0.089557f, -0.078446f, -0.197488f, - -0.173665f, 0.052583f, 0.044361f, 0.113549f, - 0.098492f, 0.077379f, -0.011146f, -0.192593f, - -0.164435f, 0.045568f, 0.205699f, 0.049187f, - -0.082281f, 0.134874f, 0.185499f, 0.034968f, - -0.119561f, -0.112372f, -0.115091f, -0.054042f, - -0.183816f, -0.078100f, 0.190695f, 0.091617f, - 0.004257f, -0.041135f, -0.061453f, -0.141592f, - -0.194809f, -0.120638f, 0.020168f, 0.109672f, - 0.067398f, -0.015238f, -0.239145f, -0.264671f, - -0.185176f, 0.050472f, 0.020793f, 0.035678f, - 0.022839f, -0.052055f, -0.127968f, -0.113049f, - -0.228416f, -0.258281f, -0.053437f, 0.076424f, - 0.061450f, 0.237478f, 0.003618f, -0.055865f, - -0.108087f, -0.028937f, 0.045585f, 0.052829f, - -0.001471f, 0.022826f, 0.059565f, -0.104430f, - -0.077266f, -0.211882f, -0.212078f, 0.028074f, - 0.075846f, 0.016265f, 0.161879f, 0.134477f, - 0.008935f, -0.048041f, 0.074692f, 0.004928f, - -0.025156f, 0.192874f, 0.074410f, 0.308732f, - 0.267400f, 0.094208f, -0.005251f, 0.042041f, - -0.032148f, 0.015588f, 0.252869f, 0.175302f, - 0.022892f, 0.081673f, 0.063208f, 0.162626f, - 0.194426f, 0.233890f, 0.262292f, 0.186930f, - 0.084079f, -0.286388f, -0.213034f, -0.048867f, - -0.207669f, -0.170050f, 0.011673f, -0.092958f, - -0.192786f, -0.273536f, 0.230904f, 0.266732f, - 0.320519f, 0.297155f, 0.548169f, 0.304922f, - 0.132687f, 0.247333f, 0.212488f, -0.271472f, - -0.142105f, -0.002627f, -0.119215f, 0.128383f, - 0.100079f, -0.057490f, -0.121902f, -0.228892f, - 0.202292f, -0.399795f, -0.371326f, -0.095836f, - -0.063626f, -0.161375f, -0.311180f, -0.294797f, - 0.242122f, 0.011788f, 0.095573f, 0.322523f, - 0.511840f, 0.322880f, 0.313259f, 0.173331f, - 0.002542f, -0.029802f, 0.324766f, -0.326170f, - -0.340547f, -0.138288f, -0.002963f, -0.114060f, - -0.377312f, -0.442570f, 0.212446f, -0.007759f, - -0.011576f, 0.169711f, 0.308689f, 0.317348f, - 0.539390f, 0.332845f, 0.057331f, -0.068180f, - 0.101994f, 0.266995f, 0.209570f, 0.355730f, - 0.091635f, 0.170238f, 0.125215f, 0.274154f, - 0.070223f, 0.025515f, 0.049946f, -0.000550f, - 0.043715f, -0.141843f, 0.020844f, 0.129871f, - 0.256588f, 0.105015f, 0.148339f, 0.170682f, - 0.028792f, 0.074037f, 0.160042f, 0.405137f, - 0.246187f, 0.352160f, 0.168951f, 0.222263f, - 0.264439f, 0.065945f, 0.021963f, -0.075084f, - 0.093105f, 0.027318f, 0.098864f, 0.057566f, - -0.080282f, 0.185032f, 0.314419f, 0.333727f, - 0.125798f, 0.294919f, 0.386002f, 0.217619f, - -0.183517f, -0.278622f, -0.002342f, -0.027821f, - -0.134266f, -0.331843f, -0.008296f, 0.124564f, - 0.053712f, -0.369016f, -0.095036f, 0.209381f, - 0.423760f, 0.371760f, 0.106397f, 0.369408f, - 0.485608f, 0.231201f, -0.138685f, -0.349208f, - -0.070083f, 0.028991f, -0.081630f, -0.395992f, - -0.146791f, -0.027354f, 0.063396f, -0.272484f, - 0.058299f, 0.338207f, 0.110767f, -0.052642f, - -0.233848f, -0.027448f, 0.030328f, 0.155572f, - -0.093826f, 0.019331f, 0.120638f, 0.006292f, - -0.106083f, -0.236290f, -0.140933f, -0.088067f, - -0.025138f, -0.208395f, -0.025502f, 0.144192f, - -0.048353f, -0.106144f, -0.305121f, -0.114147f, - 0.090963f, 0.327727f, 0.035606f, -0.093779f, - 0.002651f, -0.171081f, -0.188131f, -0.216571f, - -0.209101f, -0.054402f, 0.157147f, -0.057127f, - 0.066584f, 0.008988f, 0.041191f, 0.034456f, - -0.078255f, 0.052099f, -0.022239f, 0.066981f, - -0.117520f, -0.072637f, 0.062512f, 0.037570f, - -0.057544f, -0.312359f, 0.034357f, -0.031549f, - 0.002566f, -0.207375f, -0.070654f, -0.018786f, - -0.044815f, -0.012814f, -0.076320f, 0.078183f, - 0.023877f, 0.117078f, 0.022292f, -0.205424f, - -0.060430f, -0.017296f, -0.004827f, -0.321036f, - -0.092155f, 0.038837f, 0.073190f, -0.067513f, - 0.026521f, 0.171945f, 0.087318f, 0.034495f, - -0.034089f, 0.154410f, -0.061431f, 0.007435f, - -0.111094f, -0.095976f, 0.014741f, -0.132324f, - -0.029517f, -0.192160f, 0.098667f, 0.020762f, - 0.177050f, -0.064510f, -0.054437f, -0.058678f, - -0.001858f, 0.167602f, 0.015735f, 0.054338f, - 0.016477f, 0.186381f, -0.010667f, 0.054692f, - 0.126742f, 0.013140f, 0.090353f, -0.133608f, - -0.018017f, -0.152619f, 0.027600f, -0.138700f, - -0.050274f, 0.045141f, -0.118731f, 0.094797f, - -0.167605f, 0.097461f, -0.009131f, 0.199920f, - -0.052976f, 0.158194f, 0.178568f, -0.107600f, - 0.009671f, -0.084072f, -0.040258f, -0.205673f, - 0.102891f, 0.223511f, 0.042699f, 0.118548f, - -0.021274f, 0.110997f, -0.155121f, 0.027696f, - -0.149968f, 0.051552f, -0.129219f, 0.173524f, - 0.073972f, -0.189045f, -0.034523f, -0.106655f, - -0.011843f, -0.197381f, 0.219413f, 0.183197f, - -0.054920f, 0.144955f, 0.036517f, -0.085412f, - -0.229070f, -0.143710f, -0.049486f, 0.156634f, - -0.008673f, -0.064778f, 0.082344f, 0.145673f, - 0.002912f, -0.210121f, -0.116564f, 0.078425f, - 0.220908f, -0.067594f, 0.048610f, 0.084912f, - -0.066202f, -0.112515f, -0.217767f, -0.082640f, - -0.017414f, 0.230265f, -0.070735f, 0.066073f, - 0.215256f, 0.071157f, -0.087220f, -0.202235f, - -0.011918f, 0.099562f, 0.174716f, -0.063845f, - -0.121055f, 0.014367f, 0.132709f, -0.005060f, - -0.244606f, -0.179693f, -0.134690f, 0.023239f, - -0.193116f, -0.076975f, -0.021164f, -0.001938f, - -0.163799f, -0.111437f, -0.210362f, -0.166376f, - 0.034754f, 0.010036f, -0.021917f, 0.068014f, - -0.086893f, -0.251746f, -0.267171f, 0.037383f, - 0.003966f, 0.033571f, -0.151506f, 0.025437f, - -0.020626f, -0.308454f, -0.343143f, -0.092263f, - -0.026261f, -0.028345f, 0.036036f, 0.035169f, - 0.129470f, 0.122205f, 0.015661f, -0.070612f, - -0.094333f, -0.066055f, -0.041083f, 0.159146f, - 0.073184f, 0.110044f, 0.174471f, 0.078069f, - -0.014881f, 0.008116f, 0.013209f, 0.075857f, - 0.195605f, 0.062714f, 0.067955f, 0.056544f, - -0.153908f, -0.141749f, -0.072550f, 0.033523f, - -0.024665f, 0.134487f, 0.079076f, 0.133562f, - 0.227130f, 0.018054f, 0.004928f, 0.169162f, - 0.065152f, 0.072160f, 0.131631f, 0.096303f, - 0.054288f, 0.106256f, 0.114632f, 0.119038f, - 0.515200f, 0.247429f, 0.199134f, 0.211957f, - 0.127558f, -0.294684f, -0.194890f, -0.049988f, - -0.112247f, -0.008122f, -0.006176f, 0.037035f, - -0.110881f, -0.249989f, 0.152434f, 0.234621f, - 0.153340f, 0.349283f, 0.683049f, 0.157174f, - 0.124844f, 0.099136f, 0.064407f, -0.248400f, - -0.155323f, -0.026498f, -0.023450f, 0.049051f, - -0.114187f, 0.007195f, -0.176825f, -0.376926f, - 0.366159f, -0.179938f, -0.148508f, 0.006043f, - 0.170048f, 0.097866f, -0.102658f, -0.260430f, - 0.248868f, 0.037019f, -0.118111f, 0.078176f, - 0.194171f, 0.211328f, 0.368612f, 0.361213f, - 0.130013f, 0.094650f, 0.227396f, -0.178058f, - -0.114782f, -0.008093f, 0.231080f, -0.011843f, - -0.097917f, -0.325788f, 0.141879f, 0.119738f, - -0.230427f, -0.117419f, -0.114153f, 0.037903f, - 0.116383f, 0.218773f, -0.101884f, 0.059466f, - 0.119255f, 0.010874f, -0.031449f, 0.045996f, - 0.119931f, 0.273760f, 0.311700f, 0.261794f, - 0.194809f, 0.339829f, 0.239449f, 0.064140f, - 0.077597f, 0.098996f, 0.143534f, 0.184602f, - 0.037507f, 0.225494f, 0.096142f, -0.147370f, - -0.207833f, -0.174742f, -0.086391f, -0.038942f, - 0.159577f, -0.088492f, -0.000989f, 0.108154f, - -0.025890f, -0.072713f, 0.025997f, -0.006803f, - -0.086879f, -0.011290f, -0.269200f, -0.103450f, - -0.124910f, -0.116340f, 0.141459f, 0.208800f, - 0.042268f, 0.265034f, 0.516474f, 0.217591f, - -0.018843f, -0.313328f, -0.168363f, 0.047129f, - 0.090480f, -0.109852f, -0.018761f, 0.210669f, - 0.281269f, -0.043591f, -0.034147f, -0.237772f, - -0.134843f, -0.072481f, -0.103831f, 0.038355f, - 0.308619f, 0.148023f, -0.045867f, -0.123950f, - -0.210860f, -0.064973f, -0.036308f, -0.046731f, - -0.022099f, 0.095776f, 0.409423f, 0.060635f, - -0.065196f, 0.051828f, 0.027981f, -0.009609f, - -0.137681f, -0.095011f, -0.019045f, 0.177278f, - 0.009759f, -0.092119f, -0.016958f, -0.133860f, - -0.118421f, -0.032039f, -0.006214f, -0.084541f, - 0.063971f, -0.073642f, 0.165676f, 0.110443f, - 0.044131f, 0.046568f, 0.053292f, -0.055466f, - 0.015512f, 0.371947f, 0.232102f, -0.016923f, - 0.103979f, -0.091758f, 0.005907f, 0.209100f, - 0.157433f, 0.030518f, 0.250366f, 0.062322f, - 0.036720f, 0.094676f, 0.017306f, -0.010328f, - -0.079012f, 0.016781f, -0.112435f, 0.061795f, - 0.042543f, -0.126799f, -0.009975f, -0.056760f, - 0.046424f, -0.194712f, -0.139399f, -0.037731f, - 0.157989f, -0.016261f, 0.123345f, 0.230563f, - 0.083300f, -0.016392f, 0.059567f, -0.016035f, - -0.064767f, 0.231945f, 0.156629f, 0.034602f, - 0.145628f, 0.041315f, 0.034535f, 0.019967f, - -0.089188f, -0.012091f, 0.307857f, 0.211405f, - -0.025091f, -0.148249f, -0.129384f, 0.063536f, - -0.068603f, -0.067941f, -0.035104f, 0.210832f, - 0.063810f, 0.062764f, -0.089889f, -0.030554f, - 0.014791f, -0.053362f, -0.037818f, -0.196640f, - 0.008388f, -0.082654f, 0.143056f, 0.064221f, - 0.069795f, 0.191040f, 0.097321f, -0.028679f, - 0.075794f, 0.313154f, 0.086240f, 0.207643f, - 0.017809f, 0.122867f, 0.224586f, 0.167403f, - -0.023884f, 0.047434f, 0.344091f, 0.187745f, - 0.136177f, 0.141738f, 0.063799f, 0.045233f, - -0.077342f, -0.003525f, -0.165041f, -0.025616f, - -0.073745f, 0.164439f, 0.011200f, -0.145896f, - -0.027954f, -0.061987f, -0.039874f, -0.142775f, - 0.151042f, -0.038238f, 0.053152f, 0.078615f, - 0.086061f, 0.100593f, 0.128046f, -0.071006f, - -0.116558f, 0.208445f, 0.051086f, 0.076843f, - 0.023191f, -0.084781f, -0.011790f, 0.147807f, - -0.048554f, -0.113932f, 0.283322f, 0.190934f, - 0.092789f, 0.033018f, -0.142428f, -0.142480f, - -0.099023f, -0.041020f, -0.042760f, 0.203295f, - -0.053475f, 0.042424f, 0.222839f, -0.019167f, - -0.133176f, -0.276216f, -0.031998f, 0.117290f, - 0.177827f, -0.059973f, -0.064744f, -0.117040f, - -0.155482f, -0.099531f, 0.164121f, -0.026682f, - -0.093810f, 0.238993f, -0.006506f, 0.007830f, - 0.065819f, -0.203643f, -0.100925f, -0.053652f, - -0.130770f, 0.026277f, 0.131796f, 0.032742f, - 0.127186f, 0.116694f, -0.161122f, -0.279773f, - -0.252515f, -0.002638f, 0.042812f, 0.096776f, - -0.123280f, 0.064858f, -0.010455f, -0.219760f, - -0.239331f, -0.104363f, -0.058022f, -0.053584f, - 0.025611f, 0.005129f, -0.100418f, -0.045712f, - -0.194418f, -0.126366f, -0.030530f, 0.051168f, - 0.215959f, 0.172402f, -0.054700f, -0.185995f, - -0.278360f, -0.193693f, -0.040309f, 0.003735f, - -0.007770f, 0.123556f, 0.190179f, -0.077315f, - 0.117403f, 0.212942f, 0.012160f, 0.000113f, - 0.027331f, 0.040202f, 0.033293f, 0.219438f, - 0.184174f, 0.259349f, 0.311206f, 0.082547f, - -0.047875f, -0.078417f, 0.010746f, 0.082620f, - 0.311931f, 0.307605f, 0.003863f, 0.021405f, - -0.026388f, -0.019572f, 0.020582f, -0.059353f, - 0.025199f, 0.261319f, 0.086316f, 0.143614f, - 0.107780f, 0.003900f, -0.188397f, -0.038563f, - -0.106045f, -0.125154f, -0.010509f, 0.054021f, - 0.242130f, 0.279152f, 0.215546f, 0.346995f, - 0.440856f, 0.237452f, 0.234154f, 0.301646f, - 0.168929f, -0.208358f, -0.126848f, 0.010260f, - 0.121018f, -0.062975f, -0.052848f, 0.050341f, - -0.061103f, -0.266482f, 0.107186f, 0.140221f, - 0.280065f, 0.287889f, 0.373198f, 0.151596f, - 0.013593f, 0.115616f, 0.014616f, -0.281710f, - -0.237597f, -0.117305f, -0.000034f, -0.136739f, - -0.196275f, -0.095225f, -0.125310f, -0.250514f, - 0.236804f, -0.071805f, -0.037421f, 0.048230f, - 0.321596f, 0.063632f, 0.024039f, -0.029133f, - 0.230983f, 0.160593f, -0.154355f, -0.013086f, - -0.079929f, 0.094692f, 0.160391f, 0.180239f, - 0.053895f, 0.100759f, 0.288631f, 0.038191f, - 0.181692f, 0.229682f, 0.440166f, 0.063401f, - 0.006273f, 0.020865f, 0.338695f, 0.256244f, - -0.043927f, 0.115617f, 0.003296f, 0.173965f, - 0.021318f, -0.040936f, -0.118932f, 0.182380f, - 0.235922f, -0.053233f, -0.015053f, -0.101057f, - 0.095341f, 0.051111f, 0.161831f, 0.032614f, - 0.159496f, 0.072375f, 0.025089f, 0.023748f, - 0.029151f, 0.161284f, -0.117717f, -0.036191f, - -0.176822f, -0.162006f, 0.226542f, -0.078329f, - 0.043079f, -0.119172f, 0.054614f, -0.101365f, - -0.064541f, -0.115304f, 0.135170f, 0.298872f, - 0.098060f, 0.089428f, -0.007497f, 0.110391f, - -0.028824f, 0.020835f, -0.036804f, 0.125411f, - 0.192105f, -0.048931f, 0.003086f, -0.010681f, - 0.074698f, -0.016263f, 0.096063f, 0.060267f, - -0.007277f, 0.139139f, -0.080635f, 0.036628f, - 0.086058f, 0.131979f, 0.085707f, 0.025301f, - 0.226094f, 0.194759f, 0.042193f, -0.157846f, - -0.068402f, -0.141450f, -0.112659f, -0.076305f, - -0.069085f, -0.114332f, -0.102005f, 0.132193f, - -0.067042f, 0.106643f, 0.198964f, 0.171616f, - 0.167237f, -0.033730f, -0.026755f, 0.083621f, - 0.149459f, -0.002799f, -0.000318f, 0.011753f, - 0.065889f, -0.089375f, -0.049610f, 0.224579f, - 0.216548f, -0.034908f, -0.017851f, -0.088144f, - 0.007530f, 0.240268f, 0.073270f, 0.013263f, - 0.175323f, 0.012082f, 0.093993f, 0.015282f, - 0.105854f, 0.107990f, 0.077798f, -0.096166f, - -0.079607f, 0.177820f, 0.142392f, 0.033337f, - -0.078100f, -0.081616f, -0.046993f, 0.139459f, - 0.020272f, -0.123161f, 0.175269f, 0.105217f, - 0.057328f, 0.080909f, -0.012612f, -0.097081f, - 0.082060f, -0.096716f, -0.063921f, 0.201884f, - 0.128166f, -0.035051f, -0.032227f, -0.068139f, - -0.115915f, 0.095080f, -0.086007f, -0.067543f, - 0.030776f, 0.032712f, 0.088937f, 0.054336f, - -0.039329f, -0.114022f, 0.171672f, -0.112321f, - -0.217646f, 0.065186f, 0.060223f, 0.192174f, - 0.055580f, -0.131107f, -0.144338f, 0.056730f, - -0.034707f, -0.081616f, -0.135298f, -0.000614f, - 0.087189f, 0.014614f, 0.067709f, 0.107689f, - 0.225780f, 0.084361f, -0.008544f, 0.051649f, - -0.048369f, -0.037739f, -0.060710f, 0.002654f, - 0.016935f, 0.085563f, -0.015961f, -0.019265f, - 0.111788f, 0.062376f, 0.202019f, 0.047713f, - 0.042261f, 0.069716f, 0.242913f, 0.021052f, - -0.072812f, -0.155920f, -0.026436f, 0.035621f, - -0.079300f, -0.028787f, -0.048329f, 0.084718f, - -0.060565f, -0.083750f, -0.164075f, -0.040742f, - -0.086219f, 0.015271f, -0.005204f, -0.016038f, - 0.045816f, -0.050433f, -0.077652f, 0.117109f, - 0.009611f, -0.009045f, -0.008634f, -0.055373f, - -0.085968f, 0.028527f, -0.054736f, -0.168089f, - 0.175839f, 0.071205f, -0.023603f, 0.037907f, - -0.004561f, -0.022634f, 0.123831f, 0.094469f, - -0.072920f, -0.133642f, -0.014032f, -0.142754f, - -0.026999f, -0.199409f, 0.013268f, 0.226989f, - 0.048650f, -0.170988f, -0.050141f, 0.007880f, - 0.061880f, 0.019078f, -0.043578f, -0.038139f, - 0.134814f, 0.054097f, -0.081670f, 0.176838f, - 0.047920f, -0.038176f, 0.050406f, -0.107181f, - -0.036279f, 0.027060f, 0.081594f, -0.002820f, - 0.090507f, -0.033338f, -0.059571f, 0.013404f, - -0.099860f, 0.073371f, 0.342805f, 0.098305f, - -0.150910f, -0.020822f, -0.056960f, 0.046262f, - -0.043413f, -0.149405f, -0.129105f, -0.010899f, - -0.014229f, -0.179949f, -0.113044f, -0.049468f, - -0.065513f, 0.090269f, -0.011919f, 0.087846f, - 0.095796f, 0.146127f, 0.101599f, 0.078066f, - -0.084348f, -0.100002f, -0.020134f, -0.050169f, - 0.062122f, 0.014640f, 0.019143f, 0.036543f, - 0.180924f, -0.013976f, -0.066768f, -0.001090f, - -0.070419f, -0.004839f, -0.001504f, 0.034483f, - -0.044954f, -0.050336f, -0.088638f, -0.174782f, - -0.116082f, -0.205507f, 0.015587f, -0.042839f, - -0.096879f, -0.144097f, -0.050268f, -0.196796f, - 0.109639f, 0.271411f, 0.173732f, 0.108070f, - 0.156437f, 0.124255f, 0.097242f, 0.238693f, - 0.083941f, 0.109105f, 0.223940f, 0.267188f, - 0.027385f, 0.025819f, 0.125070f, 0.093738f, - 0.040353f, 0.038645f, -0.012730f, 0.144063f, - 0.052931f, -0.009138f, 0.084193f, 0.160272f, - -0.041366f, 0.011951f, -0.121446f, -0.106713f, - -0.047566f, 0.047984f, -0.255224f, -0.076116f, - 0.098685f, -0.150845f, -0.171513f, -0.156590f, - 0.058331f, 0.187493f, 0.413018f, 0.554265f, - 0.372242f, 0.237943f, 0.124571f, 0.110829f, - 0.010322f, -0.174477f, -0.067627f, -0.001979f, - 0.142913f, 0.040597f, 0.019907f, 0.025963f, - -0.043585f, -0.120732f, 0.099937f, 0.091059f, - 0.247307f, 0.204226f, -0.042753f, -0.068580f, - -0.119002f, 0.026722f, 0.034853f, -0.060934f, - -0.025054f, -0.093026f, -0.035372f, -0.233209f, - -0.049869f, -0.039151f, -0.022279f, -0.065380f, - -9.063785f}; - return std::vector(detector, detector + sizeof(detector)/sizeof(detector[0])); -} - -class HOGConfInvoker : - public ParallelLoopBody -{ -public: - HOGConfInvoker( const HOGDescriptor* _hog, const Mat& _img, - double _hitThreshold, const Size& _padding, - std::vector* locs, - std::vector* _vec, Mutex* _mtx ) - { - hog = _hog; - img = _img; - hitThreshold = _hitThreshold; - padding = _padding; - locations = locs; - vec = _vec; - mtx = _mtx; - } - - void operator()(const Range& range) const CV_OVERRIDE + void HOGDescriptor::compute(InputArray _img, std::vector& descriptors, + Size winStride, Size padding, const std::vector& locations) const { CV_INSTRUMENT_REGION(); - int i, i1 = range.start, i2 = range.end; + if (winStride == Size()) + winStride = cellSize; + Size cacheStride(gcd(winStride.width, blockStride.width), + gcd(winStride.height, blockStride.height)); - Size maxSz(cvCeil(img.cols/(*locations)[0].scale), cvCeil(img.rows/(*locations)[0].scale)); - Mat smallerImgBuf(maxSz, img.type()); - std::vector dets; + Size imgSize = _img.size(); - for( i = i1; i < i2; i++ ) + size_t nwindows = locations.size(); + padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width); + padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height); + Size paddedImgSize(imgSize.width + padding.width*2, imgSize.height + padding.height*2); + + CV_OCL_RUN(_img.dims() <= 2 && _img.type() == CV_8UC1 && _img.isUMat(), + ocl_compute(_img, winStride, descriptors, DESCR_FORMAT_COL_BY_COL, blockSize, + cellSize, nbins, blockStride, winSize, (float)getWinSigma(), gammaCorrection, L2HysThreshold, signedGradient)) + + Mat img = _img.getMat(); + HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride); + + if (!nwindows) + nwindows = cache.windowsInImage(paddedImgSize, winStride).area(); + + const HOGCache::BlockData* blockData = &cache.blockData[0]; + + int nblocks = cache.nblocks.area(); + int blockHistogramSize = cache.blockHistogramSize; + size_t dsize = getDescriptorSize(); + descriptors.resize(dsize*nwindows); + + // for each window + for (size_t i = 0; i < nwindows; i++) { - double scale = (*locations)[i].scale; + float* descriptor = &descriptors[i*dsize]; - Size sz(cvRound(img.cols / scale), cvRound(img.rows / scale)); - Mat smallerImg(sz, img.type(), smallerImgBuf.ptr()); - - if( sz == img.size() ) - smallerImg = Mat(sz, img.type(), img.data, img.step); - else - resize(img, smallerImg, sz, 0, 0, INTER_LINEAR_EXACT); - - hog->detectROI(smallerImg, (*locations)[i].locations, dets, (*locations)[i].confidences, hitThreshold, Size(), padding); - Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); - mtx->lock(); - for( size_t j = 0; j < dets.size(); j++ ) - vec->push_back(Rect(cvRound(dets[j].x*scale), - cvRound(dets[j].y*scale), - scaledWinSize.width, scaledWinSize.height)); - mtx->unlock(); - } - } - - const HOGDescriptor* hog; - Mat img; - double hitThreshold; - std::vector* locations; - Size padding; - std::vector* vec; - Mutex* mtx; -}; - -void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector &locations, - CV_OUT std::vector& foundLocations, CV_OUT std::vector& confidences, - double hitThreshold, cv::Size winStride, cv::Size padding) const -{ - CV_INSTRUMENT_REGION(); - - foundLocations.clear(); - confidences.clear(); - - if( svmDetector.empty() || locations.empty()) - return; - - if( winStride == Size() ) - winStride = cellSize; - Size cacheStride(gcd(winStride.width, blockStride.width), - gcd(winStride.height, blockStride.height)); - - size_t nwindows = locations.size(); - padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width); - padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height); - Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2); - - // HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride); - HOGCache cache(this, img, padding, padding, true, cacheStride); - if( !nwindows ) - nwindows = cache.windowsInImage(paddedImgSize, winStride).area(); - - const HOGCache::BlockData* blockData = &cache.blockData[0]; - - int nblocks = cache.nblocks.area(); - int blockHistogramSize = cache.blockHistogramSize; - size_t dsize = getDescriptorSize(); - - double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0; - std::vector blockHist(blockHistogramSize); - -#if CV_SIMD128 - float partSum[4]; -#endif - - for( size_t i = 0; i < nwindows; i++ ) - { - Point pt0; - pt0 = locations[i]; - if( pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width || - pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height ) - { - // out of image - confidences.push_back(-10.0); - continue; - } - - double s = rho; - const float* svmVec = &svmDetector[0]; - int j, k; - - for( j = 0; j < nblocks; j++, svmVec += blockHistogramSize ) - { - const HOGCache::BlockData& bj = blockData[j]; - Point pt = pt0 + bj.imgOffset; - - // need to divide this into 4 parts! - const float* vec = cache.getBlock(pt, &blockHist[0]); -#if CV_SIMD128 - v_float32x4 _vec = v_load(vec); - v_float32x4 _svmVec = v_load(svmVec); - v_float32x4 sum = _svmVec * _vec; - - for( k = 4; k <= blockHistogramSize - 4; k += 4 ) + Point pt0; + if (!locations.empty()) { - _vec = v_load(vec + k); - _svmVec = v_load(svmVec + k); - - sum += _vec * _svmVec; + pt0 = locations[i]; + if (pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width || + pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height) + continue; + } + else + { + pt0 = cache.getWindow(paddedImgSize, winStride, (int)i).tl() - Point(padding); +// CV_Assert(pt0.x % cacheStride.width == 0 && pt0.y % cacheStride.height == 0); } - v_store(partSum, sum); + for (int j = 0; j < nblocks; j++) + { + const HOGCache::BlockData& bj = blockData[j]; + Point pt = pt0 + bj.imgOffset; - double t0 = partSum[0] + partSum[1]; - double t1 = partSum[2] + partSum[3]; - s += t0 + t1; -#else - for( k = 0; k <= blockHistogramSize - 4; k += 4 ) - s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] + - vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3]; -#endif - for( ; k < blockHistogramSize; k++ ) - s += vec[k]*svmVec[k]; + float* dst = descriptor + bj.histOfs; + const float* src = cache.getBlock(pt, dst); + if (src != dst) + memcpy(dst, src, blockHistogramSize * sizeof(float)); + } } - confidences.push_back(s); - - if( s >= hitThreshold ) - foundLocations.push_back(pt0); } -} -void HOGDescriptor::detectMultiScaleROI(const cv::Mat& img, - CV_OUT std::vector& foundLocations, std::vector& locations, - double hitThreshold, int groupThreshold) const -{ - CV_INSTRUMENT_REGION(); - - std::vector allCandidates; - Mutex mtx; - - parallel_for_(Range(0, (int)locations.size()), - HOGConfInvoker(this, img, hitThreshold, Size(8, 8), - &locations, &allCandidates, &mtx)); - - foundLocations.resize(allCandidates.size()); - std::copy(allCandidates.begin(), allCandidates.end(), foundLocations.begin()); - cv::groupRectangles(foundLocations, groupThreshold, 0.2); -} - -void HOGDescriptor::readALTModel(String modelfile) -{ - // read model from SVMlight format.. - FILE *modelfl; - if ((modelfl = fopen(modelfile.c_str(), "rb")) == NULL) + void HOGDescriptor::detect(const Mat& img, + std::vector& hits, std::vector& weights, double hitThreshold, + Size winStride, Size padding, const std::vector& locations) const { - String eerr("file not exist"); - String efile(__FILE__); - String efunc(__FUNCTION__); - throw Exception(Error::StsError, eerr, efile, efunc, __LINE__); + CV_INSTRUMENT_REGION(); + + hits.clear(); + weights.clear(); + if (svmDetector.empty()) + return; + + if (winStride == Size()) + winStride = cellSize; + Size cacheStride(gcd(winStride.width, blockStride.width), + gcd(winStride.height, blockStride.height)); + + size_t nwindows = locations.size(); + padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width); + padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height); + Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2); + + HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride); + + if (!nwindows) + nwindows = cache.windowsInImage(paddedImgSize, winStride).area(); + + const HOGCache::BlockData* blockData = &cache.blockData[0]; + + int nblocks = cache.nblocks.area(); + int blockHistogramSize = cache.blockHistogramSize; + size_t dsize = getDescriptorSize(); + + double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0; + std::vector blockHist(blockHistogramSize); + +#if CV_SIMD128 + float partSum[4]; +#endif + + for (size_t i = 0; i < nwindows; i++) + { + Point pt0; + if (!locations.empty()) + { + pt0 = locations[i]; + if (pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width || + pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height) + continue; + } + else + { + pt0 = cache.getWindow(paddedImgSize, winStride, (int)i).tl() - Point(padding); + CV_Assert(pt0.x % cacheStride.width == 0 && pt0.y % cacheStride.height == 0); + } + double s = rho; + const float* svmVec = &svmDetector[0]; + + int j, k; + for (j = 0; j < nblocks; j++, svmVec += blockHistogramSize) + { + const HOGCache::BlockData& bj = blockData[j]; + Point pt = pt0 + bj.imgOffset; + + const float* vec = cache.getBlock(pt, &blockHist[0]); +#if CV_SIMD128 + v_float32x4 _vec = v_load(vec); + v_float32x4 _svmVec = v_load(svmVec); + v_float32x4 sum = _svmVec * _vec; + + for (k = 4; k <= blockHistogramSize - 4; k += 4) + { + _vec = v_load(vec + k); + _svmVec = v_load(svmVec + k); + + sum += _vec * _svmVec; + } + + v_store(partSum, sum); + double t0 = partSum[0] + partSum[1]; + double t1 = partSum[2] + partSum[3]; + s += t0 + t1; +#else + for (k = 0; k <= blockHistogramSize - 4; k += 4) + s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] + + vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3]; +#endif + for ( ; k < blockHistogramSize; k++) + s += vec[k]*svmVec[k]; + } + if (s >= hitThreshold) + { + hits.push_back(pt0); + weights.push_back(s); + } + } } - char version_buffer[10]; - if (!fread (&version_buffer,sizeof(char),10,modelfl)) + + void HOGDescriptor::detect(const Mat& img, std::vector& hits, double hitThreshold, + Size winStride, Size padding, const std::vector& locations) const { - String eerr("version?"); - String efile(__FILE__); - String efunc(__FUNCTION__); - fclose(modelfl); + CV_INSTRUMENT_REGION(); - throw Exception(Error::StsError, eerr, efile, efunc, __LINE__); + std::vector weightsV; + detect(img, hits, weightsV, hitThreshold, winStride, padding, locations); } - if(strcmp(version_buffer,"V6.01")) { - String eerr("version does not match"); - String efile(__FILE__); - String efunc(__FUNCTION__); - fclose(modelfl); - throw Exception(Error::StsError, eerr, efile, efunc, __LINE__); - } - /* read version number */ - int version = 0; - if (!fread (&version,sizeof(int),1,modelfl)) + class HOGInvoker : + public ParallelLoopBody { - fclose(modelfl); - throw Exception(); - } - if (version < 200) + public: + HOGInvoker( const HOGDescriptor* _hog, const Mat& _img, + double _hitThreshold, const Size& _winStride, const Size& _padding, + const double* _levelScale, std::vector * _vec, Mutex* _mtx, + std::vector* _weights=0, std::vector* _scales=0 ) + { + hog = _hog; + img = _img; + hitThreshold = _hitThreshold; + winStride = _winStride; + padding = _padding; + levelScale = _levelScale; + vec = _vec; + weights = _weights; + scales = _scales; + mtx = _mtx; + } + + void operator()(const Range& range) const CV_OVERRIDE + { + int i, i1 = range.start, i2 = range.end; + double minScale = i1 > 0 ? levelScale[i1] : i2 > 1 ? levelScale[i1+1] : std::max(img.cols, img.rows); + Size maxSz(cvCeil(img.cols/minScale), cvCeil(img.rows/minScale)); + Mat smallerImgBuf(maxSz, img.type()); + std::vector locations; + std::vector hitsWeights; + + for (i = i1; i < i2; i++) + { + double scale = levelScale[i]; + Size sz(cvRound(img.cols/scale), cvRound(img.rows/scale)); + Mat smallerImg(sz, img.type(), smallerImgBuf.ptr()); + if (sz == img.size()) + smallerImg = Mat(sz, img.type(), img.data, img.step); + else + resize(img, smallerImg, sz, 0, 0, INTER_LINEAR_EXACT); + hog->detect(smallerImg, locations, hitsWeights, hitThreshold, winStride, padding); + Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); + + mtx->lock(); + for (size_t j = 0; j < locations.size(); j++) + { + vec->push_back(Rect(cvRound(locations[j].x*scale), + cvRound(locations[j].y*scale), + scaledWinSize.width, scaledWinSize.height)); + if (scales) + scales->push_back(scale); + } + mtx->unlock(); + + if (weights && (!hitsWeights.empty())) + { + mtx->lock(); + for (size_t j = 0; j < locations.size(); j++) + weights->push_back(hitsWeights[j]); + mtx->unlock(); + } + } + } + + private: + const HOGDescriptor* hog; + Mat img; + double hitThreshold; + Size winStride; + Size padding; + const double* levelScale; + std::vector* vec; + std::vector* weights; + std::vector* scales; + Mutex* mtx; + }; + +#ifdef HAVE_OPENCL + + static bool ocl_classify_hists(int win_height, int win_width, int block_stride_y, int block_stride_x, + int win_stride_y, int win_stride_x, int height, int width, + const UMat& block_hists, UMat detector, + float free_coef, float threshold, UMat& labels, Size descr_size, int block_hist_size) { - String eerr("version does not match"); - String efile(__FILE__); - String efunc(__FUNCTION__); - fclose(modelfl); - throw Exception(); - } - int kernel_type; - size_t nread; - nread=fread(&(kernel_type),sizeof(int),1,modelfl); + int nthreads; + bool is_cpu = cv::ocl::Device::getDefault().type() == cv::ocl::Device::TYPE_CPU; + cv::String opts; - {// ignore these - int poly_degree; - nread=fread(&(poly_degree),sizeof(int),1,modelfl); + ocl::Kernel k; + int idx = 0; + switch (descr_size.width) + { + case 180: + nthreads = 180; + k.create("classify_hists_180_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32"); + if (k.empty()) + return false; + if (is_cpu) + opts = "-D CPU "; + else + opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); + k.create("classify_hists_180_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); + if (k.empty()) + return false; + idx = k.set(idx, descr_size.width); + idx = k.set(idx, descr_size.height); + break; - double rbf_gamma; - nread=fread(&(rbf_gamma),sizeof(double), 1, modelfl); - double coef_lin; - nread=fread(&(coef_lin),sizeof(double),1,modelfl); - double coef_const; - nread=fread(&(coef_const),sizeof(double),1,modelfl); - int l; - nread=fread(&l,sizeof(int),1,modelfl); - CV_Assert(l >= 0 && l < 0xFFFF); - char* custom = new char[l]; - nread=fread(custom,sizeof(char),l,modelfl); - delete[] custom; - } - int totwords; - nread=fread(&(totwords),sizeof(int),1,modelfl); - {// ignore these - int totdoc; - nread=fread(&(totdoc),sizeof(int),1,modelfl); - int sv_num; - nread=fread(&(sv_num), sizeof(int),1,modelfl); + case 252: + nthreads = 256; + k.create("classify_hists_252_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32"); + if (k.empty()) + return false; + if (is_cpu) + opts = "-D CPU "; + else + opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); + k.create("classify_hists_252_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); + if (k.empty()) + return false; + idx = k.set(idx, descr_size.width); + idx = k.set(idx, descr_size.height); + break; + + default: + nthreads = 256; + k.create("classify_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, "-D WAVE_SIZE=32"); + if (k.empty()) + return false; + if (is_cpu) + opts = "-D CPU "; + else + opts = cv::format("-D WAVE_SIZE=%d", k.preferedWorkGroupSizeMultiple()); + k.create("classify_hists_kernel", ocl::objdetect::objdetect_hog_oclsrc, opts); + if (k.empty()) + return false; + idx = k.set(idx, descr_size.area()); + idx = k.set(idx, descr_size.height); + } + + int win_block_stride_x = win_stride_x / block_stride_x; + int win_block_stride_y = win_stride_y / block_stride_y; + int img_win_width = (width - win_width + win_stride_x) / win_stride_x; + int img_win_height = (height - win_height + win_stride_y) / win_stride_y; + int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / + block_stride_x; + + size_t globalThreads[3] = { (size_t)img_win_width * nthreads, (size_t)img_win_height, 1 }; + size_t localThreads[3] = { (size_t)nthreads, 1, 1 }; + + idx = k.set(idx, block_hist_size); + idx = k.set(idx, img_win_width); + idx = k.set(idx, img_block_width); + idx = k.set(idx, win_block_stride_x); + idx = k.set(idx, win_block_stride_y); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(block_hists)); + idx = k.set(idx, ocl::KernelArg::PtrReadOnly(detector)); + idx = k.set(idx, free_coef); + idx = k.set(idx, threshold); + idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(labels)); + + return k.run(2, globalThreads, localThreads, false); } - double linearbias; - nread=fread(&linearbias, sizeof(double), 1, modelfl); + static bool ocl_detect(InputArray img, std::vector &hits, double hit_threshold, Size win_stride, + const UMat& oclSvmDetector, Size blockSize, Size cellSize, int nbins, Size blockStride, Size winSize, + bool gammaCorrection, double L2HysThreshold, float sigma, float free_coef, bool signedGradient) + { + hits.clear(); + if (oclSvmDetector.empty()) + return false; - std::vector detector; - detector.clear(); - if(kernel_type == 0) { /* linear kernel */ - /* save linear wts also */ - CV_Assert(totwords + 1 > 0 && totwords < 0xFFFF); - double *linearwt = new double[totwords+1]; - int length = totwords; - nread = fread(linearwt, sizeof(double), totwords + 1, modelfl); - if(nread != static_cast(length) + 1) { - delete [] linearwt; + Size imgSize = img.size(); + Size effect_size = imgSize; + UMat grad(imgSize, CV_32FC2); + int qangle_type = ocl::Device::getDefault().isIntel() ? CV_32SC2 : CV_8UC2; + UMat qangle(imgSize, qangle_type); + + const size_t block_hist_size = getBlockHistogramSize(blockSize, cellSize, nbins); + const Size blocks_per_img = numPartsWithin(imgSize, blockSize, blockStride); + UMat block_hists(1, static_cast(block_hist_size * blocks_per_img.area()) + 256, CV_32F); + + Size wins_per_img = numPartsWithin(imgSize, winSize, win_stride); + UMat labels(1, wins_per_img.area(), CV_8U); + + float scale = 1.f / (2.f * sigma * sigma); + Mat gaussian_lut(1, 512, CV_32FC1); + int idx = 0; + for (int i=-8; i<8; i++) + for (int j=-8; j<8; j++) + gaussian_lut.at(idx++) = std::exp(-(j * j + i * i) * scale); + for (int i=-8; i<8; i++) + for (int j=-8; j<8; j++) + gaussian_lut.at(idx++) = (8.f - fabs(j + 0.5f)) * (8.f - fabs(i + 0.5f)) / 64.f; + + if (!ocl_computeGradient(img, grad, qangle, nbins, effect_size, gammaCorrection, signedGradient)) + return false; + + UMat gauss_w_lut; + gaussian_lut.copyTo(gauss_w_lut); + if (!ocl_compute_hists(nbins, blockStride.width, blockStride.height, effect_size.height, + effect_size.width, grad, qangle, gauss_w_lut, block_hists, block_hist_size)) + return false; + + if (!ocl_normalize_hists(nbins, blockStride.width, blockStride.height, effect_size.height, + effect_size.width, block_hists, (float)L2HysThreshold)) + return false; + + Size blocks_per_win = numPartsWithin(winSize, blockSize, blockStride); + + Size descr_size((int)block_hist_size*blocks_per_win.width, blocks_per_win.height); + + if (!ocl_classify_hists(winSize.height, winSize.width, blockStride.height, + blockStride.width, win_stride.height, win_stride.width, + effect_size.height, effect_size.width, block_hists, oclSvmDetector, + free_coef, (float)hit_threshold, labels, descr_size, (int)block_hist_size)) + return false; + + Mat labels_host = labels.getMat(ACCESS_READ); + unsigned char *vec = labels_host.ptr(); + for (int i = 0; i < wins_per_img.area(); i++) + { + int y = i / wins_per_img.width; + int x = i - wins_per_img.width * y; + if (vec[i]) + { + hits.push_back(Point(x * win_stride.width, y * win_stride.height)); + } + } + return true; + } + + static bool ocl_detectMultiScale(InputArray _img, std::vector &found_locations, std::vector& level_scale, + double hit_threshold, Size win_stride, double group_threshold, + const UMat& oclSvmDetector, Size blockSize, Size cellSize, + int nbins, Size blockStride, Size winSize, bool gammaCorrection, + double L2HysThreshold, float sigma, float free_coef, bool signedGradient) + { + std::vector all_candidates; + std::vector locations; + UMat image_scale; + Size imgSize = _img.size(); + image_scale.create(imgSize, _img.type()); + + for (size_t i = 0; i& foundLocations, std::vector& foundWeights, + double hitThreshold, Size winStride, Size padding, + double scale0, double finalThreshold, bool useMeanshiftGrouping) const + { + CV_INSTRUMENT_REGION(); + + double scale = 1.; + int levels = 0; + + Size imgSize = _img.size(); + std::vector levelScale; + for (levels = 0; levels < nlevels; levels++) + { + levelScale.push_back(scale); + if (cvRound(imgSize.width/scale) < winSize.width || + cvRound(imgSize.height/scale) < winSize.height || + scale0 <= 1) + break; + scale *= scale0; + } + levels = std::max(levels, 1); + levelScale.resize(levels); + + if (winStride == Size()) + winStride = blockStride; + + CV_OCL_RUN(_img.dims() <= 2 && _img.type() == CV_8UC1 && scale0 > 1 && winStride.width % blockStride.width == 0 && + winStride.height % blockStride.height == 0 && padding == Size(0,0) && _img.isUMat(), + ocl_detectMultiScale(_img, foundLocations, levelScale, hitThreshold, winStride, finalThreshold, oclSvmDetector, + blockSize, cellSize, nbins, blockStride, winSize, gammaCorrection, L2HysThreshold, (float)getWinSigma(), free_coef, signedGradient)); + + std::vector allCandidates; + std::vector tempScales; + std::vector tempWeights; + std::vector foundScales; + + Mutex mtx; + Mat img = _img.getMat(); + Range range(0, (int)levelScale.size()); + HOGInvoker invoker(this, img, hitThreshold, winStride, padding, &levelScale[0], &allCandidates, &mtx, &tempWeights, &tempScales); + parallel_for_(range, invoker); + + std::copy(tempScales.begin(), tempScales.end(), back_inserter(foundScales)); + foundLocations.clear(); + std::copy(allCandidates.begin(), allCandidates.end(), back_inserter(foundLocations)); + foundWeights.clear(); + std::copy(tempWeights.begin(), tempWeights.end(), back_inserter(foundWeights)); + + if (useMeanshiftGrouping) + groupRectangles_meanshift(foundLocations, foundWeights, foundScales, finalThreshold, winSize); + else + groupRectangles(foundLocations, foundWeights, (int)finalThreshold, 0.2); + clipObjects(imgSize, foundLocations, 0, &foundWeights); + } + + void HOGDescriptor::detectMultiScale(InputArray img, std::vector& foundLocations, + double hitThreshold, Size winStride, Size padding, + double scale0, double finalThreshold, bool useMeanshiftGrouping) const + { + CV_INSTRUMENT_REGION(); + + std::vector foundWeights; + detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride, + padding, scale0, finalThreshold, useMeanshiftGrouping); + } + + template struct RTTIImpl + { + public: + static int isInstance(const void* ptr) + { + static _ClsName dummy; + static void* dummyp = &dummy; + union + { + const void* p; + const void** pp; + } a, b; + a.p = dummyp; + b.p = ptr; + return *a.pp == *b.pp; + } + static void release(void** dbptr) + { + if (dbptr && *dbptr) + { + delete (_ClsName*)*dbptr; + *dbptr = 0; + } + } + static void* read(CvFileStorage* fs, CvFileNode* n) + { + FileNode fn(fs, n); + _ClsName* obj = new _ClsName; + if (obj->read(fn)) + return obj; + delete obj; + return 0; + } + + static void write(CvFileStorage* _fs, const char* name, const void* ptr, CvAttrList) + { + if (ptr && _fs) + { + FileStorage fs(_fs, false); + ((const _ClsName*)ptr)->write(fs, String(name)); + } + } + + static void* clone(const void* ptr) + { + if (!ptr) + return 0; + return new _ClsName(*(const _ClsName*)ptr); + } + }; + + typedef RTTIImpl HOGRTTI; + + CvType hog_type( CV_TYPE_NAME_HOG_DESCRIPTOR, HOGRTTI::isInstance, + HOGRTTI::release, HOGRTTI::read, HOGRTTI::write, HOGRTTI::clone); + + std::vector HOGDescriptor::getDefaultPeopleDetector() + { + static const float detector[] = { + 0.05359386f, -0.14721455f, -0.05532170f, 0.05077307f, + 0.11547081f, -0.04268804f, 0.04635834f, -0.05468199f, 0.08232084f, + 0.10424068f, -0.02294518f, 0.01108519f, 0.01378693f, 0.11193510f, + 0.01268418f, 0.08528346f, -0.06309239f, 0.13054633f, 0.08100729f, + -0.05209739f, -0.04315529f, 0.09341384f, 0.11035026f, -0.07596218f, + -0.05517511f, -0.04465296f, 0.02947334f, 0.04555536f, + -3.55954492e-003f, 0.07818956f, 0.07730991f, 0.07890715f, 0.06222893f, + 0.09001380f, -0.03574381f, 0.03414327f, 0.05677258f, -0.04773581f, + 0.03746637f, -0.03521175f, 0.06955440f, -0.03849038f, 0.01052293f, + 0.01736112f, 0.10867710f, 0.08748853f, 3.29739624e-003f, 0.10907028f, + 0.07913758f, 0.10393070f, 0.02091867f, 0.11594022f, 0.13182420f, + 0.09879354f, 0.05362710f, -0.06745391f, -7.01260753e-003f, + 5.24702156e-003f, 0.03236255f, 0.01407916f, 0.02207983f, 0.02537322f, + 0.04547948f, 0.07200756f, 0.03129894f, -0.06274468f, 0.02107014f, + 0.06035208f, 0.08636236f, 4.53164103e-003f, 0.02193363f, 0.02309801f, + 0.05568166f, -0.02645093f, 0.04448695f, 0.02837519f, 0.08975694f, + 0.04461516f, 0.08975355f, 0.07514391f, 0.02306982f, 0.10410084f, + 0.06368385f, 0.05943464f, 4.58420580e-003f, 0.05220337f, 0.06675851f, + 0.08358569f, 0.06712101f, 0.06559004f, -0.03930482f, -9.15936660e-003f, + -0.05897915f, 0.02816453f, 0.05032348f, 0.06780671f, 0.03377650f, + -6.09417039e-004f, -0.01795146f, -0.03083684f, -0.01302475f, + -0.02972313f, 7.88706727e-003f, -0.03525961f, -2.50397739e-003f, + 0.05245084f, 0.11791293f, -0.02167498f, 0.05299332f, 0.06640524f, + 0.05190265f, -8.27316567e-003f, 0.03033127f, 0.05842173f, + -4.01050318e-003f, -6.25105947e-003f, 0.05862958f, -0.02465461f, + 0.05546781f, -0.08228195f, -0.07234028f, 0.04640540f, -0.01308254f, + -0.02506191f, 0.03100746f, -0.04665651f, -0.04591486f, 0.02949927f, + 0.06035462f, 0.02244646f, -0.01698639f, 0.01040041f, 0.01131170f, + 0.05419579f, -0.02130277f, -0.04321722f, -0.03665198f, 0.01126490f, + -0.02606488f, -0.02228328f, -0.02255680f, -0.03427236f, + -7.75165204e-003f, -0.06195229f, 8.21638294e-003f, 0.09535975f, + -0.03709979f, -0.06942501f, 0.14579427f, -0.05448192f, -0.02055904f, + 0.05747357f, 0.02781788f, -0.07077577f, -0.05178314f, -0.10429011f, + -0.11235505f, 0.07529039f, -0.07559302f, -0.08786739f, 0.02983843f, + 0.02667585f, 0.01382199f, -0.01797496f, -0.03141199f, -0.02098101f, + 0.09029204f, 0.04955018f, 0.13718739f, 0.11379953f, 1.80019124e-003f, + -0.04577610f, -1.11108483e-003f, -0.09470536f, -0.11596080f, + 0.04489342f, 0.01784211f, 3.06850672e-003f, 0.10781866f, + 3.36498418e-003f, -0.10842580f, -0.07436839f, -0.10535070f, + -0.01866805f, 0.16057891f, -5.07316366e-003f, -0.04295658f, + -5.90488780e-003f, 8.82003549e-003f, -0.01492646f, -0.05029279f, + -0.12875880f, 8.78831954e-004f, -0.01297184f, -0.07592774f, + -0.02668831f, -6.93787413e-004f, 0.02406698f, -0.01773298f, + -0.03855745f, -0.05877856f, 0.03259695f, 0.12826584f, 0.06292590f, + -4.10733931e-003f, 0.10996531f, 0.01332991f, 0.02088735f, 0.04037504f, + -0.05210760f, 0.07760046f, 0.06399347f, -0.05751930f, -0.10053057f, + 0.07505023f, -0.02139782f, 0.01796176f, 2.34400877e-003f, -0.04208319f, + 0.07355055f, 0.05093350f, -0.02996780f, -0.02219072f, 0.03355330f, + 0.04418742f, -0.05580705f, -0.05037573f, -0.04548179f, 0.01379514f, + 0.02150671f, -0.02194211f, -0.13682702f, 0.05464972f, 0.01608082f, + 0.05309116f, 0.04701022f, 1.33690401e-003f, 0.07575664f, 0.09625306f, + 8.92647635e-003f, -0.02819123f, 0.10866830f, -0.03439325f, + -0.07092371f, -0.06004780f, -0.02712298f, -7.07467366e-003f, + -0.01637020f, 0.01336790f, -0.10313606f, 0.04906582f, -0.05732445f, + -0.02731079f, 0.01042235f, -0.08340668f, 0.03686501f, 0.06108340f, + 0.01322748f, -0.07809529f, 0.03774724f, -0.03413248f, -0.06096525f, + -0.04212124f, -0.07982176f, -1.25973229e-003f, -0.03045501f, + -0.01236493f, -0.06312395f, 0.04789570f, -0.04602066f, 0.08576570f, + 0.02521080f, 0.02988098f, 0.10314583f, 0.07060035f, 0.04520544f, + -0.04426654f, 0.13146530f, 0.08386490f, 0.02164590f, -2.12280243e-003f, + -0.03686353f, -0.02074944f, -0.03829959f, -0.01530596f, 0.02689708f, + 0.11867401f, -0.06043470f, -0.02785023f, -0.04775074f, 0.04878745f, + 0.06350956f, 0.03494788f, 0.01467400f, 1.17890188e-003f, 0.04379614f, + 2.03681854e-003f, -0.03958609f, -0.01072688f, 6.43705716e-003f, + 0.02996500f, -0.03418507f, -0.01960307f, -0.01219154f, + -4.37000440e-003f, -0.02549453f, 0.02646318f, -0.01632513f, + 6.46516960e-003f, -0.01929734f, 4.78711911e-003f, 0.04962371f, + 0.03809111f, 0.07265724f, 0.05758125f, -0.03741554f, 0.01648608f, + -8.45285598e-003f, 0.03996826f, -0.08185477f, 0.02638875f, + -0.04026615f, -0.02744674f, -0.04071517f, 1.05096330e-003f, + -0.04741232f, -0.06733172f, 8.70434940e-003f, -0.02192543f, + 1.35350740e-003f, -0.03056974f, -0.02975521f, -0.02887780f, + -0.01210713f, -0.04828526f, -0.09066251f, -0.09969629f, -0.03665164f, + -8.88111943e-004f, -0.06826669f, -0.01866150f, -0.03627640f, + -0.01408288f, 0.01874239f, -0.02075835f, 0.09145175f, -0.03547291f, + 0.05396780f, 0.04198981f, 0.01301925f, -0.03384354f, -0.12201976f, + 0.06830920f, -0.03715654f, 9.55848210e-003f, 5.05685573e-003f, + 0.05659294f, 3.90764466e-003f, 0.02808490f, -0.05518097f, -0.03711621f, + -0.02835565f, -0.04420464f, -0.01031947f, 0.01883466f, + -8.49525444e-003f, -0.09419250f, -0.01269387f, -0.02133371f, + -0.10190815f, -0.07844430f, 2.43644323e-003f, -4.09610150e-003f, + 0.01202551f, -0.06452291f, -0.10593818f, -0.02464746f, -0.02199699f, + -0.07401930f, 0.07285886f, 8.87513801e-004f, 9.97662079e-003f, + 8.46779719e-003f, 0.03730333f, -0.02905126f, 0.03573337f, -0.04393689f, + -0.12014472f, 0.03176554f, -2.76015815e-003f, 0.10824566f, 0.05090732f, + -3.30179278e-003f, -0.05123822f, 5.04784798e-003f, -0.05664124f, + -5.99415926e-003f, -0.05341901f, -0.01221393f, 0.01291318f, + 9.91760660e-003f, -7.56987557e-003f, -0.06193124f, -2.24549137e-003f, + 0.01987562f, -0.02018840f, -0.06975540f, -0.06601523f, -0.03349112f, + -0.08910118f, -0.03371435f, -0.07406893f, -0.02248047f, -0.06159951f, + 2.77751544e-003f, -0.05723337f, -0.04792468f, 0.07518548f, + 2.77279224e-003f, 0.04211938f, 0.03100502f, 0.05278448f, 0.03954679f, + -0.03006846f, -0.03851741f, -0.02792403f, -0.02875333f, 0.01531280f, + 0.02186953f, -0.01989829f, 2.50679464e-003f, -0.10258728f, + -0.04785743f, -0.02887216f, 3.85063468e-003f, 0.01112236f, + 8.29218887e-003f, -0.04822981f, -0.04503597f, -0.03713100f, + -0.06988008f, -0.11002295f, -2.69209221e-003f, 1.85383670e-003f, + -0.05921049f, -0.06105053f, -0.08458050f, -0.04527602f, + 8.90329306e-004f, -0.05875023f, -2.68602883e-003f, -0.01591195f, + 0.03631859f, 0.05493166f, 0.07300330f, 5.53333294e-003f, 0.06400407f, + 0.01847740f, -5.76280477e-003f, -0.03210877f, 4.25160583e-003f, + 0.01166520f, -1.44864211e-003f, 0.02253744f, -0.03367080f, 0.06983195f, + -4.22323542e-003f, -8.89401045e-003f, -0.07943393f, 0.05199728f, + 0.06065201f, 0.04133492f, 1.44032843e-003f, -0.09585235f, -0.03964731f, + 0.04232114f, 0.01750465f, -0.04487902f, -7.59733608e-003f, 0.02011171f, + 0.04673622f, 0.09011173f, -0.07869188f, -0.04682482f, -0.05080139f, + -3.99383716e-003f, -0.05346331f, 0.01085723f, -0.03599333f, + -0.07097908f, 0.03551549f, 0.02680387f, 0.03471529f, 0.01790393f, + 0.05471273f, 9.62048303e-003f, -0.03180215f, 0.05864431f, 0.02330614f, + 0.01633144f, -0.05616681f, -0.10245429f, -0.08302189f, 0.07291322f, + -0.01972590f, -0.02619633f, -0.02485327f, -0.04627592f, + 1.48853404e-003f, 0.05514185f, -0.01270860f, -0.01948900f, 0.06373586f, + 0.05002292f, -0.03009798f, 8.76216311e-003f, -0.02474238f, + -0.05504891f, 1.74034527e-003f, -0.03333667f, 0.01524987f, 0.11663762f, + -1.32344989e-003f, -0.06608453f, 0.05687166f, -6.89525274e-004f, + -0.04402352f, 0.09450210f, -0.04222684f, -0.05360983f, 0.01779531f, + 0.02561388f, -0.11075410f, -8.77790991e-003f, -0.01099504f, + -0.10380266f, 0.03103457f, -0.02105741f, -0.07371717f, 0.05146710f, + 0.10581432f, -0.08617968f, -0.02892107f, 0.01092199f, 0.14551543f, + -2.24320893e-003f, -0.05818033f, -0.07390742f, 0.05701261f, + 0.12937020f, -0.04986651f, 0.10182415f, 0.05028650f, 0.12515625f, + 0.09175041f, 0.06404983f, 0.01523394f, 0.09460562f, 0.06106631f, + -0.14266998f, -0.02926703f, 0.02762171f, 0.02164151f, + -9.58488265e-004f, -0.04231362f, -0.09866509f, 0.04322244f, + 0.05872034f, -0.04838847f, 0.06319253f, 0.02443798f, -0.03606876f, + 9.38737206e-003f, 0.04289991f, -0.01027411f, 0.08156885f, 0.08751175f, + -0.13191354f, 8.16054735e-003f, -0.01452161f, 0.02952677f, 0.03615945f, + -2.09128903e-003f, 0.02246693f, 0.09623287f, 0.09412123f, -0.02924758f, + -0.07815186f, -0.02203079f, -2.02566991e-003f, 0.01094733f, + -0.01442332f, 0.02838561f, 0.11882371f, 7.28798332e-003f, -0.10345965f, + 0.07561217f, -0.02049661f, 4.44177445e-003f, 0.01609347f, -0.04893158f, + -0.08758243f, -7.67420698e-003f, 0.08862378f, 0.06098121f, 0.06565887f, + 7.32981879e-003f, 0.03558407f, -0.03874352f, -0.02490055f, + -0.06771075f, 0.09939223f, -0.01066077f, 0.01382995f, -0.07289080f, + 7.47184316e-003f, 0.10621431f, -0.02878659f, 0.02383525f, -0.03274646f, + 0.02137008f, 0.03837290f, 0.02450992f, -0.04296818f, -0.02895143f, + 0.05327370f, 0.01499020f, 0.04998732f, 0.12938657f, 0.09391870f, + 0.04292390f, -0.03359194f, -0.06809492f, 0.01125796f, 0.17290455f, + -0.03430733f, -0.06255233f, -0.01813114f, 0.11726857f, -0.06127599f, + -0.08677909f, -0.03429872f, 0.04684938f, 0.08161420f, 0.03538774f, + 0.01833884f, 0.11321855f, 0.03261845f, -0.04826299f, 0.01752407f, + -0.01796414f, -0.10464549f, -3.30041884e-003f, 2.29343961e-004f, + 0.01457292f, -0.02132982f, -0.02602923f, -9.87351313e-003f, + 0.04273872f, -0.02103316f, -0.07994065f, 0.02614958f, -0.02111666f, + -0.06964913f, -0.13453490f, -0.06861878f, -6.09341264e-003f, + 0.08251446f, 0.15612499f, 2.46531400e-003f, 8.88424646e-003f, + -0.04152999f, 0.02054853f, 0.05277953f, -0.03087788f, 0.02817579f, + 0.13939077f, 0.07641046f, -0.03627627f, -0.03015098f, -0.04041540f, + -0.01360690f, -0.06227205f, -0.02738223f, 0.13577610f, 0.15235767f, + -0.05392922f, -0.11175954f, 0.02157129f, 0.01146481f, -0.05264937f, + -0.06595174f, -0.02749175f, 0.11812254f, 0.17404149f, -0.06137035f, + -0.11003478f, -0.01351621f, -0.01745916f, -0.08577441f, -0.04469909f, + -0.06106115f, 0.10559758f, 0.20806813f, -0.09174948f, 7.09621934e-004f, + 0.03579374f, 0.07215115f, 0.02221742f, 0.01827742f, -7.90785067e-003f, + 0.01489554f, 0.14519960f, -0.06425831f, 0.02990399f, -1.80181325e-003f, + -0.01401528f, -0.04171134f, -3.70530109e-003f, -0.09090481f, + 0.09520713f, 0.08845516f, -0.02651753f, -0.03016730f, 0.02562448f, + 0.03563816f, -0.03817881f, 0.01433385f, 0.02256983f, 0.02872120f, + 0.01001934f, -0.06332260f, 0.04338406f, 0.07001807f, -0.04705722f, + -0.07318907f, 0.02630457f, 0.03106382f, 0.06648342f, 0.10913180f, + -0.01630815f, 0.02910308f, 0.02895109f, 0.08040254f, 0.06969310f, + 0.06797734f, 6.08639978e-003f, 4.16588830e-003f, 0.08926726f, + -0.03123648f, 0.02700146f, 0.01168734f, -0.01631594f, 4.61015804e-003f, + 8.51359498e-003f, -0.03544224f, 0.03571994f, 4.29766066e-003f, + -0.01970077f, -8.79793242e-003f, 0.09607988f, 0.01544222f, + -0.03923707f, 0.07308586f, 0.06061262f, 1.31683104e-004f, + -7.98222050e-003f, 0.02399261f, -0.06084389f, -0.02743429f, + -0.05475523f, -0.04131311f, 0.03559756f, 0.03055342f, 0.02981433f, + 0.14860515f, 0.01766787f, 0.02945257f, 0.04898238f, 0.01026922f, + 0.02811658f, 0.08267091f, 0.02732154f, -0.01237693f, 0.11760156f, + 0.03802063f, -0.03309754f, 5.24957618e-003f, -0.02460510f, 0.02691451f, + 0.05399988f, -0.10133506f, 0.06385437f, -0.01818005f, 0.02259503f, + 0.03573135f, 0.01042848f, -0.04153402f, -0.04043029f, 0.01643575f, + 0.08326677f, 4.61383024e-004f, -0.05308095f, -0.08536223f, + -1.61011645e-003f, -0.02163720f, -0.01783352f, 0.03859637f, + 0.08498885f, -0.01725216f, 0.08625131f, 0.10995087f, 0.09177644f, + 0.08498347f, 0.07646490f, 0.05580502f, 0.02693516f, 0.09996913f, + 0.09070327f, 0.06667200f, 0.05873008f, -0.02247842f, 0.07772321f, + 0.12408436f, 0.12629253f, -8.41997913e-004f, 0.01477783f, 0.09165990f, + -2.98401713e-003f, -0.06466447f, -0.07057302f, 2.09516948e-004f, + 0.02210209f, -0.02158809f, -0.08602506f, -0.02284836f, + 4.01876355e-003f, 9.56660323e-003f, -0.02073978f, -0.04635138f, + -7.59423291e-003f, -0.01377393f, -0.04559359f, -0.13284740f, + -0.08671406f, -0.03654395f, 0.01142869f, 0.03287891f, -0.04392983f, + 0.06142959f, 0.17710890f, 0.10385257f, 0.01329137f, 0.10067633f, + 0.12450829f, -0.04476709f, 0.09049144f, 0.04589312f, 0.11167907f, + 0.08587538f, 0.04767583f, 1.67188141e-003f, 0.02359802f, -0.03808852f, + 0.03126272f, -0.01919029f, -0.05698918f, -0.02365112f, -0.06519032f, + -0.05599358f, -0.07097308f, -0.03301812f, -0.04719102f, -0.02566297f, + 0.01324074f, -0.09230672f, -0.05518232f, -0.04712864f, -0.03380903f, + -0.06719479f, 0.01183908f, -0.09326738f, 0.01642865f, 0.03789867f, + -6.61567831e-003f, 0.07796386f, 0.07246574f, 0.04706347f, -0.02523437f, + -0.01696830f, -0.08068866f, 0.06030888f, 0.10527060f, -0.06611756f, + 0.02977346f, 0.02621830f, 0.01913855f, -0.08479366f, -0.06322418f, + -0.13570616f, -0.07644490f, 9.31900274e-003f, -0.08095149f, + -0.10197903f, -0.05204025f, 0.01413151f, -0.07800411f, -0.01885122f, + -0.07509381f, -0.10136326f, -0.05212355f, -0.09944065f, + -1.33606605e-003f, -0.06342617f, -0.04178550f, -0.12373723f, + -0.02832736f, -0.06057501f, 0.05830070f, 0.07604282f, -0.06462587f, + 8.02447461e-003f, 0.11580125f, 0.12332212f, 0.01978462f, + -2.72378162e-003f, 0.05850752f, -0.04674481f, 0.05148062f, + -2.62542837e-003f, 0.11253355f, 0.09893716f, 0.09785093f, -0.04659257f, + -0.01102429f, -0.07002308f, 0.03088913f, -0.02565549f, -0.07671449f, + 3.17443861e-003f, -0.10783514f, -0.02314270f, -0.11089555f, + -0.01024768f, 0.03116021f, -0.04964825f, 0.02281825f, 5.50005678e-003f, + -0.08427856f, -0.14685495f, -0.07719755f, -0.13342668f, -0.04525511f, + -0.09914210f, 0.02588859f, 0.03469279f, 0.04664020f, 0.11688190f, + 0.09647275f, 0.10857815f, -0.01448726f, 0.04299758f, -0.06763151f, + 1.33257592e-003f, 0.14331576f, 0.07574340f, 0.09166205f, 0.05674926f, + 0.11325553f, -0.01106494f, 0.02062161f, -0.11484840f, -0.07492137f, + -0.02864293f, -0.01275638f, -0.06946032f, -0.10101652f, -0.04113498f, + -0.02214783f, -0.01273942f, -0.07480393f, -0.10556041f, -0.07622112f, + -0.09988393f, -0.11453961f, -0.12073903f, -0.09412795f, -0.07146588f, + -0.04054537f, -0.06127083f, 0.04221122f, 0.07688113f, 0.04099256f, + 0.12663734f, 0.14683802f, 0.21761774f, 0.12525328f, 0.18431792f, + -1.66402373e-003f, 2.37777247e-003f, 0.01445475f, 0.03509416f, + 0.02654697f, 0.01716739f, 0.05374011f, 0.02944174f, 0.11323927f, + -0.01485456f, -0.01611330f, -1.85554172e-003f, -0.01708549f, + -0.05435753f, -0.05302101f, 0.05260378f, -0.03582945f, + -3.42867890e-004f, 1.36076682e-003f, -0.04436073f, -0.04228432f, + 0.03281291f, -0.05480836f, -0.10197772f, -0.07206279f, -0.10741059f, + -0.02366946f, 0.10278475f, -2.74783419e-003f, -0.03242477f, + 0.02308955f, 0.02835869f, 0.10348799f, 0.19580358f, 0.10252027f, + 0.08039929f, 0.05525554f, -0.13250865f, -0.14395352f, 3.13586881e-003f, + -0.03387071f, 8.94669443e-003f, 0.05406157f, -4.97324532e-003f, + -0.01189114f, 2.82919413e-004f, -0.03901557f, -0.04898705f, + 0.02164520f, -0.01382906f, -0.01850416f, 0.01869347f, -0.02450060f, + 0.02291678f, 0.08196463f, 0.03309153f, -0.10629974f, 0.02473924f, + 0.05344394f, -0.02404823f, -0.03243643f, -5.55244600e-003f, + -0.08009996f, 0.02811539f, 0.04235742f, 0.01859004f, 0.04902123f, + -0.01438252f, -0.01526853f, 0.02044195f, -0.05008660f, 0.04244113f, + 0.07611816f, 0.04950470f, -0.06020549f, -4.26026015e-003f, 0.13133512f, + -0.01438738f, -0.01958807f, -0.04044152f, -0.12425045f, + 2.84353318e-003f, -0.05042776f, -0.09121484f, 7.34345755e-003f, + 0.09388847f, 0.11800314f, 4.72295098e-003f, 4.44378285e-003f, + -0.07984917f, -0.03613737f, 0.04490915f, -0.02246483f, 0.04681071f, + 0.05240871f, 0.02157206f, -0.04603431f, -0.01197929f, -0.02748779f, + 0.13621049f, 0.08812155f, -0.07802048f, 4.86458559e-003f, -0.01598836f, + 0.01024450f, -0.03463517f, -0.02304239f, -0.08692665f, 0.06655128f, + 0.05785803f, -0.12640759f, 0.02307472f, 0.07337402f, 0.07525434f, + 0.04943763f, -0.02241034f, -0.09978238f, 0.14487994f, -0.06570521f, + -0.07855482f, 0.02830222f, -5.29603509e-004f, -0.04669895f, + -0.11822784f, -0.12246452f, -0.15365660f, -0.02969127f, 0.08078201f, + 0.13512598f, 0.11505685f, 0.04740673f, 0.01376022f, -0.05852978f, + -0.01537809f, -0.05541119f, 0.02491065f, -0.02870786f, 0.02760978f, + 0.23836176f, 0.22347429f, 0.10306466f, -0.06919070f, -0.10132039f, + -0.20198342f, -0.05040560f, 0.27163076f, 0.36987007f, 0.34540465f, + 0.29095781f, 0.05649706f, 0.04125737f, 0.07505883f, -0.02737836f, + -8.43431335e-003f, 0.07368195f, 0.01653876f, -0.09402955f, + -0.09574359f, 0.01474337f, -0.07128561f, -0.03460737f, 0.11438941f, + 0.13752601f, -0.06385452f, -0.06310338f, 8.19548313e-003f, 0.11622470f, + 5.05133113e-003f, -0.07602754f, 0.06695660f, 0.25723928f, 0.09037900f, + 0.28826267f, 0.13165380f, -0.05312614f, -0.02137198f, -0.03442232f, + -0.06255679f, 0.03899667f, 0.18391028f, 0.26016650f, 0.03374462f, + 0.01860465f, 0.19077586f, 0.18160543f, 3.43634398e-003f, -0.03036782f, + 0.19683038f, 0.35378191f, 0.24968483f, -0.03222649f, 0.28972381f, + 0.43091634f, 0.30778357f, 0.02335266f, -0.09877399f, -6.85245218e-003f, + 0.08945240f, -0.08150686f, 0.02792493f, 0.24806842f, 0.17338486f, + 0.06231801f, -0.10432383f, -0.16653322f, -0.13197899f, -0.08531576f, + -0.19271527f, -0.13536365f, 0.22240199f, 0.39219588f, 0.26597717f, + -0.01231649f, 0.01016179f, 0.13379875f, 0.12018334f, -0.04852953f, + -0.07915270f, 0.07036012f, 3.87723115e-003f, -0.06126805f, + -0.15015170f, -0.11406515f, -0.08556531f, -0.07429333f, -0.16115491f, + 0.13214062f, 0.25691369f, 0.05697750f, 0.06861912f, -6.02903729e-003f, + -7.94562511e-003f, 0.04799571f, 0.06695165f, -0.01926842f, 0.06206308f, + 0.13450983f, -0.06381495f, -2.98370165e-003f, -0.03482971f, + 7.53991678e-003f, 0.03895611f, 0.11464261f, 0.01669971f, + 8.27818643e-003f, -7.49160210e-003f, -0.11712562f, -0.10650621f, + -0.10353880f, -0.04994106f, -7.65618810e-004f, 0.03023767f, + -0.04759270f, -0.07302686f, -0.05825012f, -0.13156348f, -0.10639747f, + -0.19393684f, -0.09973683f, -0.07918908f, 4.63177625e-004f, + -6.61382044e-004f, 0.15853868f, 0.08561199f, -0.07660093f, + -0.08015265f, -0.06164073f, 0.01882577f, -7.29908410e-004f, + 0.06840892f, 0.03843764f, 0.20274927f, 0.22028814f, -5.26101235e-003f, + 0.01452435f, -0.06331623f, 0.02865064f, 0.05673740f, 0.12171564f, + 0.03837196f, 0.03555467f, -0.02662914f, -0.10280123f, -0.06526285f, + -0.11066351f, -0.08988424f, -0.10103678f, 8.10526591e-003f, + 5.95238712e-003f, 0.02617721f, -0.01705742f, -0.10897956f, + -0.08004991f, -0.11271993f, -0.06185647f, -0.06103712f, 0.01597041f, + -0.05923606f, 0.09410726f, 0.22858568f, 0.03263380f, 0.06772990f, + -0.09003516f, 0.01017870f, 0.01931688f, 0.08628357f, -0.01430009f, + 0.10954945f, 0.16612452f, -0.02434544f, -0.03310068f, -0.04236627f, + 0.01212392f, -6.15046406e-003f, 0.06954194f, 0.03015283f, 0.01787957f, + 0.02781667f, -0.05561153f, -8.96244217e-003f, -0.04971489f, + 0.07510284f, 0.01775282f, 0.05889897f, -0.07981427f, 0.03647643f, + -3.73833324e-003f, -0.08894575f, -0.06429435f, -0.08068276f, + 0.03567704f, -0.07131936f, -7.21910037e-003f, -0.09566668f, + 0.17886090f, 0.14911725f, 0.02070032f, -0.05017120f, -0.04992622f, + 0.01570143f, -0.09906903f, 0.06456193f, 0.15329507f, 0.18820767f, + 0.11689861f, -0.01178513f, -0.02225163f, -0.01905318f, 0.10271224f, + -7.27029052e-003f, 0.11664233f, 0.14796902f, 0.07771893f, 0.02400013f, + -0.05361797f, -0.01972888f, 0.01376177f, 0.06740040f, -0.06525395f, + 0.05726178f, -0.02404981f, -0.14018567f, -0.02074987f, -0.04621970f, + -0.04688627f, -0.01842059f, 0.07722727f, -0.04852883f, 0.01529004f, + -0.19639495f, 0.10817073f, 0.03795860f, -0.09435206f, -0.07984378f, + -0.03383440f, 0.11081333f, 0.02237366f, 0.12703256f, 0.21613893f, + 0.02918790f, 4.66472283e-003f, -0.10274266f, -0.04854131f, + -3.46305710e-003f, 0.08652268f, 0.02251546f, 0.09636052f, 0.17180754f, + -0.09272388f, 4.59174305e-004f, -0.11723048f, -0.12210111f, + -0.15547538f, 0.07218186f, -0.05297846f, 0.03779940f, 0.05150875f, + -0.03802310f, 0.03870645f, -0.15250699f, -0.08696499f, -0.02021560f, + 0.04118926f, -0.15177974f, 0.01577647f, 0.10249301f, 7.50041893e-003f, + 0.01721806f, -0.06828983f, -0.02397596f, -0.06598977f, -0.04317593f, + -0.08064980f, 6.66632550e-003f, 0.03333484f, 0.07093620f, 0.08231064f, + -0.06577903f, -0.06698844f, -0.06984019f, -0.06508023f, -0.14145090f, + -0.02393239f, 0.06485303f, 8.83263443e-003f, 0.09251080f, -0.07557579f, + -0.05067699f, -0.09798748f, -0.06703258f, -0.14056294f, 0.03245994f, + 0.12554143f, 0.01761621f, 0.12980327f, -0.04081950f, -0.11906909f, + -0.14813015f, -0.08376863f, -0.12200681f, 0.04988137f, 0.05424247f, + -3.90952639e-003f, 0.03255733f, -0.12717837f, -0.07461493f, + -0.05703964f, -0.01736189f, -0.08026433f, -0.05433894f, -0.01719359f, + 0.02886275f, 0.01772653f, -0.09163518f, 3.57789593e-003f, -0.10129993f, + -0.02653764f, -0.08131415f, -0.03847986f, -7.62157550e-004f, + 0.06486648f, 0.19675669f, -0.04919156f, -0.07059129f, -0.04857785f, + -0.01042383f, -0.08328653f, 0.03660302f, -0.03696846f, 0.04969259f, + 0.08241162f, -0.12514858f, -0.06122676f, -0.03750202f, + 6.52989605e-003f, -0.10247213f, 0.02568346f, 4.51781414e-003f, + -0.03734229f, -0.01131264f, -0.05412074f, 8.89345480e-004f, + -0.12388977f, -0.05959237f, -0.12418608f, -0.06151643f, -0.07310260f, + 0.02441575f, 0.07023528f, -0.07548289f, -7.57147965e-004f, + -0.09061348f, -0.08112976f, -0.06920306f, 9.54394229e-003f, + -0.01219902f, 1.21273217e-003f, -8.88989680e-003f, -0.08309301f, + -0.04552661f, -0.10739882f, -0.05691034f, -0.13928030f, 0.09027749f, + 0.15123098f, 0.03175976f, 0.17763577f, 3.29913251e-004f, 0.05151888f, + -0.09844074f, -0.09475287f, -0.08571247f, 0.16241577f, 0.19336018f, + 8.57454538e-003f, 0.11474732f, -0.01493934f, 0.03352379f, -0.08966240f, + -0.02322310f, 0.02663568f, 0.05448750f, -0.03536883f, -0.07210463f, + -0.06807277f, -0.03121621f, -0.05932408f, -0.17282860f, -0.15873498f, + -0.04956378f, 0.01603377f, -0.12385946f, 0.13878587f, 0.21468069f, + 0.13510075f, 0.20992437f, 0.08845878f, 0.08104013f, 0.03754176f, + 0.12173114f, 0.11103114f, 0.10643122f, 0.13941477f, 0.11640384f, + 0.14786847f, 0.01218238f, 0.01160753f, 0.03547940f, 0.08794311f, + -0.01695384f, -0.07692261f, -0.08236158f, 6.79194089e-003f, + -0.02458403f, 0.13022894f, 0.10953187f, 0.09857773f, 0.04735930f, + -0.04353498f, -0.15173385f, -0.17904443f, -0.10450364f, -0.13418166f, + -0.06633098f, -0.03170381f, -0.06839000f, -0.11350126f, -0.06983913f, + 0.19083543f, 0.17604128f, 0.07730632f, 0.10022651f, 0.36428109f, + 0.28291923f, 0.12688625f, 0.15942036f, 0.14064661f, -0.11201853f, + -0.13969108f, -0.09088077f, -0.14107047f, 0.05117374f, + -2.63348082e-003f, -0.10794610f, -0.09715455f, -0.05284977f, + 0.01565668f, 0.05031200f, 0.07021113f, -0.02963028f, 0.01766960f, + 0.08333644f, -0.03211382f, 4.90096770e-003f, 0.05186674f, -0.05045737f, + -0.09624767f, -0.02525997f, 0.06916669f, 0.01213916f, 0.05333899f, + -0.03443280f, -0.10055527f, -0.06291115f, 5.42851724e-003f, + -6.30360236e-003f, 0.02270257f, -0.01769792f, 0.03273688f, 0.07746078f, + 7.77099328e-003f, 0.05041346f, 0.01648103f, -0.02321534f, -0.09930186f, + -0.02293853f, 0.02034990f, -0.08324204f, 0.08510064f, -0.03732836f, + -0.06465405f, -0.06086946f, 0.13680504f, -0.11469388f, -0.03896406f, + -0.07142810f, 2.67581246e-003f, -0.03639632f, -0.09849060f, + -0.11014334f, 0.17489147f, 0.17610909f, -0.16091567f, -0.07248894f, + 0.01567141f, 0.23742996f, 0.07552249f, -0.06270349f, -0.07303379f, + 0.25442186f, 0.16903116f, -0.08168741f, -0.05913896f, -0.03954096f, + 6.81776879e-003f, -0.05615319f, -0.07303037f, -0.12176382f, + 0.12385108f, 0.22084464f, -0.05543206f, -0.03310431f, 0.05731593f, + 0.19481890f, 0.04016430f, -0.06480758f, -0.12353460f, 0.18733442f, + -0.09631214f, -0.11192076f, 0.12404587f, 0.15671748f, 0.19256128f, + 0.10895617f, 0.03391477f, -0.13032004f, -0.05626907f, -0.09025607f, + 0.23485197f, 0.27812332f, 0.26725492f, 0.07255980f, 0.16565137f, + 0.22388470f, 0.07441066f, -0.21003133f, -0.08075339f, -0.15031935f, + 0.07023834f, 0.10872041f, 0.18156518f, 0.20037253f, 0.13571967f, + -0.11915682f, -0.11131983f, -0.18878011f, 0.06074620f, 0.20578890f, + 0.12413109f, 0.03930207f, 0.29176015f, 0.29502738f, 0.27856228f, + -0.01803601f, 0.16646385f, 0.19268319f, 0.01900682f, 0.06026287f, + 2.35868432e-003f, 0.01558199f, 0.02707230f, 0.11383014f, 0.12103992f, + 0.03907350f, 0.04637353f, 0.09020995f, 0.11919726f, -3.63007211e-003f, + 0.02220155f, 0.10336831f, 0.17351882f, 0.12259731f, 0.18983354f, + 0.15736865f, 0.01160725f, -0.01690723f, -9.69582412e-004f, 0.07213813f, + 0.01161613f, 0.17864859f, 0.24486147f, 0.18208991f, 0.20177495f, + 0.05972528f, -8.93934630e-003f, -0.02316955f, 0.14436610f, 0.14114498f, + 0.05520950f, 0.06353590f, -0.19124921f, 0.10174713f, 0.29414919f, + 0.26448128f, 0.09344960f, 0.15284036f, 0.19797507f, 0.11369792f, + -0.12722753f, -0.21396367f, -0.02008235f, -0.06566695f, -0.01662150f, + -0.03937003f, 0.04778343f, 0.05017274f, -0.02299062f, -0.20208496f, + -0.06395898f, 0.13721776f, 0.22544557f, 0.14888357f, 0.08687132f, + 0.27088094f, 0.32206613f, 0.09782200f, -0.18523243f, -0.17232181f, + -0.01041531f, 0.04008654f, 0.04199702f, -0.08081299f, -0.03755421f, + -0.04809646f, -0.05222081f, -0.21709201f, -0.06622940f, 0.02945281f, + -0.04600435f, -0.05256077f, -0.08432942f, 0.02848100f, 0.03490564f, + 8.28621630e-003f, -0.11051246f, -0.11210597f, -0.01998289f, + -0.05369405f, -0.08869293f, -0.18799506f, -0.05436598f, -0.05011634f, + -0.05419716f, -0.06151857f, -0.10827805f, 0.04346735f, 0.04016083f, + 0.01520820f, -0.12173316f, -0.04880285f, -0.01101406f, 0.03250847f, + -0.06009551f, -0.03082932f, -0.02295134f, -0.06856834f, -0.08775249f, + -0.23793389f, -0.09174541f, -0.05538322f, -0.04321031f, -0.11874759f, + -0.04221844f, -0.06070468f, 0.01194489f, 0.02608565f, -0.03892140f, + -0.01643151f, -0.02602034f, -0.01305472f, 0.03920100f, -0.06514261f, + 0.01126918f, -6.27710763e-003f, -0.02720047f, -0.11133634f, + 0.03300330f, 0.02398472f, 0.04079665f, -0.10564448f, 0.05966159f, + 0.01195221f, -0.03179441f, -0.01692590f, -0.06177841f, 0.01841576f, + -5.51078189e-003f, -0.06821765f, -0.03191888f, -0.09545476f, + 0.03030550f, -0.04896152f, -0.02914624f, -0.13283344f, -0.04783419f, + 6.07836898e-003f, -0.01449538f, -0.13358212f, -0.09687774f, + -0.02813793f, 0.01213498f, 0.06650011f, -0.02039067f, 0.13356198f, + 0.05986415f, -9.12760664e-003f, -0.18780160f, -0.11992817f, + -0.06342237f, 0.01229534f, 0.07143231f, 0.10713009f, 0.11085765f, + 0.06569190f, -0.02956399f, -0.16288325f, -0.13993549f, -0.01292515f, + 0.03833013f, 0.09130384f, -0.05086257f, 0.05617329f, -0.03896667f, + -0.06282311f, -0.11490010f, -0.14264110f, -0.04530499f, 0.01598189f, + 0.09167797f, 0.08663294f, 0.04885277f, -0.05741219f, -0.07565769f, + -0.17136464f, -0.02619422f, -0.02477579f, 0.02679587f, 0.11621952f, + 0.08788391f, 0.15520640f, 0.04709549f, 0.04504483f, -0.10214074f, + -0.12293372f, -0.04820546f, -0.05484834f, 0.05473754f, 0.07346445f, + 0.05577277f, -0.08209965f, 0.03462975f, -0.20962234f, -0.09324598f, + 3.79481679e-003f, 0.03617633f, 0.16742408f, 0.07058107f, 0.10204960f, + -0.06795346f, 3.22807301e-003f, -0.12589309f, -0.17496960f, + 0.02078314f, -0.07694324f, 0.12184640f, 0.08997164f, 0.04793497f, + -0.11383379f, -0.08046359f, -0.25716835f, -0.08080962f, + 6.80711539e-003f, -0.02930280f, -3.04938294e-003f, -0.11106286f, + -0.04628860f, -0.07821649f, 7.70127494e-003f, -0.10247706f, + 1.21042714e-003f, 0.20573859f, -0.03241005f, 8.42972286e-003f, + 0.01946464f, -0.01197973f, -0.14579976f, 0.04233614f, + -4.14096704e-003f, -0.06866436f, -0.02431862f, -0.13529138f, + 1.25891645e-003f, -0.11425111f, -0.04303651f, -0.01694815f, + 0.05720210f, -0.16040207f, 0.02772896f, 0.05498345f, -0.15010567f, + 0.01450866f, 0.02350303f, -0.04301004f, -0.04951802f, 0.21702233f, + -0.03159155f, -0.01963303f, 0.18232647f, -0.03263875f, + -2.88476888e-003f, 0.01587562f, -1.94303901e-003f, -0.07789494f, + 0.04674156f, -6.25576358e-003f, 0.08925962f, 0.21353747f, 0.01254677f, + -0.06999976f, -0.05931328f, -0.01884327f, -0.04306272f, 0.11794136f, + 0.03842728f, -0.03907030f, 0.05636114f, -0.09766009f, -0.02104000f, + 8.72711372e-003f, -0.02736877f, -0.05112274f, 0.16996814f, 0.02955785f, + 0.02094014f, 0.08414304f, -0.03335762f, -0.03617457f, -0.05808248f, + -0.08872101f, 0.02927705f, 0.27077839f, 0.06075108f, 0.07478261f, + 0.15282831f, -0.03908454f, -0.05101782f, -9.51998029e-003f, + -0.03272416f, -0.08735625f, 0.07633440f, -0.07185312f, 0.13841286f, + 0.07812646f, -0.12901451f, -0.05488589f, -0.05644578f, -0.03290703f, + -0.11184757f, 0.03751570f, -0.05978153f, -0.09155276f, 0.05657315f, + -0.04328186f, -0.03047933f, -0.01413135f, -0.10181040f, -0.01384013f, + 0.20132534f, -0.01536873f, -0.07641169f, 0.05906778f, -0.07833145f, + -0.01523801f, -0.07502609f, -0.09461885f, -0.15013233f, 0.16050665f, + 0.09021381f, 0.08473236f, 0.03386267f, -0.09147339f, -0.09170618f, + -0.08498498f, -0.05119187f, -0.10431040f, 0.01041618f, -0.03064913f, + 0.09340212f, 0.06448522f, -0.03881054f, -0.04985436f, -0.14794017f, + -0.05200112f, -0.02144495f, 0.04000821f, 0.12420804f, -0.01851651f, + -0.04116732f, -0.11951703f, -0.04879033f, -0.08722515f, -0.08454733f, + -0.10549165f, 0.11251976f, 0.10766345f, 0.19201984f, 0.06128913f, + -0.02734615f, -0.08834923f, -0.16999826f, -0.03548348f, + -5.36092324e-003f, 0.08297954f, 0.07226378f, 0.04194529f, 0.04668673f, + 8.73902347e-003f, 0.06980139f, 0.05652480f, 0.05879445f, 0.02477076f, + 0.02451423f, 0.12433673f, 0.05600227f, 0.06886370f, 0.03863076f, + 0.07459056f, 0.02264139f, 0.01495469f, 0.06344220f, 0.06945208f, + 0.02931899f, 0.11719371f, 0.04527427f, 0.03248192f, 2.08271481e-003f, + 0.02044626f, 0.11403449f, 0.04303892f, 0.06444661f, 0.04959024f, + 0.08174094f, 0.09240247f, 0.04894639f, 0.02252937f, -0.01652530f, + 0.07587013f, 0.06064249f, 0.13954395f, 0.02772832f, 0.07093039f, + 0.08501238f, 0.01701301f, 0.09055722f, 0.33421436f, 0.20163782f, + 0.09821030f, 0.07951369f, 0.08695120f, -0.12757730f, -0.13865978f, + -0.06610068f, -0.10985506f, 0.03406816f, -0.01116336f, -0.07281768f, + -0.13525715f, -0.12844718f, 0.08956250f, 0.09171610f, 0.10092317f, + 0.23385370f, 0.34489515f, 0.09901748f, 0.02002922f, 0.12335990f, + 0.07606190f, -0.14899330f, -0.15634622f, -0.06494618f, -0.01760547f, + 0.03404277f, -0.13208845f, -0.12101169f, -0.18294574f, -0.16560709f, + 0.02183887f, -0.02752613f, 0.01813638f, 0.02000757f, 0.01319924f, + 0.08030242f, 0.01220535f, 2.98233377e-003f, -0.01307070f, 0.05970297f, + -0.05345284f, -0.03381982f, -9.87543724e-003f, -0.06869387f, + 0.03956730f, -0.03108176f, -0.05732809f, 0.02172386f, 0.04159765f, + 2.62783933e-003f, 0.04813229f, 0.09358983f, -8.18389002e-003f, + 0.01724574f, -0.02547474f, -0.04967288f, -0.02390376f, 0.06640504f, + -0.06306566f, 0.01137518f, 0.05589378f, -0.08237787f, 0.02455001f, + -0.03059422f, -0.08953978f, 0.06851497f, 0.07190268f, -0.07610799f, + 7.87237938e-003f, -7.85830803e-003f, 0.06006952f, -0.01126728f, + -2.85743061e-003f, -0.04772895f, 0.01884944f, 0.15005857f, + -0.06268821f, -0.01989072f, 0.01138399f, 0.08760451f, 0.03879007f, + -9.66926850e-003f, -0.08012961f, 0.06414555f, -0.01362950f, + -0.09135523f, 0.01755159f, 0.04459474f, 0.09650917f, 0.05219948f, + -2.19440833e-003f, -0.07037939f, -0.01599054f, 0.13103317f, + -0.02492603f, -0.01032540f, -0.02903307f, 0.04489160f, 0.05148086f, + 0.01858173f, -0.02919228f, 0.08299296f, -0.04590359f, -0.15745632f, + -0.09068198f, -0.02972453f, 0.12985018f, 0.22320485f, 0.24261914f, + 0.03642650f, -0.05506422f, 2.67413049e-003f, -0.03834032f, 0.06449424f, + 0.03834866f, 0.03816991f, 0.25039271f, 0.34212017f, 0.32433882f, + 0.18824573f, -0.08599839f, -0.17599408f, -0.15317015f, -0.09913155f, + -0.02856072f, -0.05304699f, -1.06437842e-003f, -0.06641813f, + -0.07509298f, 0.01463361f, -0.07551918f, -0.04510373f, + -8.44620075e-003f, 0.01772176f, 0.04068235f, 0.20295307f, 0.15719447f, + 0.05712103f, 0.26296997f, 0.14657754f, 0.01547317f, -0.05052776f, + -0.03881342f, -0.01437883f, -0.04930177f, 0.11719568f, 0.24098417f, + 0.26468599f, 0.31698579f, 0.10103608f, -0.01096375f, -0.01367013f, + 0.17104232f, 0.20065314f, 2.67622480e-003f, -0.01190034f, 0.18301608f, + 0.09459770f, -0.06357619f, -0.06473801f, 0.01377906f, -0.10032775f, + -0.06388740f, 3.80393048e-003f, 0.06206078f, 0.10349120f, 0.26804337f, + 8.17918684e-003f, -0.02314351f, 9.34422202e-003f, 0.09198381f, + 0.03681326f, -8.77339672e-003f, -0.09662418f, -0.02715708f, + 0.13503517f, 0.08962728f, -6.57071499e-003f, -0.03201199f, 0.28510824f, + 0.32095715f, 0.18512695f, -0.14230858f, -0.14048551f, -0.07181299f, + -0.08575408f, -0.08661680f, -0.17416079f, 7.54326640e-004f, + 0.05601677f, 0.13585392f, -0.04960437f, -0.07708392f, 0.10676333f, + -0.04407546f, -0.07209078f, 0.03663663f, 0.28949317f, 0.41127121f, + 0.27431169f, -0.06900328f, -0.21474190f, -0.15578632f, -0.19555484f, + -0.15209621f, -0.11269179f, 0.07416003f, 0.18991330f, 0.26858172f, + 0.01952259f, 0.01017922f, 0.02159843f, -4.95165400e-003f, -0.04368168f, + -0.12721671f, -0.06673957f, -0.11275250f, 0.04413409f, 0.05578312f, + 0.03896771f, 0.03566417f, -0.05871816f, -0.07388090f, -0.17965563f, + -0.08570268f, -0.15273231f, -0.06022318f, -0.06999847f, + -6.81510568e-003f, 0.06294262f, -6.54901436e-004f, -0.01128654f, + -0.02289657f, 0.04849290f, 0.04140804f, 0.23681939f, 0.14545733f, + 0.01989965f, 0.12032662f, 3.87463090e-003f, -6.02597650e-003f, + -0.05919775f, -0.03067224f, -0.07787777f, 0.10834727f, 0.02153730f, + 0.02765649f, 0.03975543f, -0.12182906f, -0.04900113f, -0.09940100f, + -0.06453611f, -0.13757215f, -0.03721382f, 0.02827376f, -0.04351249f, + 0.01907038f, -0.10284120f, -0.05671160f, -0.10760647f, -0.09624009f, + -0.09565596f, -0.01303654f, 0.03080539f, 0.01416511f, 0.05846142f, + -5.42971538e-003f, 0.06221476f, -0.03320325f, -0.06791797f, + -0.05791342f, 0.12851369f, 0.14990346f, 0.03634374f, 0.14262885f, + 0.04330391f, 0.05032569f, -0.05631914f, 0.01606137f, 0.04387223f, + 0.22344995f, 0.15722635f, -0.04693628f, 0.03006579f, -2.52882647e-003f, + 0.05717621f, -0.07529724f, -0.02848588f, -0.06868757f, + -4.51729307e-003f, 0.06466042f, -0.05935378f, -0.04704857f, + -0.07363959f, 0.04843248f, -0.13421375f, -0.09789340f, -0.10255270f, + 0.03509852f, 0.04751543f, -0.03822323f, 0.09740467f, 0.04762916f, + 0.03940146f, -0.08283259f, 0.09552965f, 0.05038739f, 0.21258622f, + 0.09646992f, 0.03241193f, 0.05167701f, 0.04614570f, 0.04330090f, + -0.02671840f, -0.06259909f, -0.02301898f, 0.18829170f, 0.10522786f, + 0.04313190f, 0.01670948f, -0.08421925f, 0.05911417f, -0.10582602f, + -0.04855484f, -0.08373898f, 0.07775915f, 0.03723533f, -0.12047344f, + 4.86345543e-003f, -0.10520902f, 0.06571782f, -0.07528137f, + -0.03245651f, -0.09869066f, -0.02917477f, -0.18293270f, 0.14810945f, + 9.24033765e-003f, -0.04354914f, 0.02266885f, -0.11872729f, + -0.04016589f, 0.02830229f, 0.22539048f, 0.20565644f, 0.16701797f, + 0.09019924f, 0.01300652f, 0.09760600f, -0.03675831f, -0.01935448f, + -0.06894835f, 0.08077277f, 0.19047537f, 0.11312226f, 0.04106043f, + -0.11187182f, 0.04312806f, -0.18548580f, -0.11287174f, -0.08794551f, + 0.02078281f, -0.15295486f, 0.11806386f, -0.01103218f, -0.15971117f, + 0.02153538f, -0.05232147f, -0.10835317f, -0.13910367f, 0.05920752f, + -0.10122602f, 0.20174250f, 0.09105796f, -0.01881348f, 0.09559010f, + -0.03725745f, -0.09442931f, -0.09763174f, 0.05854454f, 0.08287182f, + 0.12919849f, 0.08594352f, -2.49806582e-003f, 0.02398440f, + 5.67950122e-003f, -0.06296340f, -0.12993270f, 0.03855852f, 0.05186560f, + 0.10839908f, -0.03380463f, -0.12654832f, -0.05399339f, -0.07456800f, + -0.04736232f, -0.10164231f, 0.07496139f, 0.08125214f, 0.07656177f, + -0.04999603f, -0.12823077f, -0.07692395f, -0.11317524f, -0.09118655f, + -0.05695669f, 0.10477209f, 0.07468581f, 0.01630048f, -8.00961629e-003f, + -0.06582128f, -0.04019095f, -0.04682907f, -0.01907842f, -0.10997720f, + 0.04911406f, 0.02931030f, 0.04197735f, -0.05773980f, -0.09670641f, + -0.03594951f, -0.03402121f, -0.07149299f, -0.10566200f, 0.10601286f, + 0.06340689f, -0.01518632f, -5.96402306e-003f, -0.07628012f, + -3.52779147e-003f, -0.02683854f, -0.10265494f, -0.02680815f, + 0.16338381f, 0.03103515f, 0.02296976f, 0.01624348f, -0.10831620f, + -0.02314233f, -0.04789969f, -0.05530700f, -0.06461314f, 0.10494506f, + 0.04642856f, -0.07592955f, -0.06197905f, -0.09042154f, -0.01445521f, + -0.04297818f, -0.11262015f, -0.11430512f, 0.03174541f, -0.03677487f, + -0.02963996f, -0.06610169f, -0.13292049f, -0.07059067f, -0.08444111f, + -0.02640536f, -0.07136250f, 0.04559967f, 0.01459980f, 0.17989251f, + 0.04435328f, -0.12464730f, -0.02871115f, -0.10752209f, -0.03393742f, + -0.03791408f, 0.02548251f, 0.01956050f, 0.19245651f, 0.13963254f, + -0.05904696f, -0.07424626f, -0.10411884f, 1.54176133e-003f, + 0.01797429f, 0.13025844f, 0.04547642f, -0.05710349f, -0.10697161f, + -0.13489437f, -0.06515755f, -0.06406886f, -4.08572936e-003f, + -0.01336483f, 0.04368737f, -0.11259720f, -0.05701635f, -0.06469971f, + -0.08346602f, -0.04166770f, -0.05795543f, -0.08247511f, -0.05742628f, + 0.08452254f, -0.03350224f, 0.13980860f, 0.13252275f, 0.07589617f, + 0.07539988f, 0.12155797f, 0.19087289f, 0.15050751f, 0.21250245f, + 0.14206800f, 0.01298489f, 0.07450245f, 0.06559097f, 0.01700557f, + 0.04512971f, 0.16950700f, 0.10261577f, 0.16389982f, 0.05505059f, + -0.03453077f, 0.08622462f, 0.07935954f, 0.03976260f, 0.02036091f, + 3.95744899e-003f, 0.03267065f, 0.15235919f, 0.01297494f, -0.08109194f, + 0.01407558f, 4.40693414e-003f, -0.15157418f, -0.11390478f, + -0.07487597f, -7.81322457e-003f, -0.02749545f, -0.10181408f, + 0.13755716f, 0.14007211f, 0.13482562f, 0.27517235f, 0.34251109f, + 0.07639657f, 0.07268607f, 0.19823882f, 0.16135791f, -0.04186463f, + -0.12784107f, -0.09846287f, 0.03169041f, 0.10974082f, -0.15051922f, + -0.08916726f, -0.07138767f, -0.04153349f, 6.25418453e-003f, + 0.01266654f, 0.10533249f, 0.12749144f, 0.15148053f, 0.01498513f, + 0.06305949f, -0.01247123f, -0.08778401f, -0.08551880f, -0.11955146f, + -0.08493572f, -0.02901620f, -0.02394859f, -0.13427313f, -0.11053200f, + -0.14413260f, -0.15203285f, 0.03972760f, -3.72127310e-004f, + -0.04200919f, 0.06105104f, 0.01904975f, -0.01106191f, + -7.27445772e-003f, -0.01520341f, 1.10228511e-003f, -0.04949187f, + -0.08013099f, 5.72071038e-003f, 0.08415454f, -0.06523152f, 0.03664081f, + -0.02673042f, -0.12066154f, -0.03702074f, 0.06006580f, 0.01628682f, + -6.17772620e-003f, 0.08192339f, -3.41629819e-003f, 0.02870512f, + 0.05807141f, 0.04959986f, 0.04618251f, -0.04901629f, -0.10579574f, + 0.02274442f, 0.12070961f, 2.23597488e-003f, 0.09831765f, -0.03019848f, + -0.11181970f, -0.04961075f, 0.02498928f, -0.03714991f, -0.01619653f, + 0.02643486f, -7.62964319e-003f, -0.02882290f, -0.06242594f, + -0.08439861f, 0.07220893f, 0.07263952f, 0.01561574f, 0.03091968f, + 0.01708712f, -0.03797151f, -3.18561122e-003f, 0.01624021f, + -0.02828573f, 0.11284444f, -1.32280716e-003f, -0.07784860f, + -0.07209100f, 0.03372242f, 0.12154529f, 0.02278104f, -0.05275500f, + -0.01918484f, 0.12989293f, 0.05424401f, 0.02333086f, 0.04029022f, + 0.12392918f, 0.09495489f, 0.09190340f, 0.07935889f, 8.76816828e-003f, + 0.17148446f, -8.51302687e-003f, -0.08011249f, -0.06796283f, + 0.04884845f, 0.01112272f, -0.07835306f, -1.14811445e-003f, + -0.03440760f, 0.02845243f, 0.07695542f, -0.07069533f, -0.01151784f, + -8.53884313e-003f, -0.01662786f, -0.04163864f, 0.05400505f, + 0.02859163f, 0.02921852f, 0.05003135f, -6.85718050e-003f, -0.01632611f, + 0.07780217f, 0.04042810f, -0.01216440f, 3.60914599e-003f, -0.06322435f, + 0.09516726f, 0.12877031f, -9.69162490e-003f, 0.01031179f, 0.05180895f, + -9.34659224e-003f, -0.01644533f, -0.04849347f, -0.04343236f, + 0.10514783f, 0.08046635f, -0.04615205f, -0.03975486f, -0.01485525f, + 0.13096830f, -0.01517950f, -0.06571898f, -0.04016372f, 0.01849786f, + 0.02439670f, 0.08067258f, 1.74824719e-003f, 0.07053747f, 0.08819518f, + -5.08352555e-003f, -0.06550863f, -0.08266170f, -0.07780605f, + 0.01453450f, -0.08756890f, 0.01096501f, -8.71319138e-003f, 0.10110464f, + 0.02420769f, -0.06708383f, 0.02007811f, 5.93133038e-003f, 0.05398923f, + 0.07538138f, 0.02049227f, 0.02242589f, 0.04011070f, -1.44875818e-003f, + -4.19115182e-003f, 0.06367654f, 0.02506934f, 0.02434536f, 0.05879405f, + -8.22952855e-003f, -0.01242441f, 0.04224926f, -0.01754923f, + 0.05958161f, 0.03818886f, -0.01830363f, -0.04308917f, -0.04422197f, + -0.02432721f, 0.02264866f, 2.03751423e-003f, 0.01197031f, 0.04439203f, + 0.12169247f, 0.03602713f, -0.02599251f, -1.98226492e-003f, 0.02046336f, + -0.02639058f, -1.91242550e-003f, -0.09334669f, -0.03595153f, + -9.88179818e-003f, -0.06848445f, -0.04666303f, -0.09955736f, + -0.04206430f, 0.02609075f, 9.09005292e-003f, -0.07138551f, + -4.22313227e-004f, 0.01766645f, 0.02756404f, 0.01308276f, 0.04052891f, + 0.02387515f, 0.05337298f, 0.02500631f, -0.04970853f, -0.12467445f, + 0.17604403f, 0.12256411f, -0.07512254f, 8.70451052e-003f, -0.05697548f, + -0.03626474f, -8.76623299e-003f, -0.01210897f, -0.09451522f, + 0.07490732f, -0.02008001f, -0.02681278f, -0.06463405f, -0.01517507f, + 7.33757764e-003f, 6.07147906e-003f, -0.09316964f, -0.04575328f, + 0.13261597f, 0.15424870f, -0.01655918f, -0.02772390f, -0.05243644f, + -0.02356456f, -0.02351753f, -0.10211615f, -0.12873036f, 0.14549787f, + 0.12519856f, 4.38762689e-003f, 0.02795992f, 0.05170322f, 0.09223596f, + 0.05890015f, 0.02376701f, -0.02777346f, 0.09506908f, 0.02328936f, + -0.02319928f, -0.03218696f, -0.01527841f, -0.01016694f, -0.02674719f, + 0.05137179f, 0.01980666f, 0.06544447f, -0.01746171f, 0.01026380f, + 0.01561806f, 7.97004555e-004f, 0.07601810f, 0.01907250f, -0.03083035f, + -0.05987392f, 0.09242783f, 0.14555025f, 0.01035827f, 0.03092401f, + -0.09562709f, -0.03802354f, 0.02531144f, 0.03079449f, -0.07100715f, + 0.03330721f, -2.69116857e-003f, 0.03167490f, 0.05744999f, 0.03259895f, + 1.91266940e-003f, 0.03194578f, 0.07389776f, 0.02198060f, 0.07633314f, + 0.03293105f, -0.09103648f, 0.04718142f, 0.06102672f, -0.01003063f, + 5.85481385e-003f, -0.01522574f, 0.02323526f, 0.10584345f, + 4.35879454e-003f, 0.06107873f, 0.05868603f, -0.03115531f, 0.01214679f, + 0.08567052f, 3.93926632e-003f, -0.02521488f, -1.88425183e-003f, + 0.02038053f, -6.26854831e-004f, 0.04897438f, -0.04280585f, + -0.04819689f, -0.04812867f, -0.01451186f, 0.05101469f, + -9.01125465e-003f, -0.03333859f, 0.03917955f, 0.04196448f, 0.04292135f, + 0.02809529f, 0.02999715f, 0.04081348f, 9.10039060e-003f, 0.09703232f, + 0.10379741f, 0.02348725f, -4.72756615e-003f, 0.01027325f, 0.10402658f, + 0.12071823f, 0.09817299f, -0.02612033f, 0.03638414f, 0.05896405f, + 0.04865025f, 0.04793910f, -0.03882321f, -0.02962117f, -0.01222268f, + 0.04071597f, 0.01922777f, -0.02287866f, 0.03328381f, 0.01859092f, + 0.09024994f, 0.03804455f, -0.01424510f, 0.01953739f, 0.02509617f, + -0.03390914f, -0.05663941f, -0.01641979f, 0.05848591f, 0.04639670f, + 0.02092116f, 0.12911791f, 0.19918139f, 0.07739855f, -7.25806039e-003f, + 0.04074838f, 0.03183993f, 1.39251316e-003f, -0.01428625f, 0.01865480f, + 0.08529541f, 0.13547510f, 0.11189661f, 0.03998901f, 0.09575938f, + -0.02631102f, -0.03458253f, -0.04749985f, -0.06070716f, + 4.71884012e-003f, 0.06445789f, -0.02450038f, -0.05483776f, + -0.04657237f, -0.02030717f, -0.03480766f, -0.09397731f, -0.06399718f, + -0.01804585f, 5.62348310e-003f, -6.64811488e-003f, -0.06517869f, + 6.96210237e-003f, -0.01860148f, -0.04245830f, -0.05850367f, + -3.24417115e-003f, 0.07700698f, 0.11290991f, 0.09923030f, -0.02970599f, + 0.05592411f, 0.04813979f, -0.09811195f, -0.09357996f, -0.03276114f, + 0.05218338f, 0.04141375f, 3.92977800e-003f, -0.05047480f, 0.15960084f, + 0.04612800f, -0.03114098f, -0.04650044f, -0.03249795f, -0.02425641f, + -0.04311355f, 0.04307659f, -0.09401883f, -0.04742785f, -0.01254499f, + -0.06598741f, 3.41369561e-003f, -0.05620445f, -7.28127593e-003f, + -0.05998361f, -0.03274450f, -0.07376868f, 3.19015374e-003f, + -0.07733069f, 0.05815864f, -0.02471071f, 0.03850617f, 0.13838784f, + 0.15399861f, 0.01731321f, -0.01477586f, 0.10393341f, 0.05159833f, + -0.01945555f, -0.03427503f, -0.04867341f, 0.09237480f, 0.10732719f, + 0.06071450f, -0.01355071f, 0.01844356f, -0.03480803f, -0.03796671f, + 2.15628621e-004f, -0.05440186f, 0.01889855f, -0.01443413f, + -0.02607902f, -0.02938001f, 0.02720689f, -0.06228397f, -0.02970936f, + -0.03426210f, -0.10280876f, -0.06739304f, -0.05227850f, 0.03360292f, + -0.11278441f, -0.06966180f, -0.13937433f, 9.10932291e-003f, + 2.52020749e-004f, -4.07359656e-003f, 0.12310639f, 0.09343060f, + 0.07302511f, 0.03222093f, 0.07532879f, 0.03792387f, -0.04985180f, + 0.01804602f, 0.02694195f, 0.13481498f, 0.04601225f, 0.04106982f, + 0.08511057f, 0.12314661f, 0.01320830f, 0.05044121f, -5.52943908e-003f, + -0.08992624f, -0.02249301f, -0.08181777f, 0.06165213f, -0.03256603f, + -0.01068920f, -0.01323473f, -0.11970232f, -0.04616347f, -0.12088681f, + -0.06762606f, -0.08676834f, -0.06434575f, 0.01772529f, 0.03469615f, + -0.10926618f, 0.03013873f, 0.14030397f, 0.16130108f, 0.17985588f, + 0.11281928f, 0.10530639f, 0.08905948f, 0.07733764f, 0.06695238f, + 0.02142088f, 0.06438877f, 0.09794453f, 0.05745072f, 0.02788557f, + 0.02632830f, 0.07985807f, 4.24902979e-003f, 8.47890321e-003f, + -0.02679466f, -5.28812688e-003f, -0.02162580f, -0.07490715f, + -0.08251337f, -0.02056576f, -0.01026194f, -1.15492963e-003f, + -5.75720915e-004f, -0.07210591f, -0.07320981f, -0.04883312f, + -0.10897151f, -0.07477258f, -0.08867134f, -0.09222437f, -0.10924666f, + -0.10430276f, 0.07953499f, 0.02767959f, 0.11393359f, 0.18779543f, + 0.03313421f, 0.02143700f, 0.05852016f, -2.12067598e-003f, + -3.76984011e-003f, 0.02774167f, -0.03124610f, 0.01465141f, 0.01616004f, + -0.01391913f, -0.04404102f, -0.05444227f, -0.14684731f, -0.15016587f, + 0.04509468f, 1.29563001e-003f, 0.01398350f, 0.05610404f, -0.04868806f, + -0.04776716f, -8.16873740e-003f, -2.30126386e-003f, -0.02286313f, + 0.11983398f, -0.04703261f, -0.08814441f, -0.07585249f, -0.10799607f, + -0.03232087f, 0.01509786f, -0.04843464f, -0.03967846f, 0.09589416f, + 0.01352560f, -0.01458119f, 0.01050829f, -0.03038946f, 0.01608388f, + 1.11975556e-003f, -0.01250656f, 2.86211423e-003f, 0.04333691f, + -0.14603497f, -0.01946543f, -0.02327525f, -0.01973944f, 0.07944400f, + -0.02224544f, -0.06701808f, 0.03476532f, 0.11505594f, -0.02712801f, + -0.01665113f, 0.06315716f, -0.08205860f, 0.07431999f, 0.04915778f, + -0.04468752f, -0.01490402f, 0.07400476f, -0.11650901f, 0.05102430f, + 0.04559118f, -0.05916039f, 0.08840760f, -0.01587902f, -0.14890194f, + 0.07857784f, 0.04710254f, -0.05381983f, -0.07331945f, -0.03604643f, + 0.15611970f, 0.07649943f, -0.05959348f, -0.02776607f, 0.11098688f, + 0.03758875f, -0.04446875f, 0.04933187f, 0.01345535f, 0.06921103f, + 0.07364785f, 0.05518956f, 0.02899585f, 0.09375840f, 0.10518434f, + -0.04420241f, 0.01915282f, -3.56386811e-003f, 0.14586878f, 0.10286101f, + -0.04360626f, -0.12723237f, 0.09076386f, 0.11119842f, -0.06035013f, + 0.09674817f, 0.08938243f, 0.07065924f, 0.02603180f, 5.84815582e-003f, + -0.05922065f, 0.12360309f, 3.59695964e-003f, 2.99844006e-003f, + 0.03697936f, 0.02043072f, 0.04168725f, 0.01025975f, -0.01359980f, + -0.01600920f, 0.02581056f, 0.02329250f, 2.98100687e-003f, 0.01629762f, + 0.06652115f, 0.05855627f, 0.01237463f, -0.01297135f, 0.01761587f, + 0.05090865f, 0.06549342f, -0.04425945f, 2.43203156e-003f, + 3.07327788e-003f, 0.06678630f, -0.04303836f, 0.01082393f, -0.06476044f, + 0.04077786f, 0.12441979f, 0.08237778f, 0.07424165f, 0.04065890f, + 0.06905543f, 0.09556347f, 0.12724875f, -0.02132082f, 0.08514154f, + -0.04175328f, -0.02666954f, 0.01897836f, 0.03317382f, 9.45465732e-003f, + -0.01238974f, -0.04242500f, -0.01419479f, -0.03545213f, -0.02440874f, + 0.08684119f, 0.04212951f, 0.02462858f, -0.01104825f, -5.01706870e-003f, + 0.02968982f, 0.02597476f, -0.01568939f, 0.04514892f, 0.06974549f, + 0.08670278f, 0.06828108f, 0.10238872f, 0.05405957f, 0.06548470f, + -0.03763957f, 0.01366090f, 0.07069602f, 0.05363748f, 0.04798120f, + 0.11706422f, 0.05466456f, -0.01869259f, 0.06344382f, 0.03106543f, + 0.08432506f, -0.02061096f, 0.03821088f, -6.92190882e-003f, + 6.40467042e-003f, -0.01271779f, 6.89014705e-005f, 0.04541415f, + -0.01899539f, -0.05020239f, 0.03000903f, 0.01090422f, 4.52452758e-003f, + 0.02573632f, -0.02388454f, -0.04200457f, 1.72783900e-003f, + -0.05978370f, -0.02720562f, 0.06573715f, 0.01154317f, 0.01265615f, + 0.07375994f, -9.19828378e-003f, -0.04914120f, 0.02124831f, 0.06455322f, + 0.04372910f, -0.03310043f, 0.03605788f, -6.78055827e-003f, + 9.36202332e-003f, 0.01747596f, -0.06406314f, -0.06812935f, 0.08080816f, + -0.02778088f, 0.02735260f, 0.06393493f, 0.06652229f, 0.05676993f, + 0.08640018f, -7.59188086e-003f, -0.02012847f, -0.04741159f, + -0.01657069f, -0.01624399f, 0.05547778f, -2.33309763e-003f, + 0.01120033f, 0.06141156f, -0.06285004f, -0.08732341f, -0.09313398f, + -0.04267832f, 5.57443965e-003f, 0.04809862f, 0.01773641f, + 5.37361018e-003f, 0.14842421f, -0.06298012f, -0.02935147f, 0.11443478f, + -0.05034208f, 5.65494271e-003f, 0.02076526f, -0.04577984f, + -0.04735741f, 0.02961071f, -0.09307127f, -0.04417921f, -0.04990027f, + -0.03940028f, 0.01306016f, 0.06267900f, 0.03758737f, 0.08460117f, + 0.13858789f, 0.04862388f, -0.06319809f, -0.05655516f, 0.01885816f, + -0.03285607f, 0.03371567f, -0.07040928f, -0.04514049f, 0.01392166f, + 0.08184422f, -0.07230316f, 0.02386871f, 0.02184591f, 0.02605764f, + -0.01033954f, 9.29878280e-003f, 7.67351175e-003f, 0.15189242f, + 0.02069071f, -0.09738296f, -0.08894105f, -0.07768748f, 0.02332268f, + -0.01778995f, -0.03258888f, -0.08180822f, -0.08492987f, 0.02290156f, + -0.11368170f, -0.03554465f, -0.04533844f, -0.02861580f, 0.06782424f, + 0.01113123f, 0.02453644f, 0.12721945f, 0.08084814f, -0.03607795f, + 0.01109122f, 0.04803548f, -0.03489929f, 0.03399536f, -0.05682014f, + 8.59533902e-003f, -4.27904585e-003f, 0.03230887f, -0.01300198f, + -0.01038137f, -0.07930113f, 8.33097473e-003f, 0.02296994f, + -0.01306500f, -0.01881626f, 0.04413369f, 0.05729880f, -0.03761553f, + 0.01942326f, 1.64540811e-003f, -0.03811319f, 0.04190650f, -0.14978096f, + -0.04514487f, 0.01209545f, -5.46460645e-003f, -0.01647195f, + 7.63064111e-003f, -0.07494587f, 0.08415288f, 0.10020141f, -0.01228561f, + 0.06553826f, 0.04554005f, 0.07890417f, 0.03041138f, 0.01752007f, + 0.09208256f, -3.74419295e-004f, 0.10549527f, 0.04686913f, 0.01894833f, + -0.02651412f, -4.34682379e-003f, 5.44942822e-003f, 0.01444484f, + 0.05882156f, -0.03336544f, 0.04603891f, -0.10432546f, 0.01923928f, + 0.01842845f, -0.01712168f, -0.02222766f, 0.04693324f, -0.06202956f, + -0.01422159f, 0.08732220f, -0.07706107f, 0.02661049f, -0.04300238f, + -0.03092422f, -0.03552184f, -0.01886088f, -0.04979934f, 0.03906401f, + 0.04608644f, 0.04966111f, 0.04275464f, -0.04621769f, -0.02653212f, + 8.57011229e-003f, 0.03839684f, 0.05818764f, 0.03880796f, + -2.76100676e-004f, 0.03076511f, -0.03266929f, -0.05374557f, + 0.04986527f, -9.45429131e-003f, 0.03582499f, -2.64564669e-003f, + -1.07461517e-003f, 0.02962313f, -0.01483363f, 0.03060869f, 0.02448327f, + 0.01845641f, 0.03282966f, -0.03534438f, -0.01084059f, -0.01119136f, + -1.85360224e-003f, -5.94652840e-004f, -0.04451817f, 2.98327743e-003f, + 0.06272484f, -0.02152076f, -3.05971340e-003f, -0.05070828f, + 0.01531762f, 0.01282815f, 0.05167150f, 9.46266949e-003f, + -3.34558333e-003f, 0.11442288f, -0.03906701f, -2.67325155e-003f, + 0.03069184f, -0.01134165f, 0.02949462f, 0.02879886f, 0.03855566f, + -0.03450781f, 0.09142872f, -0.02156654f, 0.06075062f, -0.06220816f, + 0.01944680f, 6.68372354e-003f, -0.06656796f, 8.70784000e-003f, + 0.03456013f, 0.02434320f, -0.13236357f, -0.04177035f, -0.02069627f, + 0.01068112f, 0.01505432f, -0.07517391f, -3.83571628e-003f, + -0.06298508f, -0.02881260f, -0.13101046f, -0.07221562f, + -5.79945277e-003f, -8.57300125e-003f, 0.03782469f, 0.02762164f, + 0.04942456f, -0.02936396f, 0.09597211f, 0.01921411f, 0.06101191f, + -0.04787507f, -0.01379578f, -7.40224449e-003f, -0.02220136f, + -0.01313756f, 7.77558051e-003f, 0.12296968f, 0.02939998f, 0.03594062f, + -0.07788624f, -0.01133144f, 3.99316690e-004f, -0.06090347f, + -0.01122066f, -4.68682544e-003f, 0.07633100f, -0.06748922f, + -0.05640298f, -0.05265681f, -0.01139122f, -0.01624347f, -0.04715714f, + -0.01099092f, 0.01048561f, 3.28499987e-003f, -0.05810167f, + -0.07699911f, -0.03330683f, 0.04185145f, 0.03478536f, 0.02275165f, + 0.02304766f, 6.66040834e-003f, 0.10968148f, -5.93013782e-003f, + -0.04858336f, -0.04203213f, -0.09316786f, -6.13074889e-003f, + -0.02544625f, 0.01366201f, 9.18555818e-003f, -0.01846578f, + -0.05622401f, -0.03989377f, -0.07810296f, 6.91275718e-003f, + 0.05957597f, -0.03901334f, 0.01572002f, -0.01193903f, + -6.89400872e-003f, -0.03093356f, -0.04136098f, -0.01562869f, + -0.04604580f, 0.02865234f, -0.08678447f, -0.03232484f, -0.05364593f, + -0.01445016f, -0.07003860f, -0.08669746f, -0.04520775f, 0.04274122f, + 0.03117515f, 0.08175703f, 0.01081109f, 0.06379741f, 0.06199206f, + 0.02865988f, 0.02360346f, 0.06725410f, -0.03248780f, -9.37702879e-003f, + 0.08265898f, -0.02245839f, 0.05125763f, -0.01862395f, 0.01973453f, + -0.01994494f, -0.10770868f, 0.03180375f, 3.23935156e-003f, + -0.02142080f, -0.04256190f, 0.04760900f, 0.04282863f, 0.05635953f, + -0.01870849f, 0.05540622f, -0.03042666f, 0.01455277f, -0.06630179f, + -0.05843807f, -0.03739681f, -0.09739155f, -0.03220233f, -0.05620182f, + -0.10381401f, 0.07400211f, 4.20676917e-003f, 0.03258535f, + 2.14308966e-003f, 0.05121966f, -0.01274337f, 0.02384761f, 0.06335578f, + -0.07905591f, 0.08375625f, -0.07898903f, -0.06508528f, -0.02498444f, + 0.06535810f, 0.03970535f, 0.04895468f, -0.01169566f, -0.03980601f, + 0.05682293f, 0.05925463f, -0.01165808f, -0.07936699f, -0.04208954f, + 0.01333987f, 0.09051196f, 0.10098671f, -0.03974256f, 0.01238771f, + -0.07501741f, -0.03655440f, -0.04301528f, 0.09216860f, + 4.63579083e-004f, 0.02851115f, 0.02142735f, 1.28244064e-004f, + 0.02879687f, -0.08554889f, -0.04838862f, 0.08135369f, -0.05756533f, + 0.01413900f, 0.03451880f, -0.06619488f, -0.03053130f, 0.02961676f, + -0.07384635f, 0.01135692f, 0.05283910f, -0.07778034f, -0.02107482f, + -0.05511716f, -0.13473752f, 0.03030157f, 0.06722020f, -0.06218817f, + -0.05826827f, 0.06254654f, 0.02895772f, -0.01664000f, -0.03620280f, + -0.01612278f, -1.46097376e-003f, 0.14013411f, -8.96181818e-003f, + -0.03250246f, 3.38630192e-003f, 2.64779478e-003f, 0.03359732f, + -0.02411991f, -0.04229729f, 0.10666174f, -6.66579151f }; + return std::vector(detector, detector + sizeof(detector)/sizeof(detector[0])); + } + +// This function renurn 1981 SVM coeffs obtained from daimler's base. +// To use these coeffs the detection window size should be (48,96) + std::vector HOGDescriptor::getDaimlerPeopleDetector() + { + static const float detector[] = { + 0.294350f, -0.098796f, -0.129522f, 0.078753f, + 0.387527f, 0.261529f, 0.145939f, 0.061520f, + 0.328699f, 0.227148f, -0.066467f, -0.086723f, + 0.047559f, 0.106714f, 0.037897f, 0.111461f, + -0.024406f, 0.304769f, 0.254676f, -0.069235f, + 0.082566f, 0.147260f, 0.326969f, 0.148888f, + 0.055270f, -0.087985f, 0.261720f, 0.143442f, + 0.026812f, 0.238212f, 0.194020f, 0.056341f, + -0.025854f, -0.034444f, -0.156631f, 0.205174f, + 0.089008f, -0.139811f, -0.100147f, -0.037830f, + -0.029230f, -0.055641f, 0.033248f, -0.016512f, + 0.155244f, 0.247315f, -0.124694f, -0.048414f, + -0.062219f, 0.193683f, 0.004574f, 0.055089f, + 0.093565f, 0.167712f, 0.167581f, 0.018895f, + 0.215258f, 0.122609f, 0.090520f, -0.067219f, + -0.049029f, -0.099615f, 0.241804f, -0.094893f, + -0.176248f, 0.001727f, -0.134473f, 0.104442f, + 0.050942f, 0.081165f, 0.072156f, 0.121646f, + 0.002656f, -0.297974f, -0.133587f, -0.060121f, + -0.092515f, -0.048974f, -0.084754f, -0.180111f, + -0.038590f, 0.086283f, -0.134636f, -0.107249f, + 0.132890f, 0.141556f, 0.249425f, 0.130273f, + -0.030031f, 0.073212f, -0.008155f, 0.019931f, + 0.071688f, 0.000300f, -0.019525f, -0.021725f, + -0.040993f, -0.086841f, 0.070124f, 0.240033f, + 0.265350f, 0.043208f, 0.166754f, 0.091453f, + 0.060916f, -0.036972f, -0.091043f, 0.079873f, + 0.219781f, 0.158102f, -0.140618f, -0.043016f, + 0.124802f, 0.093668f, 0.103208f, 0.094872f, + 0.080541f, 0.137711f, 0.160566f, -0.169231f, + 0.013983f, 0.309508f, -0.004217f, -0.057200f, + -0.064489f, 0.014066f, 0.361009f, 0.251328f, + -0.080983f, -0.044183f, 0.061436f, -0.037381f, + -0.078786f, 0.030993f, 0.066314f, 0.037683f, + 0.152325f, -0.091683f, 0.070203f, 0.217856f, + 0.036435f, -0.076462f, 0.006254f, -0.094431f, + 0.154829f, -0.023038f, -0.196961f, -0.024594f, + 0.178465f, -0.050139f, -0.045932f, -0.000965f, + 0.109112f, 0.046165f, -0.159373f, -0.008713f, + 0.041307f, 0.097129f, -0.057211f, -0.064599f, + 0.077165f, 0.176167f, 0.138322f, 0.065753f, + -0.104950f, 0.017933f, 0.136255f, -0.011598f, + 0.047007f, 0.080550f, 0.068619f, 0.084661f, + -0.035493f, -0.091314f, -0.041411f, 0.060971f, + -0.101912f, -0.079870f, -0.085977f, -0.022686f, + 0.079788f, -0.098064f, -0.054603f, 0.040383f, + 0.300794f, 0.128603f, 0.094844f, 0.047407f, + 0.101825f, 0.061832f, -0.162160f, -0.204553f, + -0.035165f, 0.101450f, -0.016641f, -0.027140f, + -0.134392f, -0.008743f, 0.102331f, 0.114853f, + 0.009644f, 0.062823f, 0.237339f, 0.167843f, + 0.053066f, -0.012592f, 0.043158f, 0.002305f, + 0.065001f, -0.038929f, -0.020356f, 0.152343f, + 0.043469f, -0.029967f, -0.042948f, 0.032481f, + 0.068488f, -0.110840f, -0.111083f, 0.111980f, + -0.002072f, -0.005562f, 0.082926f, 0.006635f, + -0.108153f, 0.024242f, -0.086464f, -0.189884f, + -0.017492f, 0.191456f, -0.007683f, -0.128769f, + -0.038017f, -0.132380f, 0.091926f, 0.079696f, + -0.106728f, -0.007656f, 0.172744f, 0.011576f, + 0.009883f, 0.083258f, -0.026516f, 0.145534f, + 0.153924f, -0.130290f, -0.108945f, 0.124490f, + -0.003186f, -0.100485f, 0.015024f, -0.060512f, + 0.026288f, -0.086713f, -0.169012f, 0.076517f, + 0.215778f, 0.043701f, -0.131642f, -0.012585f, + -0.045181f, -0.118183f, -0.241544f, -0.167293f, + -0.020107f, -0.019917f, -0.101827f, -0.107096f, + -0.010503f, 0.044938f, 0.189680f, 0.217119f, + -0.046086f, 0.044508f, 0.199716f, -0.036004f, + -0.148927f, 0.013355f, -0.078279f, 0.030451f, + 0.056301f, -0.024609f, 0.083224f, 0.099533f, + -0.039432f, -0.138880f, 0.005482f, -0.024120f, + -0.140468f, -0.066381f, -0.017057f, 0.009260f, + -0.058004f, -0.028486f, -0.061610f, 0.007483f, + -0.158309f, -0.150687f, -0.044595f, -0.105121f, + -0.045763f, -0.006618f, -0.024419f, -0.117713f, + -0.119366f, -0.175941f, -0.071542f, 0.119027f, + 0.111362f, 0.043080f, 0.034889f, 0.093003f, + 0.007842f, 0.057368f, -0.108834f, -0.079968f, + 0.230959f, 0.020205f, 0.011470f, 0.098877f, + 0.101310f, -0.030215f, -0.018018f, -0.059552f, + -0.106157f, 0.021866f, -0.036471f, 0.080051f, + 0.041165f, -0.082101f, 0.117726f, 0.030961f, + -0.054763f, -0.084102f, -0.185778f, -0.061305f, + -0.038089f, -0.110728f, -0.264010f, 0.076675f, + -0.077111f, -0.137644f, 0.036232f, 0.277995f, + 0.019116f, 0.107738f, 0.144003f, 0.080304f, + 0.215036f, 0.228897f, 0.072713f, 0.077773f, + 0.120168f, 0.075324f, 0.062730f, 0.122478f, + -0.049008f, 0.164912f, 0.162450f, 0.041246f, + 0.009891f, -0.097827f, -0.038700f, -0.023027f, + -0.120020f, 0.203364f, 0.248474f, 0.149810f, + -0.036276f, -0.082814f, -0.090343f, -0.027143f, + -0.075689f, -0.320310f, -0.000500f, -0.143334f, + -0.065077f, -0.186936f, 0.129372f, 0.116431f, + 0.181699f, 0.170436f, 0.418854f, 0.460045f, + 0.333719f, 0.230515f, 0.047822f, -0.044954f, + -0.068086f, 0.140179f, -0.044821f, 0.085550f, + 0.092483f, -0.107296f, -0.130670f, -0.206629f, + 0.114601f, -0.317869f, -0.076663f, 0.038680f, + 0.212753f, -0.016059f, -0.126526f, -0.163602f, + 0.210154f, 0.099887f, -0.126366f, 0.118453f, + 0.019309f, -0.021611f, -0.096499f, -0.111809f, + -0.200489f, 0.142854f, 0.228840f, -0.353346f, + -0.179151f, 0.116834f, 0.252389f, -0.031728f, + -0.188135f, -0.158998f, 0.386523f, 0.122315f, + 0.209944f, 0.394023f, 0.359030f, 0.260717f, + 0.170335f, 0.013683f, -0.142596f, -0.026138f, + -0.011878f, -0.150519f, 0.047159f, -0.107062f, + -0.147347f, -0.187689f, -0.186027f, -0.208048f, + 0.058468f, -0.073026f, -0.236556f, -0.079788f, + -0.146216f, -0.058563f, -0.101361f, -0.071294f, + -0.071093f, 0.116919f, 0.234304f, 0.306781f, + 0.321866f, 0.240000f, 0.073261f, -0.012173f, + 0.026479f, 0.050173f, 0.166127f, 0.228955f, + 0.061905f, 0.156460f, 0.205990f, 0.120672f, + 0.037350f, 0.167884f, 0.290099f, 0.420900f, + -0.012601f, 0.189839f, 0.306378f, 0.118383f, + -0.095598f, -0.072360f, -0.132496f, -0.224259f, + -0.126021f, 0.022714f, 0.284039f, 0.051369f, + -0.000927f, -0.058735f, -0.083354f, -0.141254f, + -0.187578f, -0.202669f, 0.048902f, 0.246597f, + 0.441863f, 0.342519f, 0.066979f, 0.215286f, + 0.188191f, -0.072240f, -0.208142f, -0.030196f, + 0.178141f, 0.136985f, -0.043374f, -0.181098f, + 0.091815f, 0.116177f, -0.126690f, -0.386625f, + 0.368165f, 0.269149f, -0.088042f, -0.028823f, + 0.092961f, 0.024099f, 0.046112f, 0.176756f, + 0.135849f, 0.124955f, 0.195467f, -0.037218f, + 0.167217f, 0.188938f, 0.053528f, -0.066561f, + 0.133721f, -0.070565f, 0.115898f, 0.152435f, + -0.116993f, -0.110592f, -0.179005f, 0.026668f, + 0.080530f, 0.075084f, -0.070401f, 0.012497f, + 0.021849f, -0.139764f, -0.022020f, -0.096301f, + -0.064954f, -0.127446f, -0.013806f, -0.108315f, + 0.156285f, 0.149867f, -0.011382f, 0.064532f, + 0.029168f, 0.027393f, 0.069716f, 0.153735f, + 0.038459f, 0.230714f, 0.253840f, 0.059522f, + -0.045053f, 0.014083f, 0.071103f, 0.068747f, + 0.095887f, 0.005832f, 0.144887f, 0.026357f, + -0.067359f, -0.044151f, -0.123283f, -0.019911f, + 0.005318f, 0.109208f, -0.003201f, -0.021734f, + 0.142025f, -0.066907f, -0.120070f, -0.188639f, + 0.012472f, -0.048704f, -0.012366f, -0.184828f, + 0.168591f, 0.267166f, 0.058208f, -0.044101f, + 0.033500f, 0.178558f, 0.104550f, 0.122418f, + 0.080177f, 0.173246f, 0.298537f, 0.064173f, + 0.053397f, 0.174341f, 0.230984f, 0.117025f, + 0.166242f, 0.227781f, 0.120623f, 0.176952f, + -0.011393f, -0.086483f, -0.008270f, 0.051700f, + -0.153369f, -0.058837f, -0.057639f, -0.060115f, + 0.026349f, -0.160745f, -0.037894f, -0.048575f, + 0.041052f, -0.022112f, 0.060365f, 0.051906f, + 0.162657f, 0.138519f, -0.050185f, -0.005938f, + 0.071301f, 0.127686f, 0.062342f, 0.144400f, + 0.072600f, 0.198436f, 0.246219f, -0.078185f, + -0.036169f, 0.075934f, 0.047328f, -0.013601f, + 0.087205f, 0.019900f, 0.022606f, -0.015365f, + -0.092506f, 0.075275f, -0.116375f, 0.050500f, + 0.045118f, 0.166567f, 0.072073f, 0.060371f, + 0.131747f, -0.169863f, -0.039352f, -0.047486f, + -0.039797f, -0.204312f, 0.021710f, 0.129443f, + -0.021173f, 0.173416f, -0.070794f, -0.063986f, + 0.069689f, -0.064099f, -0.123201f, -0.017372f, + -0.206870f, 0.065863f, 0.113226f, 0.024707f, + -0.071341f, -0.066964f, -0.098278f, -0.062927f, + 0.075840f, 0.014716f, 0.019378f, 0.132699f, + -0.074191f, -0.089557f, -0.078446f, -0.197488f, + -0.173665f, 0.052583f, 0.044361f, 0.113549f, + 0.098492f, 0.077379f, -0.011146f, -0.192593f, + -0.164435f, 0.045568f, 0.205699f, 0.049187f, + -0.082281f, 0.134874f, 0.185499f, 0.034968f, + -0.119561f, -0.112372f, -0.115091f, -0.054042f, + -0.183816f, -0.078100f, 0.190695f, 0.091617f, + 0.004257f, -0.041135f, -0.061453f, -0.141592f, + -0.194809f, -0.120638f, 0.020168f, 0.109672f, + 0.067398f, -0.015238f, -0.239145f, -0.264671f, + -0.185176f, 0.050472f, 0.020793f, 0.035678f, + 0.022839f, -0.052055f, -0.127968f, -0.113049f, + -0.228416f, -0.258281f, -0.053437f, 0.076424f, + 0.061450f, 0.237478f, 0.003618f, -0.055865f, + -0.108087f, -0.028937f, 0.045585f, 0.052829f, + -0.001471f, 0.022826f, 0.059565f, -0.104430f, + -0.077266f, -0.211882f, -0.212078f, 0.028074f, + 0.075846f, 0.016265f, 0.161879f, 0.134477f, + 0.008935f, -0.048041f, 0.074692f, 0.004928f, + -0.025156f, 0.192874f, 0.074410f, 0.308732f, + 0.267400f, 0.094208f, -0.005251f, 0.042041f, + -0.032148f, 0.015588f, 0.252869f, 0.175302f, + 0.022892f, 0.081673f, 0.063208f, 0.162626f, + 0.194426f, 0.233890f, 0.262292f, 0.186930f, + 0.084079f, -0.286388f, -0.213034f, -0.048867f, + -0.207669f, -0.170050f, 0.011673f, -0.092958f, + -0.192786f, -0.273536f, 0.230904f, 0.266732f, + 0.320519f, 0.297155f, 0.548169f, 0.304922f, + 0.132687f, 0.247333f, 0.212488f, -0.271472f, + -0.142105f, -0.002627f, -0.119215f, 0.128383f, + 0.100079f, -0.057490f, -0.121902f, -0.228892f, + 0.202292f, -0.399795f, -0.371326f, -0.095836f, + -0.063626f, -0.161375f, -0.311180f, -0.294797f, + 0.242122f, 0.011788f, 0.095573f, 0.322523f, + 0.511840f, 0.322880f, 0.313259f, 0.173331f, + 0.002542f, -0.029802f, 0.324766f, -0.326170f, + -0.340547f, -0.138288f, -0.002963f, -0.114060f, + -0.377312f, -0.442570f, 0.212446f, -0.007759f, + -0.011576f, 0.169711f, 0.308689f, 0.317348f, + 0.539390f, 0.332845f, 0.057331f, -0.068180f, + 0.101994f, 0.266995f, 0.209570f, 0.355730f, + 0.091635f, 0.170238f, 0.125215f, 0.274154f, + 0.070223f, 0.025515f, 0.049946f, -0.000550f, + 0.043715f, -0.141843f, 0.020844f, 0.129871f, + 0.256588f, 0.105015f, 0.148339f, 0.170682f, + 0.028792f, 0.074037f, 0.160042f, 0.405137f, + 0.246187f, 0.352160f, 0.168951f, 0.222263f, + 0.264439f, 0.065945f, 0.021963f, -0.075084f, + 0.093105f, 0.027318f, 0.098864f, 0.057566f, + -0.080282f, 0.185032f, 0.314419f, 0.333727f, + 0.125798f, 0.294919f, 0.386002f, 0.217619f, + -0.183517f, -0.278622f, -0.002342f, -0.027821f, + -0.134266f, -0.331843f, -0.008296f, 0.124564f, + 0.053712f, -0.369016f, -0.095036f, 0.209381f, + 0.423760f, 0.371760f, 0.106397f, 0.369408f, + 0.485608f, 0.231201f, -0.138685f, -0.349208f, + -0.070083f, 0.028991f, -0.081630f, -0.395992f, + -0.146791f, -0.027354f, 0.063396f, -0.272484f, + 0.058299f, 0.338207f, 0.110767f, -0.052642f, + -0.233848f, -0.027448f, 0.030328f, 0.155572f, + -0.093826f, 0.019331f, 0.120638f, 0.006292f, + -0.106083f, -0.236290f, -0.140933f, -0.088067f, + -0.025138f, -0.208395f, -0.025502f, 0.144192f, + -0.048353f, -0.106144f, -0.305121f, -0.114147f, + 0.090963f, 0.327727f, 0.035606f, -0.093779f, + 0.002651f, -0.171081f, -0.188131f, -0.216571f, + -0.209101f, -0.054402f, 0.157147f, -0.057127f, + 0.066584f, 0.008988f, 0.041191f, 0.034456f, + -0.078255f, 0.052099f, -0.022239f, 0.066981f, + -0.117520f, -0.072637f, 0.062512f, 0.037570f, + -0.057544f, -0.312359f, 0.034357f, -0.031549f, + 0.002566f, -0.207375f, -0.070654f, -0.018786f, + -0.044815f, -0.012814f, -0.076320f, 0.078183f, + 0.023877f, 0.117078f, 0.022292f, -0.205424f, + -0.060430f, -0.017296f, -0.004827f, -0.321036f, + -0.092155f, 0.038837f, 0.073190f, -0.067513f, + 0.026521f, 0.171945f, 0.087318f, 0.034495f, + -0.034089f, 0.154410f, -0.061431f, 0.007435f, + -0.111094f, -0.095976f, 0.014741f, -0.132324f, + -0.029517f, -0.192160f, 0.098667f, 0.020762f, + 0.177050f, -0.064510f, -0.054437f, -0.058678f, + -0.001858f, 0.167602f, 0.015735f, 0.054338f, + 0.016477f, 0.186381f, -0.010667f, 0.054692f, + 0.126742f, 0.013140f, 0.090353f, -0.133608f, + -0.018017f, -0.152619f, 0.027600f, -0.138700f, + -0.050274f, 0.045141f, -0.118731f, 0.094797f, + -0.167605f, 0.097461f, -0.009131f, 0.199920f, + -0.052976f, 0.158194f, 0.178568f, -0.107600f, + 0.009671f, -0.084072f, -0.040258f, -0.205673f, + 0.102891f, 0.223511f, 0.042699f, 0.118548f, + -0.021274f, 0.110997f, -0.155121f, 0.027696f, + -0.149968f, 0.051552f, -0.129219f, 0.173524f, + 0.073972f, -0.189045f, -0.034523f, -0.106655f, + -0.011843f, -0.197381f, 0.219413f, 0.183197f, + -0.054920f, 0.144955f, 0.036517f, -0.085412f, + -0.229070f, -0.143710f, -0.049486f, 0.156634f, + -0.008673f, -0.064778f, 0.082344f, 0.145673f, + 0.002912f, -0.210121f, -0.116564f, 0.078425f, + 0.220908f, -0.067594f, 0.048610f, 0.084912f, + -0.066202f, -0.112515f, -0.217767f, -0.082640f, + -0.017414f, 0.230265f, -0.070735f, 0.066073f, + 0.215256f, 0.071157f, -0.087220f, -0.202235f, + -0.011918f, 0.099562f, 0.174716f, -0.063845f, + -0.121055f, 0.014367f, 0.132709f, -0.005060f, + -0.244606f, -0.179693f, -0.134690f, 0.023239f, + -0.193116f, -0.076975f, -0.021164f, -0.001938f, + -0.163799f, -0.111437f, -0.210362f, -0.166376f, + 0.034754f, 0.010036f, -0.021917f, 0.068014f, + -0.086893f, -0.251746f, -0.267171f, 0.037383f, + 0.003966f, 0.033571f, -0.151506f, 0.025437f, + -0.020626f, -0.308454f, -0.343143f, -0.092263f, + -0.026261f, -0.028345f, 0.036036f, 0.035169f, + 0.129470f, 0.122205f, 0.015661f, -0.070612f, + -0.094333f, -0.066055f, -0.041083f, 0.159146f, + 0.073184f, 0.110044f, 0.174471f, 0.078069f, + -0.014881f, 0.008116f, 0.013209f, 0.075857f, + 0.195605f, 0.062714f, 0.067955f, 0.056544f, + -0.153908f, -0.141749f, -0.072550f, 0.033523f, + -0.024665f, 0.134487f, 0.079076f, 0.133562f, + 0.227130f, 0.018054f, 0.004928f, 0.169162f, + 0.065152f, 0.072160f, 0.131631f, 0.096303f, + 0.054288f, 0.106256f, 0.114632f, 0.119038f, + 0.515200f, 0.247429f, 0.199134f, 0.211957f, + 0.127558f, -0.294684f, -0.194890f, -0.049988f, + -0.112247f, -0.008122f, -0.006176f, 0.037035f, + -0.110881f, -0.249989f, 0.152434f, 0.234621f, + 0.153340f, 0.349283f, 0.683049f, 0.157174f, + 0.124844f, 0.099136f, 0.064407f, -0.248400f, + -0.155323f, -0.026498f, -0.023450f, 0.049051f, + -0.114187f, 0.007195f, -0.176825f, -0.376926f, + 0.366159f, -0.179938f, -0.148508f, 0.006043f, + 0.170048f, 0.097866f, -0.102658f, -0.260430f, + 0.248868f, 0.037019f, -0.118111f, 0.078176f, + 0.194171f, 0.211328f, 0.368612f, 0.361213f, + 0.130013f, 0.094650f, 0.227396f, -0.178058f, + -0.114782f, -0.008093f, 0.231080f, -0.011843f, + -0.097917f, -0.325788f, 0.141879f, 0.119738f, + -0.230427f, -0.117419f, -0.114153f, 0.037903f, + 0.116383f, 0.218773f, -0.101884f, 0.059466f, + 0.119255f, 0.010874f, -0.031449f, 0.045996f, + 0.119931f, 0.273760f, 0.311700f, 0.261794f, + 0.194809f, 0.339829f, 0.239449f, 0.064140f, + 0.077597f, 0.098996f, 0.143534f, 0.184602f, + 0.037507f, 0.225494f, 0.096142f, -0.147370f, + -0.207833f, -0.174742f, -0.086391f, -0.038942f, + 0.159577f, -0.088492f, -0.000989f, 0.108154f, + -0.025890f, -0.072713f, 0.025997f, -0.006803f, + -0.086879f, -0.011290f, -0.269200f, -0.103450f, + -0.124910f, -0.116340f, 0.141459f, 0.208800f, + 0.042268f, 0.265034f, 0.516474f, 0.217591f, + -0.018843f, -0.313328f, -0.168363f, 0.047129f, + 0.090480f, -0.109852f, -0.018761f, 0.210669f, + 0.281269f, -0.043591f, -0.034147f, -0.237772f, + -0.134843f, -0.072481f, -0.103831f, 0.038355f, + 0.308619f, 0.148023f, -0.045867f, -0.123950f, + -0.210860f, -0.064973f, -0.036308f, -0.046731f, + -0.022099f, 0.095776f, 0.409423f, 0.060635f, + -0.065196f, 0.051828f, 0.027981f, -0.009609f, + -0.137681f, -0.095011f, -0.019045f, 0.177278f, + 0.009759f, -0.092119f, -0.016958f, -0.133860f, + -0.118421f, -0.032039f, -0.006214f, -0.084541f, + 0.063971f, -0.073642f, 0.165676f, 0.110443f, + 0.044131f, 0.046568f, 0.053292f, -0.055466f, + 0.015512f, 0.371947f, 0.232102f, -0.016923f, + 0.103979f, -0.091758f, 0.005907f, 0.209100f, + 0.157433f, 0.030518f, 0.250366f, 0.062322f, + 0.036720f, 0.094676f, 0.017306f, -0.010328f, + -0.079012f, 0.016781f, -0.112435f, 0.061795f, + 0.042543f, -0.126799f, -0.009975f, -0.056760f, + 0.046424f, -0.194712f, -0.139399f, -0.037731f, + 0.157989f, -0.016261f, 0.123345f, 0.230563f, + 0.083300f, -0.016392f, 0.059567f, -0.016035f, + -0.064767f, 0.231945f, 0.156629f, 0.034602f, + 0.145628f, 0.041315f, 0.034535f, 0.019967f, + -0.089188f, -0.012091f, 0.307857f, 0.211405f, + -0.025091f, -0.148249f, -0.129384f, 0.063536f, + -0.068603f, -0.067941f, -0.035104f, 0.210832f, + 0.063810f, 0.062764f, -0.089889f, -0.030554f, + 0.014791f, -0.053362f, -0.037818f, -0.196640f, + 0.008388f, -0.082654f, 0.143056f, 0.064221f, + 0.069795f, 0.191040f, 0.097321f, -0.028679f, + 0.075794f, 0.313154f, 0.086240f, 0.207643f, + 0.017809f, 0.122867f, 0.224586f, 0.167403f, + -0.023884f, 0.047434f, 0.344091f, 0.187745f, + 0.136177f, 0.141738f, 0.063799f, 0.045233f, + -0.077342f, -0.003525f, -0.165041f, -0.025616f, + -0.073745f, 0.164439f, 0.011200f, -0.145896f, + -0.027954f, -0.061987f, -0.039874f, -0.142775f, + 0.151042f, -0.038238f, 0.053152f, 0.078615f, + 0.086061f, 0.100593f, 0.128046f, -0.071006f, + -0.116558f, 0.208445f, 0.051086f, 0.076843f, + 0.023191f, -0.084781f, -0.011790f, 0.147807f, + -0.048554f, -0.113932f, 0.283322f, 0.190934f, + 0.092789f, 0.033018f, -0.142428f, -0.142480f, + -0.099023f, -0.041020f, -0.042760f, 0.203295f, + -0.053475f, 0.042424f, 0.222839f, -0.019167f, + -0.133176f, -0.276216f, -0.031998f, 0.117290f, + 0.177827f, -0.059973f, -0.064744f, -0.117040f, + -0.155482f, -0.099531f, 0.164121f, -0.026682f, + -0.093810f, 0.238993f, -0.006506f, 0.007830f, + 0.065819f, -0.203643f, -0.100925f, -0.053652f, + -0.130770f, 0.026277f, 0.131796f, 0.032742f, + 0.127186f, 0.116694f, -0.161122f, -0.279773f, + -0.252515f, -0.002638f, 0.042812f, 0.096776f, + -0.123280f, 0.064858f, -0.010455f, -0.219760f, + -0.239331f, -0.104363f, -0.058022f, -0.053584f, + 0.025611f, 0.005129f, -0.100418f, -0.045712f, + -0.194418f, -0.126366f, -0.030530f, 0.051168f, + 0.215959f, 0.172402f, -0.054700f, -0.185995f, + -0.278360f, -0.193693f, -0.040309f, 0.003735f, + -0.007770f, 0.123556f, 0.190179f, -0.077315f, + 0.117403f, 0.212942f, 0.012160f, 0.000113f, + 0.027331f, 0.040202f, 0.033293f, 0.219438f, + 0.184174f, 0.259349f, 0.311206f, 0.082547f, + -0.047875f, -0.078417f, 0.010746f, 0.082620f, + 0.311931f, 0.307605f, 0.003863f, 0.021405f, + -0.026388f, -0.019572f, 0.020582f, -0.059353f, + 0.025199f, 0.261319f, 0.086316f, 0.143614f, + 0.107780f, 0.003900f, -0.188397f, -0.038563f, + -0.106045f, -0.125154f, -0.010509f, 0.054021f, + 0.242130f, 0.279152f, 0.215546f, 0.346995f, + 0.440856f, 0.237452f, 0.234154f, 0.301646f, + 0.168929f, -0.208358f, -0.126848f, 0.010260f, + 0.121018f, -0.062975f, -0.052848f, 0.050341f, + -0.061103f, -0.266482f, 0.107186f, 0.140221f, + 0.280065f, 0.287889f, 0.373198f, 0.151596f, + 0.013593f, 0.115616f, 0.014616f, -0.281710f, + -0.237597f, -0.117305f, -0.000034f, -0.136739f, + -0.196275f, -0.095225f, -0.125310f, -0.250514f, + 0.236804f, -0.071805f, -0.037421f, 0.048230f, + 0.321596f, 0.063632f, 0.024039f, -0.029133f, + 0.230983f, 0.160593f, -0.154355f, -0.013086f, + -0.079929f, 0.094692f, 0.160391f, 0.180239f, + 0.053895f, 0.100759f, 0.288631f, 0.038191f, + 0.181692f, 0.229682f, 0.440166f, 0.063401f, + 0.006273f, 0.020865f, 0.338695f, 0.256244f, + -0.043927f, 0.115617f, 0.003296f, 0.173965f, + 0.021318f, -0.040936f, -0.118932f, 0.182380f, + 0.235922f, -0.053233f, -0.015053f, -0.101057f, + 0.095341f, 0.051111f, 0.161831f, 0.032614f, + 0.159496f, 0.072375f, 0.025089f, 0.023748f, + 0.029151f, 0.161284f, -0.117717f, -0.036191f, + -0.176822f, -0.162006f, 0.226542f, -0.078329f, + 0.043079f, -0.119172f, 0.054614f, -0.101365f, + -0.064541f, -0.115304f, 0.135170f, 0.298872f, + 0.098060f, 0.089428f, -0.007497f, 0.110391f, + -0.028824f, 0.020835f, -0.036804f, 0.125411f, + 0.192105f, -0.048931f, 0.003086f, -0.010681f, + 0.074698f, -0.016263f, 0.096063f, 0.060267f, + -0.007277f, 0.139139f, -0.080635f, 0.036628f, + 0.086058f, 0.131979f, 0.085707f, 0.025301f, + 0.226094f, 0.194759f, 0.042193f, -0.157846f, + -0.068402f, -0.141450f, -0.112659f, -0.076305f, + -0.069085f, -0.114332f, -0.102005f, 0.132193f, + -0.067042f, 0.106643f, 0.198964f, 0.171616f, + 0.167237f, -0.033730f, -0.026755f, 0.083621f, + 0.149459f, -0.002799f, -0.000318f, 0.011753f, + 0.065889f, -0.089375f, -0.049610f, 0.224579f, + 0.216548f, -0.034908f, -0.017851f, -0.088144f, + 0.007530f, 0.240268f, 0.073270f, 0.013263f, + 0.175323f, 0.012082f, 0.093993f, 0.015282f, + 0.105854f, 0.107990f, 0.077798f, -0.096166f, + -0.079607f, 0.177820f, 0.142392f, 0.033337f, + -0.078100f, -0.081616f, -0.046993f, 0.139459f, + 0.020272f, -0.123161f, 0.175269f, 0.105217f, + 0.057328f, 0.080909f, -0.012612f, -0.097081f, + 0.082060f, -0.096716f, -0.063921f, 0.201884f, + 0.128166f, -0.035051f, -0.032227f, -0.068139f, + -0.115915f, 0.095080f, -0.086007f, -0.067543f, + 0.030776f, 0.032712f, 0.088937f, 0.054336f, + -0.039329f, -0.114022f, 0.171672f, -0.112321f, + -0.217646f, 0.065186f, 0.060223f, 0.192174f, + 0.055580f, -0.131107f, -0.144338f, 0.056730f, + -0.034707f, -0.081616f, -0.135298f, -0.000614f, + 0.087189f, 0.014614f, 0.067709f, 0.107689f, + 0.225780f, 0.084361f, -0.008544f, 0.051649f, + -0.048369f, -0.037739f, -0.060710f, 0.002654f, + 0.016935f, 0.085563f, -0.015961f, -0.019265f, + 0.111788f, 0.062376f, 0.202019f, 0.047713f, + 0.042261f, 0.069716f, 0.242913f, 0.021052f, + -0.072812f, -0.155920f, -0.026436f, 0.035621f, + -0.079300f, -0.028787f, -0.048329f, 0.084718f, + -0.060565f, -0.083750f, -0.164075f, -0.040742f, + -0.086219f, 0.015271f, -0.005204f, -0.016038f, + 0.045816f, -0.050433f, -0.077652f, 0.117109f, + 0.009611f, -0.009045f, -0.008634f, -0.055373f, + -0.085968f, 0.028527f, -0.054736f, -0.168089f, + 0.175839f, 0.071205f, -0.023603f, 0.037907f, + -0.004561f, -0.022634f, 0.123831f, 0.094469f, + -0.072920f, -0.133642f, -0.014032f, -0.142754f, + -0.026999f, -0.199409f, 0.013268f, 0.226989f, + 0.048650f, -0.170988f, -0.050141f, 0.007880f, + 0.061880f, 0.019078f, -0.043578f, -0.038139f, + 0.134814f, 0.054097f, -0.081670f, 0.176838f, + 0.047920f, -0.038176f, 0.050406f, -0.107181f, + -0.036279f, 0.027060f, 0.081594f, -0.002820f, + 0.090507f, -0.033338f, -0.059571f, 0.013404f, + -0.099860f, 0.073371f, 0.342805f, 0.098305f, + -0.150910f, -0.020822f, -0.056960f, 0.046262f, + -0.043413f, -0.149405f, -0.129105f, -0.010899f, + -0.014229f, -0.179949f, -0.113044f, -0.049468f, + -0.065513f, 0.090269f, -0.011919f, 0.087846f, + 0.095796f, 0.146127f, 0.101599f, 0.078066f, + -0.084348f, -0.100002f, -0.020134f, -0.050169f, + 0.062122f, 0.014640f, 0.019143f, 0.036543f, + 0.180924f, -0.013976f, -0.066768f, -0.001090f, + -0.070419f, -0.004839f, -0.001504f, 0.034483f, + -0.044954f, -0.050336f, -0.088638f, -0.174782f, + -0.116082f, -0.205507f, 0.015587f, -0.042839f, + -0.096879f, -0.144097f, -0.050268f, -0.196796f, + 0.109639f, 0.271411f, 0.173732f, 0.108070f, + 0.156437f, 0.124255f, 0.097242f, 0.238693f, + 0.083941f, 0.109105f, 0.223940f, 0.267188f, + 0.027385f, 0.025819f, 0.125070f, 0.093738f, + 0.040353f, 0.038645f, -0.012730f, 0.144063f, + 0.052931f, -0.009138f, 0.084193f, 0.160272f, + -0.041366f, 0.011951f, -0.121446f, -0.106713f, + -0.047566f, 0.047984f, -0.255224f, -0.076116f, + 0.098685f, -0.150845f, -0.171513f, -0.156590f, + 0.058331f, 0.187493f, 0.413018f, 0.554265f, + 0.372242f, 0.237943f, 0.124571f, 0.110829f, + 0.010322f, -0.174477f, -0.067627f, -0.001979f, + 0.142913f, 0.040597f, 0.019907f, 0.025963f, + -0.043585f, -0.120732f, 0.099937f, 0.091059f, + 0.247307f, 0.204226f, -0.042753f, -0.068580f, + -0.119002f, 0.026722f, 0.034853f, -0.060934f, + -0.025054f, -0.093026f, -0.035372f, -0.233209f, + -0.049869f, -0.039151f, -0.022279f, -0.065380f, + -9.063785f}; + return std::vector(detector, detector + sizeof(detector)/sizeof(detector[0])); + } + + class HOGConfInvoker : + public ParallelLoopBody + { + public: + HOGConfInvoker( const HOGDescriptor* _hog, const Mat& _img, + double _hitThreshold, const Size& _padding, + std::vector* locs, + std::vector* _vec, Mutex* _mtx ) + { + hog = _hog; + img = _img; + hitThreshold = _hitThreshold; + padding = _padding; + locations = locs; + vec = _vec; + mtx = _mtx; + } + + void operator()(const Range& range) const CV_OVERRIDE + { + CV_INSTRUMENT_REGION(); + + int i, i1 = range.start, i2 = range.end; + + Size maxSz(cvCeil(img.cols/(*locations)[0].scale), cvCeil(img.rows/(*locations)[0].scale)); + Mat smallerImgBuf(maxSz, img.type()); + std::vector dets; + + for (i = i1; i < i2; i++) + { + double scale = (*locations)[i].scale; + + Size sz(cvRound(img.cols / scale), cvRound(img.rows / scale)); + Mat smallerImg(sz, img.type(), smallerImgBuf.ptr()); + + if (sz == img.size()) + smallerImg = Mat(sz, img.type(), img.data, img.step); + else + resize(img, smallerImg, sz, 0, 0, INTER_LINEAR_EXACT); + + hog->detectROI(smallerImg, (*locations)[i].locations, dets, (*locations)[i].confidences, hitThreshold, Size(), padding); + Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); + mtx->lock(); + for (size_t j = 0; j < dets.size(); j++) + vec->push_back(Rect(cvRound(dets[j].x*scale), + cvRound(dets[j].y*scale), + scaledWinSize.width, scaledWinSize.height)); + mtx->unlock(); + } + } + + const HOGDescriptor* hog; + Mat img; + double hitThreshold; + std::vector* locations; + Size padding; + std::vector* vec; + Mutex* mtx; + }; + + void HOGDescriptor::detectROI(const cv::Mat& img, const std::vector &locations, + CV_OUT std::vector& foundLocations, CV_OUT std::vector& confidences, + double hitThreshold, cv::Size winStride, cv::Size padding) const + { + CV_INSTRUMENT_REGION(); + + foundLocations.clear(); + confidences.clear(); + + if (svmDetector.empty() || locations.empty()) + return; + + if (winStride == Size()) + winStride = cellSize; + Size cacheStride(gcd(winStride.width, blockStride.width), + gcd(winStride.height, blockStride.height)); + + size_t nwindows = locations.size(); + padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width); + padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height); + Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2); + + // HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride); + HOGCache cache(this, img, padding, padding, true, cacheStride); + if (!nwindows) + nwindows = cache.windowsInImage(paddedImgSize, winStride).area(); + + const HOGCache::BlockData* blockData = &cache.blockData[0]; + + int nblocks = cache.nblocks.area(); + int blockHistogramSize = cache.blockHistogramSize; + size_t dsize = getDescriptorSize(); + + double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0; + std::vector blockHist(blockHistogramSize); + +#if CV_SIMD128 + float partSum[4]; +#endif + + for (size_t i = 0; i < nwindows; i++) + { + Point pt0; + pt0 = locations[i]; + if (pt0.x < -padding.width || pt0.x > img.cols + padding.width - winSize.width || + pt0.y < -padding.height || pt0.y > img.rows + padding.height - winSize.height) + { + // out of image + confidences.push_back(-10.0); + continue; + } + + double s = rho; + const float* svmVec = &svmDetector[0]; + int j, k; + + for (j = 0; j < nblocks; j++, svmVec += blockHistogramSize) + { + const HOGCache::BlockData& bj = blockData[j]; + Point pt = pt0 + bj.imgOffset; + + // need to divide this into 4 parts! + const float* vec = cache.getBlock(pt, &blockHist[0]); +#if CV_SIMD128 + v_float32x4 _vec = v_load(vec); + v_float32x4 _svmVec = v_load(svmVec); + v_float32x4 sum = _svmVec * _vec; + + for (k = 4; k <= blockHistogramSize - 4; k += 4) + { + _vec = v_load(vec + k); + _svmVec = v_load(svmVec + k); + + sum += _vec * _svmVec; + } + + v_store(partSum, sum); + + double t0 = partSum[0] + partSum[1]; + double t1 = partSum[2] + partSum[3]; + s += t0 + t1; +#else + for (k = 0; k <= blockHistogramSize - 4; k += 4) + s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] + + vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3]; +#endif + for ( ; k < blockHistogramSize; k++) + s += vec[k]*svmVec[k]; + } + confidences.push_back(s); + + if (s >= hitThreshold) + foundLocations.push_back(pt0); + } + } + + void HOGDescriptor::detectMultiScaleROI(const cv::Mat& img, + CV_OUT std::vector& foundLocations, std::vector& locations, + double hitThreshold, int groupThreshold) const + { + CV_INSTRUMENT_REGION(); + + std::vector allCandidates; + Mutex mtx; + + parallel_for_(Range(0, (int)locations.size()), + HOGConfInvoker(this, img, hitThreshold, Size(8, 8), + &locations, &allCandidates, &mtx)); + + foundLocations.resize(allCandidates.size()); + std::copy(allCandidates.begin(), allCandidates.end(), foundLocations.begin()); + cv::groupRectangles(foundLocations, groupThreshold, 0.2); + } + + void HOGDescriptor::readALTModel(String modelfile) + { + // read model from SVMlight format.. + FILE *modelfl; + if ((modelfl = fopen(modelfile.c_str(), "rb")) == NULL) + { + String eerr("file not exist"); + String efile(__FILE__); + String efunc(__FUNCTION__); + throw Exception(Error::StsError, eerr, efile, efunc, __LINE__); + } + char version_buffer[10]; + if (!fread (&version_buffer,sizeof(char),10,modelfl)) + { + String eerr("version?"); + String efile(__FILE__); + String efunc(__FUNCTION__); + fclose(modelfl); + + throw Exception(Error::StsError, eerr, efile, efunc, __LINE__); + } + if (strcmp(version_buffer,"V6.01")) { + String eerr("version does not match"); + String efile(__FILE__); + String efunc(__FUNCTION__); + fclose(modelfl); + + throw Exception(Error::StsError, eerr, efile, efunc, __LINE__); + } + /* read version number */ + int version = 0; + if (!fread (&version,sizeof(int),1,modelfl)) + { fclose(modelfl); throw Exception(); } + if (version < 200) + { + String eerr("version does not match"); + String efile(__FILE__); + String efunc(__FUNCTION__); + fclose(modelfl); + throw Exception(); + } + int kernel_type; + size_t nread; + nread=fread(&(kernel_type),sizeof(int),1,modelfl); - for(int i = 0; i < length; i++) - detector.push_back((float)linearwt[i]); + {// ignore these + int poly_degree; + nread=fread(&(poly_degree),sizeof(int),1,modelfl); - detector.push_back((float)-linearbias); - setSVMDetector(detector); - delete [] linearwt; - } else { + double rbf_gamma; + nread=fread(&(rbf_gamma),sizeof(double), 1, modelfl); + double coef_lin; + nread=fread(&(coef_lin),sizeof(double),1,modelfl); + double coef_const; + nread=fread(&(coef_const),sizeof(double),1,modelfl); + int l; + nread=fread(&l,sizeof(int),1,modelfl); + CV_Assert(l >= 0 && l < 0xFFFF); + char* custom = new char[l]; + nread=fread(custom,sizeof(char),l,modelfl); + delete[] custom; + } + int totwords; + nread=fread(&(totwords),sizeof(int),1,modelfl); + {// ignore these + int totdoc; + nread=fread(&(totdoc),sizeof(int),1,modelfl); + int sv_num; + nread=fread(&(sv_num), sizeof(int),1,modelfl); + } + + double linearbias; + nread=fread(&linearbias, sizeof(double), 1, modelfl); + + std::vector detector; + detector.clear(); + if (kernel_type == 0) { /* linear kernel */ + /* save linear wts also */ + CV_Assert(totwords + 1 > 0 && totwords < 0xFFFF); + double *linearwt = new double[totwords+1]; + int length = totwords; + nread = fread(linearwt, sizeof(double), totwords + 1, modelfl); + if (nread != static_cast(length) + 1) { + delete[] linearwt; + fclose(modelfl); + throw Exception(); + } + + for (int i = 0; i < length; i++) + detector.push_back((float)linearwt[i]); + + detector.push_back((float)-linearbias); + setSVMDetector(detector); + delete[] linearwt; + } else { + fclose(modelfl); + throw Exception(); + } fclose(modelfl); - throw Exception(); - } - fclose(modelfl); -} - -void HOGDescriptor::groupRectangles(std::vector& rectList, std::vector& weights, int groupThreshold, double eps) const -{ - CV_INSTRUMENT_REGION(); - - if( groupThreshold <= 0 || rectList.empty() ) - { - return; } - CV_Assert(rectList.size() == weights.size()); - - std::vector labels; - int nclasses = partition(rectList, labels, SimilarRects(eps)); - - std::vector > rrects(nclasses); - std::vector numInClass(nclasses, 0); - std::vector foundWeights(nclasses, -std::numeric_limits::max()); - int i, j, nlabels = (int)labels.size(); - - for( i = 0; i < nlabels; i++ ) + void HOGDescriptor::groupRectangles(std::vector& rectList, std::vector& weights, int groupThreshold, double eps) const { - int cls = labels[i]; - rrects[cls].x += rectList[i].x; - rrects[cls].y += rectList[i].y; - rrects[cls].width += rectList[i].width; - rrects[cls].height += rectList[i].height; - foundWeights[cls] = max(foundWeights[cls], weights[i]); - numInClass[cls]++; - } + CV_INSTRUMENT_REGION(); - for( i = 0; i < nclasses; i++ ) - { - // find the average of all ROI in the cluster - cv::Rect_ r = rrects[i]; - double s = 1.0/numInClass[i]; - rrects[i] = cv::Rect_(cv::saturate_cast(r.x*s), - cv::saturate_cast(r.y*s), - cv::saturate_cast(r.width*s), - cv::saturate_cast(r.height*s)); - } - - rectList.clear(); - weights.clear(); - - for( i = 0; i < nclasses; i++ ) - { - cv::Rect r1 = rrects[i]; - int n1 = numInClass[i]; - double w1 = foundWeights[i]; - if( n1 <= groupThreshold ) - continue; - // filter out small rectangles inside large rectangles - for( j = 0; j < nclasses; j++ ) + if (groupThreshold <= 0 || rectList.empty()) { - int n2 = numInClass[j]; + return; + } - if( j == i || n2 <= groupThreshold ) + CV_Assert(rectList.size() == weights.size()); + + std::vector labels; + int nclasses = partition(rectList, labels, SimilarRects(eps)); + + std::vector> rrects(nclasses); + std::vector numInClass(nclasses, 0); + std::vector foundWeights(nclasses, -std::numeric_limits::max()); + int i, j, nlabels = (int)labels.size(); + + for (i = 0; i < nlabels; i++) + { + int cls = labels[i]; + rrects[cls].x += rectList[i].x; + rrects[cls].y += rectList[i].y; + rrects[cls].width += rectList[i].width; + rrects[cls].height += rectList[i].height; + foundWeights[cls] = max(foundWeights[cls], weights[i]); + numInClass[cls]++; + } + + for (i = 0; i < nclasses; i++) + { + // find the average of all ROI in the cluster + cv::Rect_ r = rrects[i]; + double s = 1.0/numInClass[i]; + rrects[i] = cv::Rect_(cv::saturate_cast(r.x*s), + cv::saturate_cast(r.y*s), + cv::saturate_cast(r.width*s), + cv::saturate_cast(r.height*s)); + } + + rectList.clear(); + weights.clear(); + + for (i = 0; i < nclasses; i++) + { + cv::Rect r1 = rrects[i]; + int n1 = numInClass[i]; + double w1 = foundWeights[i]; + if (n1 <= groupThreshold) continue; + // filter out small rectangles inside large rectangles + for (j = 0; j < nclasses; j++) + { + int n2 = numInClass[j]; - cv::Rect r2 = rrects[j]; + if (j == i || n2 <= groupThreshold) + continue; - int dx = cv::saturate_cast( r2.width * eps ); - int dy = cv::saturate_cast( r2.height * eps ); + cv::Rect r2 = rrects[j]; - if( r1.x >= r2.x - dx && - r1.y >= r2.y - dy && - r1.x + r1.width <= r2.x + r2.width + dx && - r1.y + r1.height <= r2.y + r2.height + dy && - (n2 > std::max(3, n1) || n1 < 3) ) - break; - } + int dx = cv::saturate_cast( r2.width * eps ); + int dy = cv::saturate_cast( r2.height * eps ); - if( j == nclasses ) - { - rectList.push_back(r1); - weights.push_back(w1); + if (r1.x >= r2.x - dx && + r1.y >= r2.y - dy && + r1.x + r1.width <= r2.x + r2.width + dx && + r1.y + r1.height <= r2.y + r2.height + dy && + (n2 > std::max(3, n1) || n1 < 3)) + break; + } + + if (j == nclasses) + { + rectList.push_back(r1); + weights.push_back(w1); + } } } } -} diff --git a/test/bug-hunting/cve/CVE-2019-16168/where.c b/test/bug-hunting/cve/CVE-2019-16168/where.c index 65c92863a..ea0bfe033 100644 --- a/test/bug-hunting/cve/CVE-2019-16168/where.c +++ b/test/bug-hunting/cve/CVE-2019-16168/where.c @@ -30,8 +30,8 @@ */ typedef struct HiddenIndexInfo HiddenIndexInfo; struct HiddenIndexInfo { - WhereClause *pWC; /* The Where clause being analyzed */ - Parse *pParse; /* The parsing context */ + WhereClause *pWC; /* The Where clause being analyzed */ + Parse *pParse; /* The parsing context */ }; /* Forward declaration of methods */ @@ -47,7 +47,7 @@ static int whereLoopResize(sqlite3*, WhereLoop*, int); ** Return the estimated number of output rows from a WHERE clause */ LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ - return pWInfo->nRowOut; + return pWInfo->nRowOut; } /* @@ -55,7 +55,7 @@ LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ ** WHERE clause returns outputs for DISTINCT processing. */ int sqlite3WhereIsDistinct(WhereInfo *pWInfo){ - return pWInfo->eDistinct; + return pWInfo->eDistinct; } /* @@ -63,7 +63,7 @@ int sqlite3WhereIsDistinct(WhereInfo *pWInfo){ ** Return FALSE if the output needs to be sorted. */ int sqlite3WhereIsOrdered(WhereInfo *pWInfo){ - return pWInfo->nOBSat; + return pWInfo->nOBSat; } /* @@ -84,21 +84,21 @@ int sqlite3WhereIsOrdered(WhereInfo *pWInfo){ ** be the continuation for the inner-most loop. ** ** It is always safe for this routine to return the continuation of the -** inner-most loop, in the sense that a correct answer will result. +** inner-most loop, in the sense that a correct answer will result. ** Returning the continuation the second inner loop is an optimization ** that might make the code run a little faster, but should not change ** the final answer. */ int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){ - WhereLevel *pInner; - if( !pWInfo->bOrderedInnerLoop ){ - /* The ORDER BY LIMIT optimization does not apply. Jump to the - ** continuation of the inner-most loop. */ - return pWInfo->iContinue; - } - pInner = &pWInfo->a[pWInfo->nLevel-1]; - assert( pInner->addrNxt!=0 ); - return pInner->addrNxt; + WhereLevel *pInner; + if (!pWInfo->bOrderedInnerLoop) { + /* The ORDER BY LIMIT optimization does not apply. Jump to the + ** continuation of the inner-most loop. */ + return pWInfo->iContinue; + } + pInner = &pWInfo->a[pWInfo->nLevel-1]; + assert( pInner->addrNxt!=0 ); + return pInner->addrNxt; } /* @@ -106,8 +106,8 @@ int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){ ** immediately with the next row of a WHERE clause. */ int sqlite3WhereContinueLabel(WhereInfo *pWInfo){ - assert( pWInfo->iContinue!=0 ); - return pWInfo->iContinue; + assert( pWInfo->iContinue!=0 ); + return pWInfo->iContinue; } /* @@ -115,7 +115,7 @@ int sqlite3WhereContinueLabel(WhereInfo *pWInfo){ ** out of a WHERE loop. */ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){ - return pWInfo->iBreak; + return pWInfo->iBreak; } /* @@ -123,7 +123,7 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){ ** operate directly on the rowis returned by a WHERE clause. Return ** ONEPASS_SINGLE (1) if the statement can operation directly because only ** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass -** optimization can be used on multiple +** optimization can be used on multiple ** ** If the ONEPASS optimization is used (if this routine returns true) ** then also write the indices of open cursors used by ONEPASS @@ -136,23 +136,23 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){ ** unable to use the ONEPASS optimization. */ int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){ - memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); + memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2); #ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){ - sqlite3DebugPrintf("%s cursors: %d %d\n", - pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI", - aiCur[0], aiCur[1]); - } + if (sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF) { + sqlite3DebugPrintf("%s cursors: %d %d\n", + pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI", + aiCur[0], aiCur[1]); + } #endif - return pWInfo->eOnePass; + return pWInfo->eOnePass; } /* ** Move the content of pSrc into pDest */ static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ - pDest->n = pSrc->n; - memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0])); + pDest->n = pSrc->n; + memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0])); } /* @@ -163,36 +163,36 @@ static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ ** so that pSet keeps the N_OR_COST best entries seen so far. */ static int whereOrInsert( - WhereOrSet *pSet, /* The WhereOrSet to be updated */ - Bitmask prereq, /* Prerequisites of the new entry */ - LogEst rRun, /* Run-cost of the new entry */ - LogEst nOut /* Number of outputs for the new entry */ -){ - u16 i; - WhereOrCost *p; - for(i=pSet->n, p=pSet->a; i>0; i--, p++){ - if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){ - goto whereOrInsert_done; + WhereOrSet *pSet, /* The WhereOrSet to be updated */ + Bitmask prereq, /* Prerequisites of the new entry */ + LogEst rRun, /* Run-cost of the new entry */ + LogEst nOut /* Number of outputs for the new entry */ + ){ + u16 i; + WhereOrCost *p; + for (i=pSet->n, p=pSet->a; i>0; i--, p++) { + if (rRun<=p->rRun && (prereq & p->prereq)==prereq) { + goto whereOrInsert_done; + } + if (p->rRun<=rRun && (p->prereq & prereq)==p->prereq) { + return 0; + } } - if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){ - return 0; + if (pSet->na[pSet->n++]; + p->nOut = nOut; + } else { + p = pSet->a; + for (i=1; in; i++) { + if (p->rRun>pSet->a[i].rRun) p = pSet->a + i; + } + if (p->rRun<=rRun) return 0; } - } - if( pSet->na[pSet->n++]; - p->nOut = nOut; - }else{ - p = pSet->a; - for(i=1; in; i++){ - if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i; - } - if( p->rRun<=rRun ) return 0; - } whereOrInsert_done: - p->prereq = prereq; - p->rRun = rRun; - if( p->nOut>nOut ) p->nOut = nOut; - return 1; + p->prereq = prereq; + p->rRun = rRun; + if (p->nOut>nOut) p->nOut = nOut; + return 1; } /* @@ -200,14 +200,14 @@ whereOrInsert_done: ** iCursor is not in the set. */ Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ - int i; - assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); - for(i=0; in; i++){ - if( pMaskSet->ix[i]==iCursor ){ - return MASKBIT(i); + int i; + assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); + for (i=0; in; i++) { + if (pMaskSet->ix[i]==iCursor) { + return MASKBIT(i); + } } - } - return 0; + return 0; } /* @@ -219,8 +219,8 @@ Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ ** array will never overflow. */ static void createMask(WhereMaskSet *pMaskSet, int iCursor){ - assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); - pMaskSet->ix[pMaskSet->n++] = iCursor; + assert( pMaskSet->n < ArraySize(pMaskSet->ix)); + pMaskSet->ix[pMaskSet->n++] = iCursor; } /* @@ -229,85 +229,85 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){ ** Return NULL if there are no more matching WhereTerms. */ static WhereTerm *whereScanNext(WhereScan *pScan){ - int iCur; /* The cursor on the LHS of the term */ - i16 iColumn; /* The column on the LHS of the term. -1 for IPK */ - Expr *pX; /* An expression being tested */ - WhereClause *pWC; /* Shorthand for pScan->pWC */ - WhereTerm *pTerm; /* The term being tested */ - int k = pScan->k; /* Where to start scanning */ + int iCur; /* The cursor on the LHS of the term */ + i16 iColumn; /* The column on the LHS of the term. -1 for IPK */ + Expr *pX; /* An expression being tested */ + WhereClause *pWC; /* Shorthand for pScan->pWC */ + WhereTerm *pTerm; /* The term being tested */ + int k = pScan->k; /* Where to start scanning */ - assert( pScan->iEquiv<=pScan->nEquiv ); - pWC = pScan->pWC; - while(1){ - iColumn = pScan->aiColumn[pScan->iEquiv-1]; - iCur = pScan->aiCur[pScan->iEquiv-1]; - assert( pWC!=0 ); - do{ - for(pTerm=pWC->a+k; knTerm; k++, pTerm++){ - if( pTerm->leftCursor==iCur - && pTerm->u.leftColumn==iColumn - && (iColumn!=XN_EXPR - || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, - pScan->pIdxExpr,iCur)==0) - && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) - ){ - if( (pTerm->eOperator & WO_EQUIV)!=0 - && pScan->nEquivaiCur) - && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN - ){ - int j; - for(j=0; jnEquiv; j++){ - if( pScan->aiCur[j]==pX->iTable - && pScan->aiColumn[j]==pX->iColumn ){ - break; - } + assert( pScan->iEquiv<=pScan->nEquiv ); + pWC = pScan->pWC; + while (1) { + iColumn = pScan->aiColumn[pScan->iEquiv-1]; + iCur = pScan->aiCur[pScan->iEquiv-1]; + assert( pWC!=0 ); + do{ + for (pTerm=pWC->a+k; knTerm; k++, pTerm++) { + if (pTerm->leftCursor==iCur + && pTerm->u.leftColumn==iColumn + && (iColumn!=XN_EXPR + || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, + pScan->pIdxExpr,iCur)==0) + && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) + ) { + if ((pTerm->eOperator & WO_EQUIV)!=0 + && pScan->nEquivaiCur) + && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN + ) { + int j; + for (j=0; jnEquiv; j++) { + if (pScan->aiCur[j]==pX->iTable + && pScan->aiColumn[j]==pX->iColumn) { + break; + } + } + if (j==pScan->nEquiv) { + pScan->aiCur[j] = pX->iTable; + pScan->aiColumn[j] = pX->iColumn; + pScan->nEquiv++; + } + } + if ((pTerm->eOperator & pScan->opMask)!=0) { + /* Verify the affinity and collating sequence match */ + if (pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0) { + CollSeq *pColl; + Parse *pParse = pWC->pWInfo->pParse; + pX = pTerm->pExpr; + if (!sqlite3IndexAffinityOk(pX, pScan->idxaff)) { + continue; + } + assert(pX->pLeft); + pColl = sqlite3BinaryCompareCollSeq(pParse, + pX->pLeft, pX->pRight); + if (pColl==0) pColl = pParse->db->pDfltColl; + if (sqlite3StrICmp(pColl->zName, pScan->zCollName)) { + continue; + } + } + if ((pTerm->eOperator & (WO_EQ|WO_IS))!=0 + && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN + && pX->iTable==pScan->aiCur[0] + && pX->iColumn==pScan->aiColumn[0] + ) { + testcase( pTerm->eOperator & WO_IS ); + continue; + } + pScan->pWC = pWC; + pScan->k = k+1; + return pTerm; + } + } } - if( j==pScan->nEquiv ){ - pScan->aiCur[j] = pX->iTable; - pScan->aiColumn[j] = pX->iColumn; - pScan->nEquiv++; - } - } - if( (pTerm->eOperator & pScan->opMask)!=0 ){ - /* Verify the affinity and collating sequence match */ - if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ - CollSeq *pColl; - Parse *pParse = pWC->pWInfo->pParse; - pX = pTerm->pExpr; - if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ - continue; - } - assert(pX->pLeft); - pColl = sqlite3BinaryCompareCollSeq(pParse, - pX->pLeft, pX->pRight); - if( pColl==0 ) pColl = pParse->db->pDfltColl; - if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){ - continue; - } - } - if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0 - && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN - && pX->iTable==pScan->aiCur[0] - && pX->iColumn==pScan->aiColumn[0] - ){ - testcase( pTerm->eOperator & WO_IS ); - continue; - } - pScan->pWC = pWC; - pScan->k = k+1; - return pTerm; - } - } - } - pWC = pWC->pOuter; - k = 0; - }while( pWC!=0 ); - if( pScan->iEquiv>=pScan->nEquiv ) break; - pWC = pScan->pOrigWC; - k = 0; - pScan->iEquiv++; - } - return 0; + pWC = pWC->pOuter; + k = 0; + }while (pWC!=0); + if (pScan->iEquiv>=pScan->nEquiv) break; + pWC = pScan->pOrigWC; + k = 0; + pScan->iEquiv++; + } + return 0; } /* @@ -317,8 +317,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ ** need to push registers onto the stack as part of its prologue. */ static SQLITE_NOINLINE WhereTerm *whereScanInitIndexExpr(WhereScan *pScan){ - pScan->idxaff = sqlite3ExprAffinity(pScan->pIdxExpr); - return whereScanNext(pScan); + pScan->idxaff = sqlite3ExprAffinity(pScan->pIdxExpr); + return whereScanNext(pScan); } /* @@ -341,42 +341,42 @@ static SQLITE_NOINLINE WhereTerm *whereScanInitIndexExpr(WhereScan *pScan){ ** index pIdx. */ static WhereTerm *whereScanInit( - WhereScan *pScan, /* The WhereScan object being initialized */ - WhereClause *pWC, /* The WHERE clause to be scanned */ - int iCur, /* Cursor to scan for */ - int iColumn, /* Column to scan for */ - u32 opMask, /* Operator(s) to scan for */ - Index *pIdx /* Must be compatible with this index */ -){ - pScan->pOrigWC = pWC; - pScan->pWC = pWC; - pScan->pIdxExpr = 0; - pScan->idxaff = 0; - pScan->zCollName = 0; - pScan->opMask = opMask; - pScan->k = 0; - pScan->aiCur[0] = iCur; - pScan->nEquiv = 1; - pScan->iEquiv = 1; - if( pIdx ){ - int j = iColumn; - iColumn = pIdx->aiColumn[j]; - if( iColumn==XN_EXPR ){ - pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; - pScan->zCollName = pIdx->azColl[j]; - pScan->aiColumn[0] = XN_EXPR; - return whereScanInitIndexExpr(pScan); - }else if( iColumn==pIdx->pTable->iPKey ){ - iColumn = XN_ROWID; - }else if( iColumn>=0 ){ - pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; - pScan->zCollName = pIdx->azColl[j]; + WhereScan *pScan, /* The WhereScan object being initialized */ + WhereClause *pWC, /* The WHERE clause to be scanned */ + int iCur, /* Cursor to scan for */ + int iColumn, /* Column to scan for */ + u32 opMask, /* Operator(s) to scan for */ + Index *pIdx /* Must be compatible with this index */ + ){ + pScan->pOrigWC = pWC; + pScan->pWC = pWC; + pScan->pIdxExpr = 0; + pScan->idxaff = 0; + pScan->zCollName = 0; + pScan->opMask = opMask; + pScan->k = 0; + pScan->aiCur[0] = iCur; + pScan->nEquiv = 1; + pScan->iEquiv = 1; + if (pIdx) { + int j = iColumn; + iColumn = pIdx->aiColumn[j]; + if (iColumn==XN_EXPR) { + pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + pScan->zCollName = pIdx->azColl[j]; + pScan->aiColumn[0] = XN_EXPR; + return whereScanInitIndexExpr(pScan); + } else if (iColumn==pIdx->pTable->iPKey) { + iColumn = XN_ROWID; + } else if (iColumn>=0) { + pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; + pScan->zCollName = pIdx->azColl[j]; + } + } else if (iColumn==XN_EXPR) { + return 0; } - }else if( iColumn==XN_EXPR ){ - return 0; - } - pScan->aiColumn[0] = iColumn; - return whereScanNext(pScan); + pScan->aiColumn[0] = iColumn; + return whereScanNext(pScan); } /* @@ -385,7 +385,7 @@ static WhereTerm *whereScanInit( ** if pIdx!=0 and is one of the WO_xx operator codes specified by ** the op parameter. Return a pointer to the term. Return 0 if not found. ** -** If pIdx!=0 then it must be one of the indexes of table iCur. +** If pIdx!=0 then it must be one of the indexes of table iCur. ** Search for terms matching the iColumn-th column of pIdx ** rather than the iColumn-th column of table iCur. ** @@ -405,30 +405,30 @@ static WhereTerm *whereScanInit( ** exist, try to return a term that does not use WO_EQUIV. */ WhereTerm *sqlite3WhereFindTerm( - WhereClause *pWC, /* The WHERE clause to be searched */ - int iCur, /* Cursor number of LHS */ - int iColumn, /* Column number of LHS */ - Bitmask notReady, /* RHS must not overlap with this mask */ - u32 op, /* Mask of WO_xx values describing operator */ - Index *pIdx /* Must be compatible with this index, if not NULL */ -){ - WhereTerm *pResult = 0; - WhereTerm *p; - WhereScan scan; + WhereClause *pWC, /* The WHERE clause to be searched */ + int iCur, /* Cursor number of LHS */ + int iColumn, /* Column number of LHS */ + Bitmask notReady, /* RHS must not overlap with this mask */ + u32 op, /* Mask of WO_xx values describing operator */ + Index *pIdx /* Must be compatible with this index, if not NULL */ + ){ + WhereTerm *pResult = 0; + WhereTerm *p; + WhereScan scan; - p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx); - op &= WO_EQ|WO_IS; - while( p ){ - if( (p->prereqRight & notReady)==0 ){ - if( p->prereqRight==0 && (p->eOperator&op)!=0 ){ - testcase( p->eOperator & WO_IS ); - return p; - } - if( pResult==0 ) pResult = p; + p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx); + op &= WO_EQ|WO_IS; + while (p) { + if ((p->prereqRight & notReady)==0) { + if (p->prereqRight==0 && (p->eOperator&op)!=0) { + testcase( p->eOperator & WO_IS ); + return p; + } + if (pResult==0) pResult = p; + } + p = whereScanNext(&scan); } - p = whereScanNext(&scan); - } - return pResult; + return pResult; } /* @@ -439,48 +439,48 @@ WhereTerm *sqlite3WhereFindTerm( ** no expression is found, -1 is returned. */ static int findIndexCol( - Parse *pParse, /* Parse context */ - ExprList *pList, /* Expression list to search */ - int iBase, /* Cursor for table associated with pIdx */ - Index *pIdx, /* Index to match column of */ - int iCol /* Column of index to match */ -){ - int i; - const char *zColl = pIdx->azColl[iCol]; - - for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); - if( p->op==TK_COLUMN - && p->iColumn==pIdx->aiColumn[iCol] - && p->iTable==iBase + Parse *pParse, /* Parse context */ + ExprList *pList, /* Expression list to search */ + int iBase, /* Cursor for table associated with pIdx */ + Index *pIdx, /* Index to match column of */ + int iCol /* Column of index to match */ ){ - CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr); - if( 0==sqlite3StrICmp(pColl->zName, zColl) ){ - return i; - } - } - } + int i; + const char *zColl = pIdx->azColl[iCol]; - return -1; + for (i=0; inExpr; i++) { + Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); + if (p->op==TK_COLUMN + && p->iColumn==pIdx->aiColumn[iCol] + && p->iTable==iBase + ) { + CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr); + if (0==sqlite3StrICmp(pColl->zName, zColl)) { + return i; + } + } + } + + return -1; } /* ** Return TRUE if the iCol-th column of index pIdx is NOT NULL */ static int indexColumnNotNull(Index *pIdx, int iCol){ - int j; - assert( pIdx!=0 ); - assert( iCol>=0 && iColnColumn ); - j = pIdx->aiColumn[iCol]; - if( j>=0 ){ - return pIdx->pTable->aCol[j].notNull; - }else if( j==(-1) ){ - return 1; - }else{ - assert( j==(-2) ); - return 0; /* Assume an indexed expression can always yield a NULL */ + int j; + assert( pIdx!=0 ); + assert( iCol>=0 && iColnColumn ); + j = pIdx->aiColumn[iCol]; + if (j>=0) { + return pIdx->pTable->aCol[j].notNull; + } else if (j==(-1)) { + return 1; + } else { + assert( j==(-2)); + return 0; /* Assume an indexed expression can always yield a NULL */ - } + } } /* @@ -491,60 +491,60 @@ static int indexColumnNotNull(Index *pIdx, int iCol){ ** DISTINCT list are collectively unique and individually non-null. */ static int isDistinctRedundant( - Parse *pParse, /* Parsing context */ - SrcList *pTabList, /* The FROM clause */ - WhereClause *pWC, /* The WHERE clause */ - ExprList *pDistinct /* The result set that needs to be DISTINCT */ -){ - Table *pTab; - Index *pIdx; - int i; - int iBase; + Parse *pParse, /* Parsing context */ + SrcList *pTabList, /* The FROM clause */ + WhereClause *pWC, /* The WHERE clause */ + ExprList *pDistinct /* The result set that needs to be DISTINCT */ + ){ + Table *pTab; + Index *pIdx; + int i; + int iBase; - /* If there is more than one table or sub-select in the FROM clause of - ** this query, then it will not be possible to show that the DISTINCT - ** clause is redundant. */ - if( pTabList->nSrc!=1 ) return 0; - iBase = pTabList->a[0].iCursor; - pTab = pTabList->a[0].pTab; + /* If there is more than one table or sub-select in the FROM clause of + ** this query, then it will not be possible to show that the DISTINCT + ** clause is redundant. */ + if (pTabList->nSrc!=1) return 0; + iBase = pTabList->a[0].iCursor; + pTab = pTabList->a[0].pTab; - /* If any of the expressions is an IPK column on table iBase, then return - ** true. Note: The (p->iTable==iBase) part of this test may be false if the - ** current SELECT is a correlated sub-query. - */ - for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); - if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; - } - - /* Loop through all indices on the table, checking each to see if it makes - ** the DISTINCT qualifier redundant. It does so if: - ** - ** 1. The index is itself UNIQUE, and - ** - ** 2. All of the columns in the index are either part of the pDistinct - ** list, or else the WHERE clause contains a term of the form "col=X", - ** where X is a constant value. The collation sequences of the - ** comparison and select-list expressions must match those of the index. - ** - ** 3. All of those index columns for which the WHERE clause does not - ** contain a "col=X" term are subject to a NOT NULL constraint. - */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( !IsUniqueIndex(pIdx) ) continue; - for(i=0; inKeyCol; i++){ - if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){ - if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break; - if( indexColumnNotNull(pIdx, i)==0 ) break; - } + /* If any of the expressions is an IPK column on table iBase, then return + ** true. Note: The (p->iTable==iBase) part of this test may be false if the + ** current SELECT is a correlated sub-query. + */ + for (i=0; inExpr; i++) { + Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); + if (p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0) return 1; } - if( i==pIdx->nKeyCol ){ - /* This index implies that the DISTINCT qualifier is redundant. */ - return 1; - } - } - return 0; + /* Loop through all indices on the table, checking each to see if it makes + ** the DISTINCT qualifier redundant. It does so if: + ** + ** 1. The index is itself UNIQUE, and + ** + ** 2. All of the columns in the index are either part of the pDistinct + ** list, or else the WHERE clause contains a term of the form "col=X", + ** where X is a constant value. The collation sequences of the + ** comparison and select-list expressions must match those of the index. + ** + ** 3. All of those index columns for which the WHERE clause does not + ** contain a "col=X" term are subject to a NOT NULL constraint. + */ + for (pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext) { + if (!IsUniqueIndex(pIdx)) continue; + for (i=0; inKeyCol; i++) { + if (0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx)) { + if (findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0) break; + if (indexColumnNotNull(pIdx, i)==0) break; + } + } + if (i==pIdx->nKeyCol) { + /* This index implies that the DISTINCT qualifier is redundant. */ + return 1; + } + } + + return 0; } @@ -552,14 +552,14 @@ static int isDistinctRedundant( ** Estimate the logarithm of the input value to base 2. */ static LogEst estLog(LogEst N){ - return N<=10 ? 0 : sqlite3LogEst(N) - 33; + return N<=10 ? 0 : sqlite3LogEst(N) - 33; } /* ** Convert OP_Column opcodes to OP_Copy in previously generated code. ** ** This routine runs over generated VDBE code and translates OP_Column -** opcodes into OP_Copy when the table is being accessed via co-routine +** opcodes into OP_Copy when the table is being accessed via co-routine ** instead of via table lookup. ** ** If the iAutoidxCur is not zero, then any OP_Rowid instructions on @@ -568,34 +568,34 @@ static LogEst estLog(LogEst N){ ** automatic index being generated. */ static void translateColumnToCopy( - Parse *pParse, /* Parsing context */ - int iStart, /* Translate from this opcode to the end */ - int iTabCur, /* OP_Column/OP_Rowid references to this table */ - int iRegister, /* The first column is in this register */ - int iAutoidxCur /* If non-zero, cursor of autoindex being generated */ -){ - Vdbe *v = pParse->pVdbe; - VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart); - int iEnd = sqlite3VdbeCurrentAddr(v); - if( pParse->db->mallocFailed ) return; - for(; iStartp1!=iTabCur ) continue; - if( pOp->opcode==OP_Column ){ - pOp->opcode = OP_Copy; - pOp->p1 = pOp->p2 + iRegister; - pOp->p2 = pOp->p3; - pOp->p3 = 0; - }else if( pOp->opcode==OP_Rowid ){ - if( iAutoidxCur ){ - pOp->opcode = OP_Sequence; - pOp->p1 = iAutoidxCur; - }else{ - pOp->opcode = OP_Null; - pOp->p1 = 0; - pOp->p3 = 0; - } + Parse *pParse, /* Parsing context */ + int iStart, /* Translate from this opcode to the end */ + int iTabCur, /* OP_Column/OP_Rowid references to this table */ + int iRegister, /* The first column is in this register */ + int iAutoidxCur /* If non-zero, cursor of autoindex being generated */ + ){ + Vdbe *v = pParse->pVdbe; + VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart); + int iEnd = sqlite3VdbeCurrentAddr(v); + if (pParse->db->mallocFailed) return; + for (; iStartp1!=iTabCur) continue; + if (pOp->opcode==OP_Column) { + pOp->opcode = OP_Copy; + pOp->p1 = pOp->p2 + iRegister; + pOp->p2 = pOp->p3; + pOp->p3 = 0; + } else if (pOp->opcode==OP_Rowid) { + if (iAutoidxCur) { + pOp->opcode = OP_Sequence; + pOp->p1 = iAutoidxCur; + } else { + pOp->opcode = OP_Null; + pOp->p1 = 0; + pOp->p3 = 0; + } + } } - } } /* @@ -606,37 +606,37 @@ static void translateColumnToCopy( */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) static void TRACE_IDX_INPUTS(sqlite3_index_info *p){ - int i; - if( !sqlite3WhereTrace ) return; - for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", - i, - p->aConstraint[i].iColumn, - p->aConstraint[i].iTermOffset, - p->aConstraint[i].op, - p->aConstraint[i].usable); - } - for(i=0; inOrderBy; i++){ - sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", - i, - p->aOrderBy[i].iColumn, - p->aOrderBy[i].desc); - } + int i; + if (!sqlite3WhereTrace) return; + for (i=0; inConstraint; i++) { + sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", + i, + p->aConstraint[i].iColumn, + p->aConstraint[i].iTermOffset, + p->aConstraint[i].op, + p->aConstraint[i].usable); + } + for (i=0; inOrderBy; i++) { + sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", + i, + p->aOrderBy[i].iColumn, + p->aOrderBy[i].desc); + } } static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){ - int i; - if( !sqlite3WhereTrace ) return; - for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", - i, - p->aConstraintUsage[i].argvIndex, - p->aConstraintUsage[i].omit); - } - sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum); - sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr); - sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); - sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); - sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows); + int i; + if (!sqlite3WhereTrace) return; + for (i=0; inConstraint; i++) { + sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", + i, + p->aConstraintUsage[i].argvIndex, + p->aConstraintUsage[i].omit); + } + sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum); + sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr); + sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); + sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); + sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows); } #else #define TRACE_IDX_INPUTS(A) @@ -650,28 +650,28 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){ ** index existed. */ static int termCanDriveIndex( - WhereTerm *pTerm, /* WHERE clause term to check */ - struct SrcList_item *pSrc, /* Table we are trying to access */ - Bitmask notReady /* Tables in outer loops of the join */ -){ - char aff; - if( pTerm->leftCursor!=pSrc->iCursor ) return 0; - if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0; - if( (pSrc->fg.jointype & JT_LEFT) - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - && (pTerm->eOperator & WO_IS) - ){ - /* Cannot use an IS term from the WHERE clause as an index driver for - ** the RHS of a LEFT JOIN. Such a term can only be used if it is from - ** the ON clause. */ - return 0; - } - if( (pTerm->prereqRight & notReady)!=0 ) return 0; - if( pTerm->u.leftColumn<0 ) return 0; - aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; - if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; - testcase( pTerm->pExpr->op==TK_IS ); - return 1; + WhereTerm *pTerm, /* WHERE clause term to check */ + struct SrcList_item *pSrc, /* Table we are trying to access */ + Bitmask notReady /* Tables in outer loops of the join */ + ){ + char aff; + if (pTerm->leftCursor!=pSrc->iCursor) return 0; + if ((pTerm->eOperator & (WO_EQ|WO_IS))==0) return 0; + if ((pSrc->fg.jointype & JT_LEFT) + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + && (pTerm->eOperator & WO_IS) + ) { + /* Cannot use an IS term from the WHERE clause as an index driver for + ** the RHS of a LEFT JOIN. Such a term can only be used if it is from + ** the ON clause. */ + return 0; + } + if ((pTerm->prereqRight & notReady)!=0) return 0; + if (pTerm->u.leftColumn<0) return 0; + aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; + if (!sqlite3IndexAffinityOk(pTerm->pExpr, aff)) return 0; + testcase( pTerm->pExpr->op==TK_IS ); + return 1; } #endif @@ -683,359 +683,359 @@ static int termCanDriveIndex( ** makes use of the automatic index. */ static void constructAutomaticIndex( - Parse *pParse, /* The parsing context */ - WhereClause *pWC, /* The WHERE clause */ - struct SrcList_item *pSrc, /* The FROM clause term to get the next index */ - Bitmask notReady, /* Mask of cursors that are not available */ - WhereLevel *pLevel /* Write new index here */ -){ - int nKeyCol; /* Number of columns in the constructed index */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - WhereTerm *pWCEnd; /* End of pWC->a[] */ - Index *pIdx; /* Object describing the transient index */ - Vdbe *v; /* Prepared statement under construction */ - int addrInit; /* Address of the initialization bypass jump */ - Table *pTable; /* The table being indexed */ - int addrTop; /* Top of the index fill loop */ - int regRecord; /* Register holding an index record */ - int n; /* Column counter */ - int i; /* Loop counter */ - int mxBitCol; /* Maximum column in pSrc->colUsed */ - CollSeq *pColl; /* Collating sequence to on a column */ - WhereLoop *pLoop; /* The Loop object */ - char *zNotUsed; /* Extra space on the end of pIdx */ - Bitmask idxCols; /* Bitmap of columns used for indexing */ - Bitmask extraCols; /* Bitmap of additional columns */ - u8 sentWarning = 0; /* True if a warnning has been issued */ - Expr *pPartial = 0; /* Partial Index Expression */ - int iContinue = 0; /* Jump here to skip excluded rows */ - struct SrcList_item *pTabItem; /* FROM clause term being indexed */ - int addrCounter = 0; /* Address where integer counter is initialized */ - int regBase; /* Array of registers where record is assembled */ + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + struct SrcList_item *pSrc, /* The FROM clause term to get the next index */ + Bitmask notReady, /* Mask of cursors that are not available */ + WhereLevel *pLevel /* Write new index here */ + ){ + int nKeyCol; /* Number of columns in the constructed index */ + WhereTerm *pTerm; /* A single term of the WHERE clause */ + WhereTerm *pWCEnd; /* End of pWC->a[] */ + Index *pIdx; /* Object describing the transient index */ + Vdbe *v; /* Prepared statement under construction */ + int addrInit; /* Address of the initialization bypass jump */ + Table *pTable; /* The table being indexed */ + int addrTop; /* Top of the index fill loop */ + int regRecord; /* Register holding an index record */ + int n; /* Column counter */ + int i; /* Loop counter */ + int mxBitCol; /* Maximum column in pSrc->colUsed */ + CollSeq *pColl; /* Collating sequence to on a column */ + WhereLoop *pLoop; /* The Loop object */ + char *zNotUsed; /* Extra space on the end of pIdx */ + Bitmask idxCols; /* Bitmap of columns used for indexing */ + Bitmask extraCols; /* Bitmap of additional columns */ + u8 sentWarning = 0; /* True if a warnning has been issued */ + Expr *pPartial = 0; /* Partial Index Expression */ + int iContinue = 0; /* Jump here to skip excluded rows */ + struct SrcList_item *pTabItem; /* FROM clause term being indexed */ + int addrCounter = 0; /* Address where integer counter is initialized */ + int regBase; /* Array of registers where record is assembled */ - /* Generate code to skip over the creation and initialization of the - ** transient index on 2nd and subsequent iterations of the loop. */ - v = pParse->pVdbe; - assert( v!=0 ); - addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + /* Generate code to skip over the creation and initialization of the + ** transient index on 2nd and subsequent iterations of the loop. */ + v = pParse->pVdbe; + assert( v!=0 ); + addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - /* Count the number of columns that will be added to the index - ** and used to match WHERE clause constraints */ - nKeyCol = 0; - pTable = pSrc->pTab; - pWCEnd = &pWC->a[pWC->nTerm]; - pLoop = pLevel->pWLoop; - idxCols = 0; - for(pTerm=pWC->a; pTermpExpr; - assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */ - || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */ - || pLoop->prereq!=0 ); /* table of a LEFT JOIN */ - if( pLoop->prereq==0 - && (pTerm->wtFlags & TERM_VIRTUAL)==0 - && !ExprHasProperty(pExpr, EP_FromJoin) - && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ - pPartial = sqlite3ExprAnd(pParse, pPartial, - sqlite3ExprDup(pParse->db, pExpr, 0)); - } - if( termCanDriveIndex(pTerm, pSrc, notReady) ){ - int iCol = pTerm->u.leftColumn; - Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); - testcase( iCol==BMS ); - testcase( iCol==BMS-1 ); - if( !sentWarning ){ - sqlite3_log(SQLITE_WARNING_AUTOINDEX, - "automatic index on %s(%s)", pTable->zName, - pTable->aCol[iCol].zName); - sentWarning = 1; - } - if( (idxCols & cMask)==0 ){ - if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){ - goto end_auto_index_create; + /* Count the number of columns that will be added to the index + ** and used to match WHERE clause constraints */ + nKeyCol = 0; + pTable = pSrc->pTab; + pWCEnd = &pWC->a[pWC->nTerm]; + pLoop = pLevel->pWLoop; + idxCols = 0; + for (pTerm=pWC->a; pTermpExpr; + assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */ + || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */ + || pLoop->prereq!=0 ); /* table of a LEFT JOIN */ + if (pLoop->prereq==0 + && (pTerm->wtFlags & TERM_VIRTUAL)==0 + && !ExprHasProperty(pExpr, EP_FromJoin) + && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor)) { + pPartial = sqlite3ExprAnd(pParse, pPartial, + sqlite3ExprDup(pParse->db, pExpr, 0)); + } + if (termCanDriveIndex(pTerm, pSrc, notReady)) { + int iCol = pTerm->u.leftColumn; + Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); + testcase( iCol==BMS ); + testcase( iCol==BMS-1 ); + if (!sentWarning) { + sqlite3_log(SQLITE_WARNING_AUTOINDEX, + "automatic index on %s(%s)", pTable->zName, + pTable->aCol[iCol].zName); + sentWarning = 1; + } + if ((idxCols & cMask)==0) { + if (whereLoopResize(pParse->db, pLoop, nKeyCol+1)) { + goto end_auto_index_create; + } + pLoop->aLTerm[nKeyCol++] = pTerm; + idxCols |= cMask; + } } - pLoop->aLTerm[nKeyCol++] = pTerm; - idxCols |= cMask; - } } - } - assert( nKeyCol>0 ); - pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol; - pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED + assert( nKeyCol>0 ); + pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol; + pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED | WHERE_AUTO_INDEX; - /* Count the number of additional columns needed to create a - ** covering index. A "covering index" is an index that contains all - ** columns that are needed by the query. With a covering index, the - ** original table never needs to be accessed. Automatic indices must - ** be a covering index because the index will not be updated if the - ** original table changes and the index and table cannot both be used - ** if they go out of sync. - */ - extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); - mxBitCol = MIN(BMS-1,pTable->nCol); - testcase( pTable->nCol==BMS-1 ); - testcase( pTable->nCol==BMS-2 ); - for(i=0; icolUsed & MASKBIT(BMS-1) ){ - nKeyCol += pTable->nCol - BMS + 1; - } - - /* Construct the Index object to describe this index */ - pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed); - if( pIdx==0 ) goto end_auto_index_create; - pLoop->u.btree.pIndex = pIdx; - pIdx->zName = "auto-index"; - pIdx->pTable = pTable; - n = 0; - idxCols = 0; - for(pTerm=pWC->a; pTermu.leftColumn; - Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); - testcase( iCol==BMS-1 ); - testcase( iCol==BMS ); - if( (idxCols & cMask)==0 ){ - Expr *pX = pTerm->pExpr; - idxCols |= cMask; - pIdx->aiColumn[n] = pTerm->u.leftColumn; - pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); - pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; - n++; - } + /* Count the number of additional columns needed to create a + ** covering index. A "covering index" is an index that contains all + ** columns that are needed by the query. With a covering index, the + ** original table never needs to be accessed. Automatic indices must + ** be a covering index because the index will not be updated if the + ** original table changes and the index and table cannot both be used + ** if they go out of sync. + */ + extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); + mxBitCol = MIN(BMS-1,pTable->nCol); + testcase( pTable->nCol==BMS-1 ); + testcase( pTable->nCol==BMS-2 ); + for (i=0; iu.btree.nEq ); - - /* Add additional columns needed to make the automatic index into - ** a covering index */ - for(i=0; iaiColumn[n] = i; - pIdx->azColl[n] = sqlite3StrBINARY; - n++; + if (pSrc->colUsed & MASKBIT(BMS-1)) { + nKeyCol += pTable->nCol - BMS + 1; } - } - if( pSrc->colUsed & MASKBIT(BMS-1) ){ - for(i=BMS-1; inCol; i++){ - pIdx->aiColumn[n] = i; - pIdx->azColl[n] = sqlite3StrBINARY; - n++; + + /* Construct the Index object to describe this index */ + pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed); + if (pIdx==0) goto end_auto_index_create; + pLoop->u.btree.pIndex = pIdx; + pIdx->zName = "auto-index"; + pIdx->pTable = pTable; + n = 0; + idxCols = 0; + for (pTerm=pWC->a; pTermu.leftColumn; + Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); + testcase( iCol==BMS-1 ); + testcase( iCol==BMS ); + if ((idxCols & cMask)==0) { + Expr *pX = pTerm->pExpr; + idxCols |= cMask; + pIdx->aiColumn[n] = pTerm->u.leftColumn; + pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); + pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; + n++; + } + } } - } - assert( n==nKeyCol ); - pIdx->aiColumn[n] = XN_ROWID; - pIdx->azColl[n] = sqlite3StrBINARY; + assert((u32)n==pLoop->u.btree.nEq ); - /* Create the automatic index */ - assert( pLevel->iIdxCur>=0 ); - pLevel->iIdxCur = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); - sqlite3VdbeSetP4KeyInfo(pParse, pIdx); - VdbeComment((v, "for %s", pTable->zName)); + /* Add additional columns needed to make the automatic index into + ** a covering index */ + for (i=0; iaiColumn[n] = i; + pIdx->azColl[n] = sqlite3StrBINARY; + n++; + } + } + if (pSrc->colUsed & MASKBIT(BMS-1)) { + for (i=BMS-1; inCol; i++) { + pIdx->aiColumn[n] = i; + pIdx->azColl[n] = sqlite3StrBINARY; + n++; + } + } + assert( n==nKeyCol ); + pIdx->aiColumn[n] = XN_ROWID; + pIdx->azColl[n] = sqlite3StrBINARY; - /* Fill the automatic index with content */ - pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; - if( pTabItem->fg.viaCoroutine ){ - int regYield = pTabItem->regReturn; - addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); - sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); - addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); - VdbeCoverage(v); - VdbeComment((v, "next row of %s", pTabItem->pTab->zName)); - }else{ - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); - } - if( pPartial ){ - iContinue = sqlite3VdbeMakeLabel(pParse); - sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL); - pLoop->wsFlags |= WHERE_PARTIALIDX; - } - regRecord = sqlite3GetTempReg(pParse); - regBase = sqlite3GenerateIndexKey( - pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0 - ); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); - if( pTabItem->fg.viaCoroutine ){ - sqlite3VdbeChangeP2(v, addrCounter, regBase+n); - testcase( pParse->db->mallocFailed ); - assert( pLevel->iIdxCur>0 ); - translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, - pTabItem->regResult, pLevel->iIdxCur); - sqlite3VdbeGoto(v, addrTop); - pTabItem->fg.viaCoroutine = 0; - }else{ - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); - } - sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); - sqlite3VdbeJumpHere(v, addrTop); - sqlite3ReleaseTempReg(pParse, regRecord); - - /* Jump here when skipping the initialization */ - sqlite3VdbeJumpHere(v, addrInit); + /* Create the automatic index */ + assert( pLevel->iIdxCur>=0 ); + pLevel->iIdxCur = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + VdbeComment((v, "for %s", pTable->zName)); + + /* Fill the automatic index with content */ + pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; + if (pTabItem->fg.viaCoroutine) { + int regYield = pTabItem->regReturn; + addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); + addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); + VdbeCoverage(v); + VdbeComment((v, "next row of %s", pTabItem->pTab->zName)); + } else { + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); + } + if (pPartial) { + iContinue = sqlite3VdbeMakeLabel(pParse); + sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL); + pLoop->wsFlags |= WHERE_PARTIALIDX; + } + regRecord = sqlite3GetTempReg(pParse); + regBase = sqlite3GenerateIndexKey( + pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0 + ); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + if (pPartial) sqlite3VdbeResolveLabel(v, iContinue); + if (pTabItem->fg.viaCoroutine) { + sqlite3VdbeChangeP2(v, addrCounter, regBase+n); + testcase( pParse->db->mallocFailed ); + assert( pLevel->iIdxCur>0 ); + translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, + pTabItem->regResult, pLevel->iIdxCur); + sqlite3VdbeGoto(v, addrTop); + pTabItem->fg.viaCoroutine = 0; + } else { + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); + } + sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); + sqlite3VdbeJumpHere(v, addrTop); + sqlite3ReleaseTempReg(pParse, regRecord); + + /* Jump here when skipping the initialization */ + sqlite3VdbeJumpHere(v, addrInit); end_auto_index_create: - sqlite3ExprDelete(pParse->db, pPartial); + sqlite3ExprDelete(pParse->db, pPartial); } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* -** Allocate and populate an sqlite3_index_info structure. It is the +** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure ** by passing the pointer returned by this function to sqlite3_free(). */ static sqlite3_index_info *allocateIndexInfo( - Parse *pParse, /* The parsing context */ - WhereClause *pWC, /* The WHERE clause being analyzed */ - Bitmask mUnusable, /* Ignore terms with these prereqs */ - struct SrcList_item *pSrc, /* The FROM clause term that is the vtab */ - ExprList *pOrderBy, /* The ORDER BY clause */ - u16 *pmNoOmit /* Mask of terms not to omit */ -){ - int i, j; - int nTerm; - struct sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_orderby *pIdxOrderBy; - struct sqlite3_index_constraint_usage *pUsage; - struct HiddenIndexInfo *pHidden; - WhereTerm *pTerm; - int nOrderBy; - sqlite3_index_info *pIdxInfo; - u16 mNoOmit = 0; - - /* Count the number of possible WHERE clause constraints referring - ** to this virtual table */ - for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->prereqRight & mUnusable ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_IS ); - testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - assert( pTerm->u.leftColumn>=(-1) ); - nTerm++; - } - - /* If the ORDER BY clause contains only columns in the current - ** virtual table then allocate space for the aOrderBy part of - ** the sqlite3_index_info structure. - */ - nOrderBy = 0; - if( pOrderBy ){ - int n = pOrderBy->nExpr; - for(i=0; ia[i].pExpr; - if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; - } - if( i==n){ - nOrderBy = n; - } - } - - /* Allocate the sqlite3_index_info structure - */ - pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) - + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm - + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) ); - if( pIdxInfo==0 ){ - sqlite3ErrorMsg(pParse, "out of memory"); - return 0; - } - - /* Initialize the structure. The sqlite3_index_info structure contains - ** many fields that are declared "const" to prevent xBestIndex from - ** changing them. We have to do some funky casting in order to - ** initialize those fields. - */ - pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; - pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1]; - pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; - pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; - *(int*)&pIdxInfo->nConstraint = nTerm; - *(int*)&pIdxInfo->nOrderBy = nOrderBy; - *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; - *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; - *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = - pUsage; - - pHidden->pWC = pWC; - pHidden->pParse = pParse; - for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - u16 op; - if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->prereqRight & mUnusable ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_IS ); - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - if( (pSrc->fg.jointype & JT_LEFT)!=0 - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - && (pTerm->eOperator & (WO_IS|WO_ISNULL)) + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause being analyzed */ + Bitmask mUnusable, /* Ignore terms with these prereqs */ + struct SrcList_item *pSrc, /* The FROM clause term that is the vtab */ + ExprList *pOrderBy, /* The ORDER BY clause */ + u16 *pmNoOmit /* Mask of terms not to omit */ ){ - /* An "IS" term in the WHERE clause where the virtual table is the rhs - ** of a LEFT JOIN. Do not pass this term to the virtual table - ** implementation, as this can lead to incorrect results from SQL such - ** as: - ** - ** "LEFT JOIN vtab WHERE vtab.col IS NULL" */ - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_IS ); - continue; - } - assert( pTerm->u.leftColumn>=(-1) ); - pIdxCons[j].iColumn = pTerm->u.leftColumn; - pIdxCons[j].iTermOffset = i; - op = pTerm->eOperator & WO_ALL; - if( op==WO_IN ) op = WO_EQ; - if( op==WO_AUX ){ - pIdxCons[j].op = pTerm->eMatchOp; - }else if( op & (WO_ISNULL|WO_IS) ){ - if( op==WO_ISNULL ){ - pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL; - }else{ - pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS; - } - }else{ - pIdxCons[j].op = (u8)op; - /* The direct assignment in the previous line is possible only because - ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The - ** following asserts verify this fact. */ - assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); - assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); - assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); - assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); - assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); - assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) ); + int i, j; + int nTerm; + struct sqlite3_index_constraint *pIdxCons; + struct sqlite3_index_orderby *pIdxOrderBy; + struct sqlite3_index_constraint_usage *pUsage; + struct HiddenIndexInfo *pHidden; + WhereTerm *pTerm; + int nOrderBy; + sqlite3_index_info *pIdxInfo; + u16 mNoOmit = 0; - if( op & (WO_LT|WO_LE|WO_GT|WO_GE) - && sqlite3ExprIsVector(pTerm->pExpr->pRight) - ){ - if( i<16 ) mNoOmit |= (1 << i); - if( op==WO_LT ) pIdxCons[j].op = WO_LE; - if( op==WO_GT ) pIdxCons[j].op = WO_GE; - } + /* Count the number of possible WHERE clause constraints referring + ** to this virtual table */ + for (i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++) { + if (pTerm->leftCursor != pSrc->iCursor) continue; + if (pTerm->prereqRight & mUnusable) continue; + assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV)); + testcase( pTerm->eOperator & WO_IN ); + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_IS ); + testcase( pTerm->eOperator & WO_ALL ); + if ((pTerm->eOperator & ~(WO_EQUIV))==0) continue; + if (pTerm->wtFlags & TERM_VNULL) continue; + assert( pTerm->u.leftColumn>=(-1)); + nTerm++; } - j++; - } - for(i=0; ia[i].pExpr; - pIdxOrderBy[i].iColumn = pExpr->iColumn; - pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; - } + /* If the ORDER BY clause contains only columns in the current + ** virtual table then allocate space for the aOrderBy part of + ** the sqlite3_index_info structure. + */ + nOrderBy = 0; + if (pOrderBy) { + int n = pOrderBy->nExpr; + for (i=0; ia[i].pExpr; + if (pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor) break; + } + if (i==n) { + nOrderBy = n; + } + } - *pmNoOmit = mNoOmit; - return pIdxInfo; + /* Allocate the sqlite3_index_info structure + */ + pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm + + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden)); + if (pIdxInfo==0) { + sqlite3ErrorMsg(pParse, "out of memory"); + return 0; + } + + /* Initialize the structure. The sqlite3_index_info structure contains + ** many fields that are declared "const" to prevent xBestIndex from + ** changing them. We have to do some funky casting in order to + ** initialize those fields. + */ + pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; + pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1]; + pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; + pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; + *(int*)&pIdxInfo->nConstraint = nTerm; + *(int*)&pIdxInfo->nOrderBy = nOrderBy; + *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; + *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; + *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = + pUsage; + + pHidden->pWC = pWC; + pHidden->pParse = pParse; + for (i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++) { + u16 op; + if (pTerm->leftCursor != pSrc->iCursor) continue; + if (pTerm->prereqRight & mUnusable) continue; + assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV)); + testcase( pTerm->eOperator & WO_IN ); + testcase( pTerm->eOperator & WO_IS ); + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_ALL ); + if ((pTerm->eOperator & ~(WO_EQUIV))==0) continue; + if (pTerm->wtFlags & TERM_VNULL) continue; + if ((pSrc->fg.jointype & JT_LEFT)!=0 + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + && (pTerm->eOperator & (WO_IS|WO_ISNULL)) + ) { + /* An "IS" term in the WHERE clause where the virtual table is the rhs + ** of a LEFT JOIN. Do not pass this term to the virtual table + ** implementation, as this can lead to incorrect results from SQL such + ** as: + ** + ** "LEFT JOIN vtab WHERE vtab.col IS NULL" */ + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_IS ); + continue; + } + assert( pTerm->u.leftColumn>=(-1)); + pIdxCons[j].iColumn = pTerm->u.leftColumn; + pIdxCons[j].iTermOffset = i; + op = pTerm->eOperator & WO_ALL; + if (op==WO_IN) op = WO_EQ; + if (op==WO_AUX) { + pIdxCons[j].op = pTerm->eMatchOp; + } else if (op & (WO_ISNULL|WO_IS)) { + if (op==WO_ISNULL) { + pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL; + } else { + pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS; + } + } else { + pIdxCons[j].op = (u8)op; + /* The direct assignment in the previous line is possible only because + ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The + ** following asserts verify this fact. */ + assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); + assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); + assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); + assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); + assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); + assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX)); + + if (op & (WO_LT|WO_LE|WO_GT|WO_GE) + && sqlite3ExprIsVector(pTerm->pExpr->pRight) + ) { + if (i<16) mNoOmit |= (1 << i); + if (op==WO_LT) pIdxCons[j].op = WO_LE; + if (op==WO_GT) pIdxCons[j].op = WO_GE; + } + } + + j++; + } + for (i=0; ia[i].pExpr; + pIdxOrderBy[i].iColumn = pExpr->iColumn; + pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; + } + + *pmNoOmit = mNoOmit; + return pIdxInfo; } /* @@ -1055,25 +1055,25 @@ static sqlite3_index_info *allocateIndexInfo( ** that this is required. */ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ - sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; - int rc; + sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; + int rc; - TRACE_IDX_INPUTS(p); - rc = pVtab->pModule->xBestIndex(pVtab, p); - TRACE_IDX_OUTPUTS(p); + TRACE_IDX_INPUTS(p); + rc = pVtab->pModule->xBestIndex(pVtab, p); + TRACE_IDX_OUTPUTS(p); - if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ - if( rc==SQLITE_NOMEM ){ - sqlite3OomFault(pParse->db); - }else if( !pVtab->zErrMsg ){ - sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); - }else{ - sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); + if (rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT) { + if (rc==SQLITE_NOMEM) { + sqlite3OomFault(pParse->db); + } else if (!pVtab->zErrMsg) { + sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); + } else { + sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); + } } - } - sqlite3_free(pVtab->zErrMsg); - pVtab->zErrMsg = 0; - return rc; + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = 0; + return rc; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ @@ -1088,193 +1088,193 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ ** Return the index of the sample that is the smallest sample that ** is greater than or equal to pRec. Note that this index is not an index ** into the aSample[] array - it is an index into a virtual set of samples -** based on the contents of aSample[] and the number of fields in record -** pRec. +** based on the contents of aSample[] and the number of fields in record +** pRec. */ static int whereKeyStats( - Parse *pParse, /* Database connection */ - Index *pIdx, /* Index to consider domain of */ - UnpackedRecord *pRec, /* Vector of values to consider */ - int roundUp, /* Round up if true. Round down if false */ - tRowcnt *aStat /* OUT: stats written here */ -){ - IndexSample *aSample = pIdx->aSample; - int iCol; /* Index of required stats in anEq[] etc. */ - int i; /* Index of first sample >= pRec */ - int iSample; /* Smallest sample larger than or equal to pRec */ - int iMin = 0; /* Smallest sample not yet tested */ - int iTest; /* Next sample to test */ - int res; /* Result of comparison operation */ - int nField; /* Number of fields in pRec */ - tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */ + Parse *pParse, /* Database connection */ + Index *pIdx, /* Index to consider domain of */ + UnpackedRecord *pRec, /* Vector of values to consider */ + int roundUp, /* Round up if true. Round down if false */ + tRowcnt *aStat /* OUT: stats written here */ + ){ + IndexSample *aSample = pIdx->aSample; + int iCol; /* Index of required stats in anEq[] etc. */ + int i; /* Index of first sample >= pRec */ + int iSample; /* Smallest sample larger than or equal to pRec */ + int iMin = 0; /* Smallest sample not yet tested */ + int iTest; /* Next sample to test */ + int res; /* Result of comparison operation */ + int nField; /* Number of fields in pRec */ + tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */ #ifndef SQLITE_DEBUG - UNUSED_PARAMETER( pParse ); + UNUSED_PARAMETER( pParse ); #endif - assert( pRec!=0 ); - assert( pIdx->nSample>0 ); - assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol ); + assert( pRec!=0 ); + assert( pIdx->nSample>0 ); + assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol ); - /* Do a binary search to find the first sample greater than or equal - ** to pRec. If pRec contains a single field, the set of samples to search - ** is simply the aSample[] array. If the samples in aSample[] contain more - ** than one fields, all fields following the first are ignored. - ** - ** If pRec contains N fields, where N is more than one, then as well as the - ** samples in aSample[] (truncated to N fields), the search also has to - ** consider prefixes of those samples. For example, if the set of samples - ** in aSample is: - ** - ** aSample[0] = (a, 5) - ** aSample[1] = (a, 10) - ** aSample[2] = (b, 5) - ** aSample[3] = (c, 100) - ** aSample[4] = (c, 105) - ** - ** Then the search space should ideally be the samples above and the - ** unique prefixes [a], [b] and [c]. But since that is hard to organize, - ** the code actually searches this set: - ** - ** 0: (a) - ** 1: (a, 5) - ** 2: (a, 10) - ** 3: (a, 10) - ** 4: (b) - ** 5: (b, 5) - ** 6: (c) - ** 7: (c, 100) - ** 8: (c, 105) - ** 9: (c, 105) - ** - ** For each sample in the aSample[] array, N samples are present in the - ** effective sample array. In the above, samples 0 and 1 are based on - ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc. - ** - ** Often, sample i of each block of N effective samples has (i+1) fields. - ** Except, each sample may be extended to ensure that it is greater than or - ** equal to the previous sample in the array. For example, in the above, - ** sample 2 is the first sample of a block of N samples, so at first it - ** appears that it should be 1 field in size. However, that would make it - ** smaller than sample 1, so the binary search would not work. As a result, - ** it is extended to two fields. The duplicates that this creates do not - ** cause any problems. - */ - nField = pRec->nField; - iCol = 0; - iSample = pIdx->nSample * nField; - do{ - int iSamp; /* Index in aSample[] of test sample */ - int n; /* Number of fields in test sample */ + /* Do a binary search to find the first sample greater than or equal + ** to pRec. If pRec contains a single field, the set of samples to search + ** is simply the aSample[] array. If the samples in aSample[] contain more + ** than one fields, all fields following the first are ignored. + ** + ** If pRec contains N fields, where N is more than one, then as well as the + ** samples in aSample[] (truncated to N fields), the search also has to + ** consider prefixes of those samples. For example, if the set of samples + ** in aSample is: + ** + ** aSample[0] = (a, 5) + ** aSample[1] = (a, 10) + ** aSample[2] = (b, 5) + ** aSample[3] = (c, 100) + ** aSample[4] = (c, 105) + ** + ** Then the search space should ideally be the samples above and the + ** unique prefixes [a], [b] and [c]. But since that is hard to organize, + ** the code actually searches this set: + ** + ** 0: (a) + ** 1: (a, 5) + ** 2: (a, 10) + ** 3: (a, 10) + ** 4: (b) + ** 5: (b, 5) + ** 6: (c) + ** 7: (c, 100) + ** 8: (c, 105) + ** 9: (c, 105) + ** + ** For each sample in the aSample[] array, N samples are present in the + ** effective sample array. In the above, samples 0 and 1 are based on + ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc. + ** + ** Often, sample i of each block of N effective samples has (i+1) fields. + ** Except, each sample may be extended to ensure that it is greater than or + ** equal to the previous sample in the array. For example, in the above, + ** sample 2 is the first sample of a block of N samples, so at first it + ** appears that it should be 1 field in size. However, that would make it + ** smaller than sample 1, so the binary search would not work. As a result, + ** it is extended to two fields. The duplicates that this creates do not + ** cause any problems. + */ + nField = pRec->nField; + iCol = 0; + iSample = pIdx->nSample * nField; + do{ + int iSamp; /* Index in aSample[] of test sample */ + int n; /* Number of fields in test sample */ - iTest = (iMin+iSample)/2; - iSamp = iTest / nField; - if( iSamp>0 ){ - /* The proposed effective sample is a prefix of sample aSample[iSamp]. - ** Specifically, the shortest prefix of at least (1 + iTest%nField) - ** fields that is greater than the previous effective sample. */ - for(n=(iTest % nField) + 1; n0) { + /* The proposed effective sample is a prefix of sample aSample[iSamp]. + ** Specifically, the shortest prefix of at least (1 + iTest%nField) + ** fields that is greater than the previous effective sample. */ + for (n=(iTest % nField) + 1; nnField = n; - res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec); - if( res<0 ){ - iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1]; - iMin = iTest+1; - }else if( res==0 && nnField = n; + res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec); + if (res<0) { + iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1]; + iMin = iTest+1; + } else if (res==0 && ndb->mallocFailed==0 ){ - if( res==0 ){ - /* If (res==0) is true, then pRec must be equal to sample i. */ - assert( inSample ); - assert( iCol==nField-1 ); - pRec->nField = nField; - assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) - || pParse->db->mallocFailed - ); - }else{ - /* Unless i==pIdx->nSample, indicating that pRec is larger than - ** all samples in the aSample[] array, pRec must be smaller than the - ** (iCol+1) field prefix of sample i. */ - assert( i<=pIdx->nSample && i>=0 ); - pRec->nField = iCol+1; - assert( i==pIdx->nSample - || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 - || pParse->db->mallocFailed ); + /* The following assert statements check that the binary search code + ** above found the right answer. This block serves no purpose other + ** than to invoke the asserts. */ + if (pParse->db->mallocFailed==0) { + if (res==0) { + /* If (res==0) is true, then pRec must be equal to sample i. */ + assert( inSample ); + assert( iCol==nField-1 ); + pRec->nField = nField; + assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) + || pParse->db->mallocFailed + ); + } else { + /* Unless i==pIdx->nSample, indicating that pRec is larger than + ** all samples in the aSample[] array, pRec must be smaller than the + ** (iCol+1) field prefix of sample i. */ + assert( i<=pIdx->nSample && i>=0 ); + pRec->nField = iCol+1; + assert( i==pIdx->nSample + || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 + || pParse->db->mallocFailed ); - /* if i==0 and iCol==0, then record pRec is smaller than all samples - ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must - ** be greater than or equal to the (iCol) field prefix of sample i. - ** If (i>0), then pRec must also be greater than sample (i-1). */ - if( iCol>0 ){ - pRec->nField = iCol; - assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 - || pParse->db->mallocFailed ); - } - if( i>0 ){ - pRec->nField = nField; - assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 - || pParse->db->mallocFailed ); - } + /* if i==0 and iCol==0, then record pRec is smaller than all samples + ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must + ** be greater than or equal to the (iCol) field prefix of sample i. + ** If (i>0), then pRec must also be greater than sample (i-1). */ + if (iCol>0) { + pRec->nField = iCol; + assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 + || pParse->db->mallocFailed ); + } + if (i>0) { + pRec->nField = nField; + assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 + || pParse->db->mallocFailed ); + } + } } - } #endif /* ifdef SQLITE_DEBUG */ - if( res==0 ){ - /* Record pRec is equal to sample i */ - assert( iCol==nField-1 ); - aStat[0] = aSample[i].anLt[iCol]; - aStat[1] = aSample[i].anEq[iCol]; - }else{ - /* At this point, the (iCol+1) field prefix of aSample[i] is the first - ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec - ** is larger than all samples in the array. */ - tRowcnt iUpper, iGap; - if( i>=pIdx->nSample ){ - iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); - }else{ - iUpper = aSample[i].anLt[iCol]; + if (res==0) { + /* Record pRec is equal to sample i */ + assert( iCol==nField-1 ); + aStat[0] = aSample[i].anLt[iCol]; + aStat[1] = aSample[i].anEq[iCol]; + } else { + /* At this point, the (iCol+1) field prefix of aSample[i] is the first + ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec + ** is larger than all samples in the array. */ + tRowcnt iUpper, iGap; + if (i>=pIdx->nSample) { + iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); + } else { + iUpper = aSample[i].anLt[iCol]; + } + + if (iLower>=iUpper) { + iGap = 0; + } else { + iGap = iUpper - iLower; + } + if (roundUp) { + iGap = (iGap*2)/3; + } else { + iGap = iGap/3; + } + aStat[0] = iLower + iGap; + aStat[1] = pIdx->aAvgEq[nField-1]; } - if( iLower>=iUpper ){ - iGap = 0; - }else{ - iGap = iUpper - iLower; - } - if( roundUp ){ - iGap = (iGap*2)/3; - }else{ - iGap = iGap/3; - } - aStat[0] = iLower + iGap; - aStat[1] = pIdx->aAvgEq[nField-1]; - } - - /* Restore the pRec->nField value before returning. */ - pRec->nField = nField; - return i; + /* Restore the pRec->nField value before returning. */ + pRec->nField = nField; + return i; } #endif /* SQLITE_ENABLE_STAT4 */ /* ** If it is not NULL, pTerm is a term that provides an upper or lower -** bound on a range scan. Without considering pTerm, it is estimated +** bound on a range scan. Without considering pTerm, it is estimated ** that the scan will visit nNew rows. This function returns the number ** estimated to be visited after taking pTerm into account. ** @@ -1284,15 +1284,15 @@ static int whereKeyStats( ** has a likelihood of 0.50, and any other term a likelihood of 0.25. */ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ - LogEst nRet = nNew; - if( pTerm ){ - if( pTerm->truthProb<=0 ){ - nRet += pTerm->truthProb; - }else if( (pTerm->wtFlags & TERM_VNULL)==0 ){ - nRet -= 20; assert( 20==sqlite3LogEst(4) ); + LogEst nRet = nNew; + if (pTerm) { + if (pTerm->truthProb<=0) { + nRet += pTerm->truthProb; + } else if ((pTerm->wtFlags & TERM_VNULL)==0) { + nRet -= 20; assert( 20==sqlite3LogEst(4)); + } } - } - return nRet; + return nRet; } @@ -1301,29 +1301,29 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ ** Return the affinity for a single column of an index. */ char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ - assert( iCol>=0 && iColnColumn ); - if( !pIdx->zColAff ){ - if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB; - } - assert( pIdx->zColAff[iCol]!=0 ); - return pIdx->zColAff[iCol]; + assert( iCol>=0 && iColnColumn ); + if (!pIdx->zColAff) { + if (sqlite3IndexAffinityStr(db, pIdx)==0) return SQLITE_AFF_BLOB; + } + assert( pIdx->zColAff[iCol]!=0 ); + return pIdx->zColAff[iCol]; } #endif #ifdef SQLITE_ENABLE_STAT4 -/* +/* ** This function is called to estimate the number of rows visited by a ** range-scan on a skip-scan index. For example: ** ** CREATE INDEX i1 ON t1(a, b, c); ** SELECT * FROM t1 WHERE a=? AND c BETWEEN ? AND ?; ** -** Value pLoop->nOut is currently set to the estimated number of rows -** visited for scanning (a=? AND b=?). This function reduces that estimate +** Value pLoop->nOut is currently set to the estimated number of rows +** visited for scanning (a=? AND b=?). This function reduces that estimate ** by some factor to account for the (c BETWEEN ? AND ?) expression based -** on the stat4 data for the index. this scan will be peformed multiple -** times (once for each (a,b) combination that matches a=?) is dealt with +** on the stat4 data for the index. this scan will be peformed multiple +** times (once for each (a,b) combination that matches a=?) is dealt with ** by the caller. ** ** It does this by scanning through all stat4 samples, comparing values @@ -1344,78 +1344,78 @@ char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){ ** estimate of the number of rows delivered remains unchanged), *pbDone ** is left as is. ** -** If an error occurs, an SQLite error code is returned. Otherwise, +** If an error occurs, an SQLite error code is returned. Otherwise, ** SQLITE_OK. */ static int whereRangeSkipScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ - WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ - WhereLoop *pLoop, /* Update the .nOut value of this loop */ - int *pbDone /* Set to true if at least one expr. value extracted */ -){ - Index *p = pLoop->u.btree.pIndex; - int nEq = pLoop->u.btree.nEq; - sqlite3 *db = pParse->db; - int nLower = -1; - int nUpper = p->nSample+1; - int rc = SQLITE_OK; - u8 aff = sqlite3IndexColumnAffinity(db, p, nEq); - CollSeq *pColl; - - sqlite3_value *p1 = 0; /* Value extracted from pLower */ - sqlite3_value *p2 = 0; /* Value extracted from pUpper */ - sqlite3_value *pVal = 0; /* Value extracted from record */ + Parse *pParse, /* Parsing & code generating context */ + WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ + WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ + WhereLoop *pLoop, /* Update the .nOut value of this loop */ + int *pbDone /* Set to true if at least one expr. value extracted */ + ){ + Index *p = pLoop->u.btree.pIndex; + int nEq = pLoop->u.btree.nEq; + sqlite3 *db = pParse->db; + int nLower = -1; + int nUpper = p->nSample+1; + int rc = SQLITE_OK; + u8 aff = sqlite3IndexColumnAffinity(db, p, nEq); + CollSeq *pColl; - pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]); - if( pLower ){ - rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1); - nLower = 0; - } - if( pUpper && rc==SQLITE_OK ){ - rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2); - nUpper = p2 ? 0 : p->nSample; - } + sqlite3_value *p1 = 0; /* Value extracted from pLower */ + sqlite3_value *p2 = 0; /* Value extracted from pUpper */ + sqlite3_value *pVal = 0; /* Value extracted from record */ - if( p1 || p2 ){ - int i; - int nDiff; - for(i=0; rc==SQLITE_OK && inSample; i++){ - rc = sqlite3Stat4Column(db, p->aSample[i].p, p->aSample[i].n, nEq, &pVal); - if( rc==SQLITE_OK && p1 ){ - int res = sqlite3MemCompare(p1, pVal, pColl); - if( res>=0 ) nLower++; - } - if( rc==SQLITE_OK && p2 ){ - int res = sqlite3MemCompare(p2, pVal, pColl); - if( res>=0 ) nUpper++; - } + pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]); + if (pLower) { + rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1); + nLower = 0; } - nDiff = (nUpper - nLower); - if( nDiff<=0 ) nDiff = 1; - - /* If there is both an upper and lower bound specified, and the - ** comparisons indicate that they are close together, use the fallback - ** method (assume that the scan visits 1/64 of the rows) for estimating - ** the number of rows visited. Otherwise, estimate the number of rows - ** using the method described in the header comment for this function. */ - if( nDiff!=1 || pUpper==0 || pLower==0 ){ - int nAdjust = (sqlite3LogEst(p->nSample) - sqlite3LogEst(nDiff)); - pLoop->nOut -= nAdjust; - *pbDone = 1; - WHERETRACE(0x10, ("range skip-scan regions: %u..%u adjust=%d est=%d\n", - nLower, nUpper, nAdjust*-1, pLoop->nOut)); + if (pUpper && rc==SQLITE_OK) { + rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2); + nUpper = p2 ? 0 : p->nSample; } - }else{ - assert( *pbDone==0 ); - } + if (p1 || p2) { + int i; + int nDiff; + for (i=0; rc==SQLITE_OK && inSample; i++) { + rc = sqlite3Stat4Column(db, p->aSample[i].p, p->aSample[i].n, nEq, &pVal); + if (rc==SQLITE_OK && p1) { + int res = sqlite3MemCompare(p1, pVal, pColl); + if (res>=0) nLower++; + } + if (rc==SQLITE_OK && p2) { + int res = sqlite3MemCompare(p2, pVal, pColl); + if (res>=0) nUpper++; + } + } + nDiff = (nUpper - nLower); + if (nDiff<=0) nDiff = 1; - sqlite3ValueFree(p1); - sqlite3ValueFree(p2); - sqlite3ValueFree(pVal); + /* If there is both an upper and lower bound specified, and the + ** comparisons indicate that they are close together, use the fallback + ** method (assume that the scan visits 1/64 of the rows) for estimating + ** the number of rows visited. Otherwise, estimate the number of rows + ** using the method described in the header comment for this function. */ + if (nDiff!=1 || pUpper==0 || pLower==0) { + int nAdjust = (sqlite3LogEst(p->nSample) - sqlite3LogEst(nDiff)); + pLoop->nOut -= nAdjust; + *pbDone = 1; + WHERETRACE(0x10, ("range skip-scan regions: %u..%u adjust=%d est=%d\n", + nLower, nUpper, nAdjust* -1, pLoop->nOut)); + } - return rc; + } else { + assert( *pbDone==0 ); + } + + sqlite3ValueFree(p1); + sqlite3ValueFree(p2); + sqlite3ValueFree(pVal); + + return rc; } #endif /* SQLITE_ENABLE_STAT4 */ @@ -1441,7 +1441,7 @@ static int whereRangeSkipScanEst( ** ** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... ** -** then nEq is set to 1 (as the range restricted column, b, is the second +** then nEq is set to 1 (as the range restricted column, b, is the second ** left-most column of the index). Or, if the query is: ** ** ... FROM t1 WHERE a > ? AND a < ? ... @@ -1449,177 +1449,177 @@ static int whereRangeSkipScanEst( ** then nEq is set to 0. ** ** When this function is called, *pnOut is set to the sqlite3LogEst() of the -** number of rows that the index scan is expected to visit without -** considering the range constraints. If nEq is 0, then *pnOut is the number of +** number of rows that the index scan is expected to visit without +** considering the range constraints. If nEq is 0, then *pnOut is the number of ** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced) ** to account for the range constraints pLower and pUpper. -** +** ** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be -** used, a single range inequality reduces the search space by a factor of 4. +** used, a single range inequality reduces the search space by a factor of 4. ** and a pair of constraints (x>? AND x123" Might be NULL */ - WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ - WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */ -){ - int rc = SQLITE_OK; - int nOut = pLoop->nOut; - LogEst nNew; + Parse *pParse, /* Parsing & code generating context */ + WhereLoopBuilder *pBuilder, + WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ + WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ + WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */ + ){ + int rc = SQLITE_OK; + int nOut = pLoop->nOut; + LogEst nNew; #ifdef SQLITE_ENABLE_STAT4 - Index *p = pLoop->u.btree.pIndex; - int nEq = pLoop->u.btree.nEq; + Index *p = pLoop->u.btree.pIndex; + int nEq = pLoop->u.btree.nEq; - if( p->nSample>0 && ALWAYS(nEqnSampleCol) - && OptimizationEnabled(pParse->db, SQLITE_Stat4) - ){ - if( nEq==pBuilder->nRecValid ){ - UnpackedRecord *pRec = pBuilder->pRec; - tRowcnt a[2]; - int nBtm = pLoop->u.btree.nBtm; - int nTop = pLoop->u.btree.nTop; + if (p->nSample>0 && ALWAYS(nEqnSampleCol) + && OptimizationEnabled(pParse->db, SQLITE_Stat4) + ) { + if (nEq==pBuilder->nRecValid) { + UnpackedRecord *pRec = pBuilder->pRec; + tRowcnt a[2]; + int nBtm = pLoop->u.btree.nBtm; + int nTop = pLoop->u.btree.nTop; - /* Variable iLower will be set to the estimate of the number of rows in - ** the index that are less than the lower bound of the range query. The - ** lower bound being the concatenation of $P and $L, where $P is the - ** key-prefix formed by the nEq values matched against the nEq left-most - ** columns of the index, and $L is the value in pLower. - ** - ** Or, if pLower is NULL or $L cannot be extracted from it (because it - ** is not a simple variable or literal value), the lower bound of the - ** range is $P. Due to a quirk in the way whereKeyStats() works, even - ** if $L is available, whereKeyStats() is called for both ($P) and - ** ($P:$L) and the larger of the two returned values is used. - ** - ** Similarly, iUpper is to be set to the estimate of the number of rows - ** less than the upper bound of the range query. Where the upper bound - ** is either ($P) or ($P:$U). Again, even if $U is available, both values - ** of iUpper are requested of whereKeyStats() and the smaller used. - ** - ** The number of rows between the two bounds is then just iUpper-iLower. - */ - tRowcnt iLower; /* Rows less than the lower bound */ - tRowcnt iUpper; /* Rows less than the upper bound */ - int iLwrIdx = -2; /* aSample[] for the lower bound */ - int iUprIdx = -1; /* aSample[] for the upper bound */ + /* Variable iLower will be set to the estimate of the number of rows in + ** the index that are less than the lower bound of the range query. The + ** lower bound being the concatenation of $P and $L, where $P is the + ** key-prefix formed by the nEq values matched against the nEq left-most + ** columns of the index, and $L is the value in pLower. + ** + ** Or, if pLower is NULL or $L cannot be extracted from it (because it + ** is not a simple variable or literal value), the lower bound of the + ** range is $P. Due to a quirk in the way whereKeyStats() works, even + ** if $L is available, whereKeyStats() is called for both ($P) and + ** ($P:$L) and the larger of the two returned values is used. + ** + ** Similarly, iUpper is to be set to the estimate of the number of rows + ** less than the upper bound of the range query. Where the upper bound + ** is either ($P) or ($P:$U). Again, even if $U is available, both values + ** of iUpper are requested of whereKeyStats() and the smaller used. + ** + ** The number of rows between the two bounds is then just iUpper-iLower. + */ + tRowcnt iLower; /* Rows less than the lower bound */ + tRowcnt iUpper; /* Rows less than the upper bound */ + int iLwrIdx = -2; /* aSample[] for the lower bound */ + int iUprIdx = -1; /* aSample[] for the upper bound */ - if( pRec ){ - testcase( pRec->nField!=pBuilder->nRecValid ); - pRec->nField = pBuilder->nRecValid; - } - /* Determine iLower and iUpper using ($P) only. */ - if( nEq==0 ){ - iLower = 0; - iUpper = p->nRowEst0; - }else{ - /* Note: this call could be optimized away - since the same values must - ** have been requested when testing key $P in whereEqualScanEst(). */ - whereKeyStats(pParse, p, pRec, 0, a); - iLower = a[0]; - iUpper = a[0] + a[1]; - } + if (pRec) { + testcase( pRec->nField!=pBuilder->nRecValid ); + pRec->nField = pBuilder->nRecValid; + } + /* Determine iLower and iUpper using ($P) only. */ + if (nEq==0) { + iLower = 0; + iUpper = p->nRowEst0; + } else { + /* Note: this call could be optimized away - since the same values must + ** have been requested when testing key $P in whereEqualScanEst(). */ + whereKeyStats(pParse, p, pRec, 0, a); + iLower = a[0]; + iUpper = a[0] + a[1]; + } - assert( pLower==0 || (pLower->eOperator & (WO_GT|WO_GE))!=0 ); - assert( pUpper==0 || (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); - assert( p->aSortOrder!=0 ); - if( p->aSortOrder[nEq] ){ - /* The roles of pLower and pUpper are swapped for a DESC index */ - SWAP(WhereTerm*, pLower, pUpper); - SWAP(int, nBtm, nTop); - } + assert( pLower==0 || (pLower->eOperator & (WO_GT|WO_GE))!=0 ); + assert( pUpper==0 || (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); + assert( p->aSortOrder!=0 ); + if (p->aSortOrder[nEq]) { + /* The roles of pLower and pUpper are swapped for a DESC index */ + SWAP(WhereTerm*, pLower, pUpper); + SWAP(int, nBtm, nTop); + } - /* If possible, improve on the iLower estimate using ($P:$L). */ - if( pLower ){ - int n; /* Values extracted from pExpr */ - Expr *pExpr = pLower->pExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n); - if( rc==SQLITE_OK && n ){ - tRowcnt iNew; - u16 mask = WO_GT|WO_LE; - if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); - iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a); - iNew = a[0] + ((pLower->eOperator & mask) ? a[1] : 0); - if( iNew>iLower ) iLower = iNew; - nOut--; - pLower = 0; + /* If possible, improve on the iLower estimate using ($P:$L). */ + if (pLower) { + int n; /* Values extracted from pExpr */ + Expr *pExpr = pLower->pExpr->pRight; + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n); + if (rc==SQLITE_OK && n) { + tRowcnt iNew; + u16 mask = WO_GT|WO_LE; + if (sqlite3ExprVectorSize(pExpr)>n) mask = (WO_LE|WO_LT); + iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a); + iNew = a[0] + ((pLower->eOperator & mask) ? a[1] : 0); + if (iNew>iLower) iLower = iNew; + nOut--; + pLower = 0; + } + } + + /* If possible, improve on the iUpper estimate using ($P:$U). */ + if (pUpper) { + int n; /* Values extracted from pExpr */ + Expr *pExpr = pUpper->pExpr->pRight; + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n); + if (rc==SQLITE_OK && n) { + tRowcnt iNew; + u16 mask = WO_GT|WO_LE; + if (sqlite3ExprVectorSize(pExpr)>n) mask = (WO_LE|WO_LT); + iUprIdx = whereKeyStats(pParse, p, pRec, 1, a); + iNew = a[0] + ((pUpper->eOperator & mask) ? a[1] : 0); + if (iNewpRec = pRec; + if (rc==SQLITE_OK) { + if (iUpper>iLower) { + nNew = sqlite3LogEst(iUpper - iLower); + /* TUNING: If both iUpper and iLower are derived from the same + ** sample, then assume they are 4x more selective. This brings + ** the estimated selectivity more in line with what it would be + ** if estimated without the use of STAT4 tables. */ + if (iLwrIdx==iUprIdx) nNew -= 20; assert( 20==sqlite3LogEst(4)); + } else { + nNew = 10; assert( 10==sqlite3LogEst(2)); + } + if (nNewpExpr->pRight; - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n); - if( rc==SQLITE_OK && n ){ - tRowcnt iNew; - u16 mask = WO_GT|WO_LE; - if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT); - iUprIdx = whereKeyStats(pParse, p, pRec, 1, a); - iNew = a[0] + ((pUpper->eOperator & mask) ? a[1] : 0); - if( iNewpRec = pRec; - if( rc==SQLITE_OK ){ - if( iUpper>iLower ){ - nNew = sqlite3LogEst(iUpper - iLower); - /* TUNING: If both iUpper and iLower are derived from the same - ** sample, then assume they are 4x more selective. This brings - ** the estimated selectivity more in line with what it would be - ** if estimated without the use of STAT4 tables. */ - if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) ); - }else{ - nNew = 10; assert( 10==sqlite3LogEst(2) ); - } - if( nNewwtFlags & TERM_VNULL)==0 ); - nNew = whereRangeAdjust(pLower, nOut); - nNew = whereRangeAdjust(pUpper, nNew); + assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 ); + nNew = whereRangeAdjust(pLower, nOut); + nNew = whereRangeAdjust(pUpper, nNew); - /* TUNING: If there is both an upper and lower limit and neither limit - ** has an application-defined likelihood(), assume the range is - ** reduced by an additional 75%. This means that, by default, an open-ended - ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the - ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to - ** match 1/64 of the index. */ - if( pLower && pLower->truthProb>0 && pUpper && pUpper->truthProb>0 ){ - nNew -= 20; - } + /* TUNING: If there is both an upper and lower limit and neither limit + ** has an application-defined likelihood(), assume the range is + ** reduced by an additional 75%. This means that, by default, an open-ended + ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the + ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to + ** match 1/64 of the index. */ + if (pLower && pLower->truthProb>0 && pUpper && pUpper->truthProb>0) { + nNew -= 20; + } - nOut -= (pLower!=0) + (pUpper!=0); - if( nNew<10 ) nNew = 10; - if( nNewnOut>nOut ){ - WHERETRACE(0x10,("Range scan lowers nOut from %d to %d\n", - pLoop->nOut, nOut)); - } + if (pLoop->nOut>nOut) { + WHERETRACE(0x10,("Range scan lowers nOut from %d to %d\n", + pLoop->nOut, nOut)); + } #endif - pLoop->nOut = (LogEst)nOut; - return rc; + pLoop->nOut = (LogEst)nOut; + return rc; } #ifdef SQLITE_ENABLE_STAT4 @@ -1631,7 +1631,7 @@ static int whereRangeScanEst( ** for that index. When pExpr==NULL that means the constraint is ** "x IS NULL" instead of "x=VALUE". ** -** Write the estimated row count into *pnRow and return SQLITE_OK. +** Write the estimated row count into *pnRow and return SQLITE_OK. ** If unable to make an estimate, leave *pnRow unchanged and return ** non-zero. ** @@ -1641,49 +1641,49 @@ static int whereRangeScanEst( ** in the pParse structure. */ static int whereEqualScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereLoopBuilder *pBuilder, - Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ - tRowcnt *pnRow /* Write the revised row estimate here */ -){ - Index *p = pBuilder->pNew->u.btree.pIndex; - int nEq = pBuilder->pNew->u.btree.nEq; - UnpackedRecord *pRec = pBuilder->pRec; - int rc; /* Subfunction return code */ - tRowcnt a[2]; /* Statistics */ - int bOk; + Parse *pParse, /* Parsing & code generating context */ + WhereLoopBuilder *pBuilder, + Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ + tRowcnt *pnRow /* Write the revised row estimate here */ + ){ + Index *p = pBuilder->pNew->u.btree.pIndex; + int nEq = pBuilder->pNew->u.btree.nEq; + UnpackedRecord *pRec = pBuilder->pRec; + int rc; /* Subfunction return code */ + tRowcnt a[2]; /* Statistics */ + int bOk; - assert( nEq>=1 ); - assert( nEq<=p->nColumn ); - assert( p->aSample!=0 ); - assert( p->nSample>0 ); - assert( pBuilder->nRecValid=1 ); + assert( nEq<=p->nColumn ); + assert( p->aSample!=0 ); + assert( p->nSample>0 ); + assert( pBuilder->nRecValidnRecValid<(nEq-1) ){ - return SQLITE_NOTFOUND; - } + /* If values are not available for all fields of the index to the left + ** of this one, no estimate can be made. Return SQLITE_NOTFOUND. */ + if (pBuilder->nRecValid<(nEq-1)) { + return SQLITE_NOTFOUND; + } - /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue() - ** below would return the same value. */ - if( nEq>=p->nColumn ){ - *pnRow = 1; - return SQLITE_OK; - } + /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue() + ** below would return the same value. */ + if (nEq>=p->nColumn) { + *pnRow = 1; + return SQLITE_OK; + } - rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, 1, nEq-1, &bOk); - pBuilder->pRec = pRec; - if( rc!=SQLITE_OK ) return rc; - if( bOk==0 ) return SQLITE_NOTFOUND; - pBuilder->nRecValid = nEq; + rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, 1, nEq-1, &bOk); + pBuilder->pRec = pRec; + if (rc!=SQLITE_OK) return rc; + if (bOk==0) return SQLITE_NOTFOUND; + pBuilder->nRecValid = nEq; - whereKeyStats(pParse, p, pRec, 0, a); - WHERETRACE(0x10,("equality scan regions %s(%d): %d\n", - p->zName, nEq-1, (int)a[1])); - *pnRow = a[1]; - - return rc; + whereKeyStats(pParse, p, pRec, 0, a); + WHERETRACE(0x10,("equality scan regions %s(%d): %d\n", + p->zName, nEq-1, (int)a[1])); + *pnRow = a[1]; + + return rc; } #endif /* SQLITE_ENABLE_STAT4 */ @@ -1695,7 +1695,7 @@ static int whereEqualScanEst( ** ** WHERE x IN (1,2,3,4) ** -** Write the estimated row count into *pnRow and return SQLITE_OK. +** Write the estimated row count into *pnRow and return SQLITE_OK. ** If unable to make an estimate, leave *pnRow unchanged and return ** non-zero. ** @@ -1705,34 +1705,34 @@ static int whereEqualScanEst( ** in the pParse structure. */ static int whereInScanEst( - Parse *pParse, /* Parsing & code generating context */ - WhereLoopBuilder *pBuilder, - ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ - tRowcnt *pnRow /* Write the revised row estimate here */ -){ - Index *p = pBuilder->pNew->u.btree.pIndex; - i64 nRow0 = sqlite3LogEstToInt(p->aiRowLogEst[0]); - int nRecValid = pBuilder->nRecValid; - int rc = SQLITE_OK; /* Subfunction return code */ - tRowcnt nEst; /* Number of rows for a single term */ - tRowcnt nRowEst = 0; /* New estimate of the number of rows */ - int i; /* Loop counter */ + Parse *pParse, /* Parsing & code generating context */ + WhereLoopBuilder *pBuilder, + ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ + tRowcnt *pnRow /* Write the revised row estimate here */ + ){ + Index *p = pBuilder->pNew->u.btree.pIndex; + i64 nRow0 = sqlite3LogEstToInt(p->aiRowLogEst[0]); + int nRecValid = pBuilder->nRecValid; + int rc = SQLITE_OK; /* Subfunction return code */ + tRowcnt nEst; /* Number of rows for a single term */ + tRowcnt nRowEst = 0; /* New estimate of the number of rows */ + int i; /* Loop counter */ - assert( p->aSample!=0 ); - for(i=0; rc==SQLITE_OK && inExpr; i++){ - nEst = nRow0; - rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); - nRowEst += nEst; - pBuilder->nRecValid = nRecValid; - } + assert( p->aSample!=0 ); + for (i=0; rc==SQLITE_OK && inExpr; i++) { + nEst = nRow0; + rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); + nRowEst += nEst; + pBuilder->nRecValid = nRecValid; + } - if( rc==SQLITE_OK ){ - if( nRowEst > nRow0 ) nRowEst = nRow0; - *pnRow = nRowEst; - WHERETRACE(0x10,("IN row estimate: est=%d\n", nRowEst)); - } - assert( pBuilder->nRecValid==nRecValid ); - return rc; + if (rc==SQLITE_OK) { + if (nRowEst > nRow0) nRowEst = nRow0; + *pnRow = nRowEst; + WHERETRACE(0x10,("IN row estimate: est=%d\n", nRowEst)); + } + assert( pBuilder->nRecValid==nRecValid ); + return rc; } #endif /* SQLITE_ENABLE_STAT4 */ @@ -1742,35 +1742,35 @@ static int whereInScanEst( ** Print the content of a WhereTerm object */ static void whereTermPrint(WhereTerm *pTerm, int iTerm){ - if( pTerm==0 ){ - sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm); - }else{ - char zType[4]; - char zLeft[50]; - memcpy(zType, "...", 4); - if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; - if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; - if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; - if( pTerm->eOperator & WO_SINGLE ){ - sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}", - pTerm->leftCursor, pTerm->u.leftColumn); - }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){ - sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld", - pTerm->u.pOrInfo->indexable); - }else{ - sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); + if (pTerm==0) { + sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm); + } else { + char zType[4]; + char zLeft[50]; + memcpy(zType, "...", 4); + if (pTerm->wtFlags & TERM_VIRTUAL) zType[0] = 'V'; + if (pTerm->eOperator & WO_EQUIV) zType[1] = 'E'; + if (ExprHasProperty(pTerm->pExpr, EP_FromJoin)) zType[2] = 'L'; + if (pTerm->eOperator & WO_SINGLE) { + sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}", + pTerm->leftCursor, pTerm->u.leftColumn); + } else if ((pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0) { + sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld", + pTerm->u.pOrInfo->indexable); + } else { + sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); + } + sqlite3DebugPrintf( + "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x", + iTerm, pTerm, zType, zLeft, pTerm->truthProb, + pTerm->eOperator, pTerm->wtFlags); + if (pTerm->iField) { + sqlite3DebugPrintf(" iField=%d\n", pTerm->iField); + } else { + sqlite3DebugPrintf("\n"); + } + sqlite3TreeViewExpr(0, pTerm->pExpr, 0); } - sqlite3DebugPrintf( - "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x", - iTerm, pTerm, zType, zLeft, pTerm->truthProb, - pTerm->eOperator, pTerm->wtFlags); - if( pTerm->iField ){ - sqlite3DebugPrintf(" iField=%d\n", pTerm->iField); - }else{ - sqlite3DebugPrintf("\n"); - } - sqlite3TreeViewExpr(0, pTerm->pExpr, 0); - } } #endif @@ -1779,10 +1779,10 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){ ** Show the complete content of a WhereClause */ void sqlite3WhereClausePrint(WhereClause *pWC){ - int i; - for(i=0; inTerm; i++){ - whereTermPrint(&pWC->a[i], i); - } + int i; + for (i=0; inTerm; i++) { + whereTermPrint(&pWC->a[i], i); + } } #endif @@ -1791,50 +1791,50 @@ void sqlite3WhereClausePrint(WhereClause *pWC){ ** Print a WhereLoop object for debugging purposes */ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ - WhereInfo *pWInfo = pWC->pWInfo; - int nb = 1+(pWInfo->pTabList->nSrc+3)/4; - struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab; - Table *pTab = pItem->pTab; - Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; - sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, - p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); - sqlite3DebugPrintf(" %12s", - pItem->zAlias ? pItem->zAlias : pTab->zName); - if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - const char *zName; - if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){ - if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ - int i = sqlite3Strlen30(zName) - 1; - while( zName[i]!='_' ) i--; - zName += i; - } - sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq); - }else{ - sqlite3DebugPrintf("%20s",""); + WhereInfo *pWInfo = pWC->pWInfo; + int nb = 1+(pWInfo->pTabList->nSrc+3)/4; + struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab; + Table *pTab = pItem->pTab; + Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1; + sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, + p->iTab, nb, p->maskSelf, nb, p->prereq & mAll); + sqlite3DebugPrintf(" %12s", + pItem->zAlias ? pItem->zAlias : pTab->zName); + if ((p->wsFlags & WHERE_VIRTUALTABLE)==0) { + const char *zName; + if (p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0) { + if (strncmp(zName, "sqlite_autoindex_", 17)==0) { + int i = sqlite3Strlen30(zName) - 1; + while (zName[i]!='_') i--; + zName += i; + } + sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq); + } else { + sqlite3DebugPrintf("%20s",""); + } + } else { + char *z; + if (p->u.vtab.idxStr) { + z = sqlite3_mprintf("(%d,\"%s\",%x)", + p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask); + } else { + z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask); + } + sqlite3DebugPrintf(" %-19s", z); + sqlite3_free(z); } - }else{ - char *z; - if( p->u.vtab.idxStr ){ - z = sqlite3_mprintf("(%d,\"%s\",%x)", - p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask); - }else{ - z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask); + if (p->wsFlags & WHERE_SKIPSCAN) { + sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); + } else { + sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm); } - sqlite3DebugPrintf(" %-19s", z); - sqlite3_free(z); - } - if( p->wsFlags & WHERE_SKIPSCAN ){ - sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); - }else{ - sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm); - } - sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); - if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ - int i; - for(i=0; inLTerm; i++){ - whereTermPrint(p->aLTerm[i], i); + sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); + if (p->nLTerm && (sqlite3WhereTrace & 0x100)!=0) { + int i; + for (i=0; inLTerm; i++) { + whereTermPrint(p->aLTerm[i], i); + } } - } } #endif @@ -1843,100 +1843,100 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){ ** to whereLoopClear harmlessly. */ static void whereLoopInit(WhereLoop *p){ - p->aLTerm = p->aLTermSpace; - p->nLTerm = 0; - p->nLSlot = ArraySize(p->aLTermSpace); - p->wsFlags = 0; + p->aLTerm = p->aLTermSpace; + p->nLTerm = 0; + p->nLSlot = ArraySize(p->aLTermSpace); + p->wsFlags = 0; } /* ** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact. */ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){ - if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){ - if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){ - sqlite3_free(p->u.vtab.idxStr); - p->u.vtab.needFree = 0; - p->u.vtab.idxStr = 0; - }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ - sqlite3DbFree(db, p->u.btree.pIndex->zColAff); - sqlite3DbFreeNN(db, p->u.btree.pIndex); - p->u.btree.pIndex = 0; + if (p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX)) { + if ((p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree) { + sqlite3_free(p->u.vtab.idxStr); + p->u.vtab.needFree = 0; + p->u.vtab.idxStr = 0; + } else if ((p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0) { + sqlite3DbFree(db, p->u.btree.pIndex->zColAff); + sqlite3DbFreeNN(db, p->u.btree.pIndex); + p->u.btree.pIndex = 0; + } } - } } /* ** Deallocate internal memory used by a WhereLoop object */ static void whereLoopClear(sqlite3 *db, WhereLoop *p){ - if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm); - whereLoopClearUnion(db, p); - whereLoopInit(p); + if (p->aLTerm!=p->aLTermSpace) sqlite3DbFreeNN(db, p->aLTerm); + whereLoopClearUnion(db, p); + whereLoopInit(p); } /* ** Increase the memory allocation for pLoop->aLTerm[] to be at least n. */ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ - WhereTerm **paNew; - if( p->nLSlot>=n ) return SQLITE_OK; - n = (n+7)&~7; - paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n); - if( paNew==0 ) return SQLITE_NOMEM_BKPT; - memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); - if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm); - p->aLTerm = paNew; - p->nLSlot = n; - return SQLITE_OK; + WhereTerm **paNew; + if (p->nLSlot>=n) return SQLITE_OK; + n = (n+7)&~7; + paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n); + if (paNew==0) return SQLITE_NOMEM_BKPT; + memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); + if (p->aLTerm!=p->aLTermSpace) sqlite3DbFreeNN(db, p->aLTerm); + p->aLTerm = paNew; + p->nLSlot = n; + return SQLITE_OK; } /* ** Transfer content from the second pLoop into the first. */ static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){ - whereLoopClearUnion(db, pTo); - if( whereLoopResize(db, pTo, pFrom->nLTerm) ){ - memset(&pTo->u, 0, sizeof(pTo->u)); - return SQLITE_NOMEM_BKPT; - } - memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); - memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); - if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){ - pFrom->u.vtab.needFree = 0; - }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){ - pFrom->u.btree.pIndex = 0; - } - return SQLITE_OK; + whereLoopClearUnion(db, pTo); + if (whereLoopResize(db, pTo, pFrom->nLTerm)) { + memset(&pTo->u, 0, sizeof(pTo->u)); + return SQLITE_NOMEM_BKPT; + } + memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); + memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); + if (pFrom->wsFlags & WHERE_VIRTUALTABLE) { + pFrom->u.vtab.needFree = 0; + } else if ((pFrom->wsFlags & WHERE_AUTO_INDEX)!=0) { + pFrom->u.btree.pIndex = 0; + } + return SQLITE_OK; } /* ** Delete a WhereLoop object */ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ - whereLoopClear(db, p); - sqlite3DbFreeNN(db, p); + whereLoopClear(db, p); + sqlite3DbFreeNN(db, p); } /* ** Free a WhereInfo structure */ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ - int i; - assert( pWInfo!=0 ); - for(i=0; inLevel; i++){ - WhereLevel *pLevel = &pWInfo->a[i]; - if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ - sqlite3DbFree(db, pLevel->u.in.aInLoop); + int i; + assert( pWInfo!=0 ); + for (i=0; inLevel; i++) { + WhereLevel *pLevel = &pWInfo->a[i]; + if (pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE)) { + sqlite3DbFree(db, pLevel->u.in.aInLoop); + } } - } - sqlite3WhereClauseClear(&pWInfo->sWC); - while( pWInfo->pLoops ){ - WhereLoop *p = pWInfo->pLoops; - pWInfo->pLoops = p->pNextLoop; - whereLoopDelete(db, p); - } - sqlite3DbFreeNN(db, pWInfo); + sqlite3WhereClauseClear(&pWInfo->sWC); + while (pWInfo->pLoops) { + WhereLoop *p = pWInfo->pLoops; + pWInfo->pLoops = p->pNextLoop; + whereLoopDelete(db, p); + } + sqlite3DbFreeNN(db, pWInfo); } /* @@ -1950,7 +1950,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ ** ** Conditions (2) and (3) mean that X is a "proper subset" of Y. ** If X is a proper subset of Y then Y is a better choice and ought -** to have a lower cost. This routine returns TRUE when that cost +** to have a lower cost. This routine returns TRUE when that cost ** relationship is inverted and needs to be adjusted. Constraint (4) ** was added because if X uses skip-scan less than Y it still might ** deserve a lower cost even if it is a proper subset of Y. Constraint (5) @@ -1958,30 +1958,30 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ ** than a non-covering index even if it is a proper subset. */ static int whereLoopCheaperProperSubset( - const WhereLoop *pX, /* First WhereLoop to compare */ - const WhereLoop *pY /* Compare against this WhereLoop */ -){ - int i, j; - if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){ - return 0; /* X is not a subset of Y */ - } - if( pY->nSkip > pX->nSkip ) return 0; - if( pX->rRun >= pY->rRun ){ - if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */ - if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */ - } - for(i=pX->nLTerm-1; i>=0; i--){ - if( pX->aLTerm[i]==0 ) continue; - for(j=pY->nLTerm-1; j>=0; j--){ - if( pY->aLTerm[j]==pX->aLTerm[i] ) break; + const WhereLoop *pX, /* First WhereLoop to compare */ + const WhereLoop *pY /* Compare against this WhereLoop */ + ){ + int i, j; + if (pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip) { + return 0; /* X is not a subset of Y */ } - if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */ - } - if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 - && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){ - return 0; /* Constraint (5) */ - } - return 1; /* All conditions meet */ + if (pY->nSkip > pX->nSkip) return 0; + if (pX->rRun >= pY->rRun) { + if (pX->rRun > pY->rRun) return 0; /* X costs more than Y */ + if (pX->nOut > pY->nOut) return 0; /* X costs more than Y */ + } + for (i=pX->nLTerm-1; i>=0; i--) { + if (pX->aLTerm[i]==0) continue; + for (j=pY->nLTerm-1; j>=0; j--) { + if (pY->aLTerm[j]==pX->aLTerm[i]) break; + } + if (j<0) return 0; /* X not a subset of Y since term X[i] not used by Y */ + } + if ((pX->wsFlags&WHERE_IDX_ONLY)!=0 + && (pY->wsFlags&WHERE_IDX_ONLY)==0) { + return 0; /* Constraint (5) */ + } + return 1; /* All conditions meet */ } /* @@ -1999,26 +1999,26 @@ static int whereLoopCheaperProperSubset( ** also used by Y. */ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ - if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; - for(; p; p=p->pNextLoop){ - if( p->iTab!=pTemplate->iTab ) continue; - if( (p->wsFlags & WHERE_INDEXED)==0 ) continue; - if( whereLoopCheaperProperSubset(p, pTemplate) ){ - /* Adjust pTemplate cost downward so that it is cheaper than its - ** subset p. */ - WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", - pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1)); - pTemplate->rRun = p->rRun; - pTemplate->nOut = p->nOut - 1; - }else if( whereLoopCheaperProperSubset(pTemplate, p) ){ - /* Adjust pTemplate cost upward so that it is costlier than p since - ** pTemplate is a proper subset of p */ - WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", - pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut+1)); - pTemplate->rRun = p->rRun; - pTemplate->nOut = p->nOut + 1; + if ((pTemplate->wsFlags & WHERE_INDEXED)==0) return; + for (; p; p=p->pNextLoop) { + if (p->iTab!=pTemplate->iTab) continue; + if ((p->wsFlags & WHERE_INDEXED)==0) continue; + if (whereLoopCheaperProperSubset(p, pTemplate)) { + /* Adjust pTemplate cost downward so that it is cheaper than its + ** subset p. */ + WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", + pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1)); + pTemplate->rRun = p->rRun; + pTemplate->nOut = p->nOut - 1; + } else if (whereLoopCheaperProperSubset(pTemplate, p)) { + /* Adjust pTemplate cost upward so that it is costlier than p since + ** pTemplate is a proper subset of p */ + WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n", + pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut+1)); + pTemplate->rRun = p->rRun; + pTemplate->nOut = p->nOut + 1; + } } - } } /* @@ -2036,67 +2036,67 @@ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ ** tail of the list. */ static WhereLoop **whereLoopFindLesser( - WhereLoop **ppPrev, - const WhereLoop *pTemplate -){ - WhereLoop *p; - for(p=(*ppPrev); p; ppPrev=&p->pNextLoop, p=*ppPrev){ - if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){ - /* If either the iTab or iSortIdx values for two WhereLoop are different - ** then those WhereLoops need to be considered separately. Neither is - ** a candidate to replace the other. */ - continue; - } - /* In the current implementation, the rSetup value is either zero - ** or the cost of building an automatic index (NlogN) and the NlogN - ** is the same for compatible WhereLoops. */ - assert( p->rSetup==0 || pTemplate->rSetup==0 - || p->rSetup==pTemplate->rSetup ); - - /* whereLoopAddBtree() always generates and inserts the automatic index - ** case first. Hence compatible candidate WhereLoops never have a larger - ** rSetup. Call this SETUP-INVARIANT */ - assert( p->rSetup>=pTemplate->rSetup ); - - /* Any loop using an appliation-defined index (or PRIMARY KEY or - ** UNIQUE constraint) with one or more == constraints is better - ** than an automatic index. Unless it is a skip-scan. */ - if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 - && (pTemplate->nSkip)==0 - && (pTemplate->wsFlags & WHERE_INDEXED)!=0 - && (pTemplate->wsFlags & WHERE_COLUMN_EQ)!=0 - && (p->prereq & pTemplate->prereq)==pTemplate->prereq + WhereLoop **ppPrev, + const WhereLoop *pTemplate ){ - break; - } + WhereLoop *p; + for (p=(*ppPrev); p; ppPrev=&p->pNextLoop, p=*ppPrev) { + if (p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx) { + /* If either the iTab or iSortIdx values for two WhereLoop are different + ** then those WhereLoops need to be considered separately. Neither is + ** a candidate to replace the other. */ + continue; + } + /* In the current implementation, the rSetup value is either zero + ** or the cost of building an automatic index (NlogN) and the NlogN + ** is the same for compatible WhereLoops. */ + assert( p->rSetup==0 || pTemplate->rSetup==0 + || p->rSetup==pTemplate->rSetup ); - /* If existing WhereLoop p is better than pTemplate, pTemplate can be - ** discarded. WhereLoop p is better if: - ** (1) p has no more dependencies than pTemplate, and - ** (2) p has an equal or lower cost than pTemplate - */ - if( (p->prereq & pTemplate->prereq)==p->prereq /* (1) */ - && p->rSetup<=pTemplate->rSetup /* (2a) */ - && p->rRun<=pTemplate->rRun /* (2b) */ - && p->nOut<=pTemplate->nOut /* (2c) */ - ){ - return 0; /* Discard pTemplate */ - } + /* whereLoopAddBtree() always generates and inserts the automatic index + ** case first. Hence compatible candidate WhereLoops never have a larger + ** rSetup. Call this SETUP-INVARIANT */ + assert( p->rSetup>=pTemplate->rSetup ); - /* If pTemplate is always better than p, then cause p to be overwritten - ** with pTemplate. pTemplate is better than p if: - ** (1) pTemplate has no more dependences than p, and - ** (2) pTemplate has an equal or lower cost than p. - */ - if( (p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */ - && p->rRun>=pTemplate->rRun /* (2a) */ - && p->nOut>=pTemplate->nOut /* (2b) */ - ){ - assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */ - break; /* Cause p to be overwritten by pTemplate */ + /* Any loop using an appliation-defined index (or PRIMARY KEY or + ** UNIQUE constraint) with one or more == constraints is better + ** than an automatic index. Unless it is a skip-scan. */ + if ((p->wsFlags & WHERE_AUTO_INDEX)!=0 + && (pTemplate->nSkip)==0 + && (pTemplate->wsFlags & WHERE_INDEXED)!=0 + && (pTemplate->wsFlags & WHERE_COLUMN_EQ)!=0 + && (p->prereq & pTemplate->prereq)==pTemplate->prereq + ) { + break; + } + + /* If existing WhereLoop p is better than pTemplate, pTemplate can be + ** discarded. WhereLoop p is better if: + ** (1) p has no more dependencies than pTemplate, and + ** (2) p has an equal or lower cost than pTemplate + */ + if ((p->prereq & pTemplate->prereq)==p->prereq /* (1) */ + && p->rSetup<=pTemplate->rSetup /* (2a) */ + && p->rRun<=pTemplate->rRun /* (2b) */ + && p->nOut<=pTemplate->nOut /* (2c) */ + ) { + return 0; /* Discard pTemplate */ + } + + /* If pTemplate is always better than p, then cause p to be overwritten + ** with pTemplate. pTemplate is better than p if: + ** (1) pTemplate has no more dependences than p, and + ** (2) pTemplate has an equal or lower cost than p. + */ + if ((p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */ + && p->rRun>=pTemplate->rRun /* (2a) */ + && p->nOut>=pTemplate->nOut /* (2b) */ + ) { + assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */ + break; /* Cause p to be overwritten by pTemplate */ + } } - } - return ppPrev; + return ppPrev; } /* @@ -2115,7 +2115,7 @@ static WhereLoop **whereLoopFindLesser( ** ** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we ** still might overwrite similar loops with the new template if the -** new template is better. Loops may be overwritten if the following +** new template is better. Loops may be overwritten if the following ** conditions are met: ** ** (1) They have the same iTab. @@ -2124,110 +2124,110 @@ static WhereLoop **whereLoopFindLesser( ** (4) The template has the same or lower cost than the current loop */ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ - WhereLoop **ppPrev, *p; - WhereInfo *pWInfo = pBuilder->pWInfo; - sqlite3 *db = pWInfo->pParse->db; - int rc; + WhereLoop **ppPrev, *p; + WhereInfo *pWInfo = pBuilder->pWInfo; + sqlite3 *db = pWInfo->pParse->db; + int rc; - /* Stop the search once we hit the query planner search limit */ - if( pBuilder->iPlanLimit==0 ){ - WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); - if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0; - return SQLITE_DONE; - } - pBuilder->iPlanLimit--; + /* Stop the search once we hit the query planner search limit */ + if (pBuilder->iPlanLimit==0) { + WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); + if (pBuilder->pOrSet) pBuilder->pOrSet->n = 0; + return SQLITE_DONE; + } + pBuilder->iPlanLimit--; - /* If pBuilder->pOrSet is defined, then only keep track of the costs - ** and prereqs. - */ - if( pBuilder->pOrSet!=0 ){ - if( pTemplate->nLTerm ){ + /* If pBuilder->pOrSet is defined, then only keep track of the costs + ** and prereqs. + */ + if (pBuilder->pOrSet!=0) { + if (pTemplate->nLTerm) { #if WHERETRACE_ENABLED - u16 n = pBuilder->pOrSet->n; - int x = + u16 n = pBuilder->pOrSet->n; + int x = #endif - whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, - pTemplate->nOut); + whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, + pTemplate->nOut); #if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); + if (sqlite3WhereTrace & 0x8) { + sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); + whereLoopPrint(pTemplate, pBuilder->pWC); + } +#endif + } + return SQLITE_OK; + } + + /* Look for an existing WhereLoop to replace with pTemplate + */ + whereLoopAdjustCost(pWInfo->pLoops, pTemplate); + ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate); + + if (ppPrev==0) { + /* There already exists a WhereLoop on the list that is better + ** than pTemplate, so just ignore pTemplate */ +#if WHERETRACE_ENABLED /* 0x8 */ + if (sqlite3WhereTrace & 0x8) { + sqlite3DebugPrintf(" skip: "); + whereLoopPrint(pTemplate, pBuilder->pWC); + } +#endif + return SQLITE_OK; + } else { + p = *ppPrev; + } + + /* If we reach this point it means that either p[] should be overwritten + ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new + ** WhereLoop and insert it. + */ +#if WHERETRACE_ENABLED /* 0x8 */ + if (sqlite3WhereTrace & 0x8) { + if (p!=0) { + sqlite3DebugPrintf("replace: "); + whereLoopPrint(p, pBuilder->pWC); + sqlite3DebugPrintf(" with: "); + } else { + sqlite3DebugPrintf(" add: "); + } whereLoopPrint(pTemplate, pBuilder->pWC); - } -#endif } - return SQLITE_OK; - } - - /* Look for an existing WhereLoop to replace with pTemplate - */ - whereLoopAdjustCost(pWInfo->pLoops, pTemplate); - ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate); - - if( ppPrev==0 ){ - /* There already exists a WhereLoop on the list that is better - ** than pTemplate, so just ignore pTemplate */ +#endif + if (p==0) { + /* Allocate a new WhereLoop to add to the end of the list */ + *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); + if (p==0) return SQLITE_NOMEM_BKPT; + whereLoopInit(p); + p->pNextLoop = 0; + } else { + /* We will be overwriting WhereLoop p[]. But before we do, first + ** go through the rest of the list and delete any other entries besides + ** p[] that are also supplated by pTemplate */ + WhereLoop **ppTail = &p->pNextLoop; + WhereLoop *pToDel; + while (*ppTail) { + ppTail = whereLoopFindLesser(ppTail, pTemplate); + if (ppTail==0) break; + pToDel = *ppTail; + if (pToDel==0) break; + *ppTail = pToDel->pNextLoop; #if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(" skip: "); - whereLoopPrint(pTemplate, pBuilder->pWC); - } + if (sqlite3WhereTrace & 0x8) { + sqlite3DebugPrintf(" delete: "); + whereLoopPrint(pToDel, pBuilder->pWC); + } #endif - return SQLITE_OK; - }else{ - p = *ppPrev; - } - - /* If we reach this point it means that either p[] should be overwritten - ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new - ** WhereLoop and insert it. - */ -#if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - if( p!=0 ){ - sqlite3DebugPrintf("replace: "); - whereLoopPrint(p, pBuilder->pWC); - sqlite3DebugPrintf(" with: "); - }else{ - sqlite3DebugPrintf(" add: "); + whereLoopDelete(db, pToDel); + } } - whereLoopPrint(pTemplate, pBuilder->pWC); - } -#endif - if( p==0 ){ - /* Allocate a new WhereLoop to add to the end of the list */ - *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); - if( p==0 ) return SQLITE_NOMEM_BKPT; - whereLoopInit(p); - p->pNextLoop = 0; - }else{ - /* We will be overwriting WhereLoop p[]. But before we do, first - ** go through the rest of the list and delete any other entries besides - ** p[] that are also supplated by pTemplate */ - WhereLoop **ppTail = &p->pNextLoop; - WhereLoop *pToDel; - while( *ppTail ){ - ppTail = whereLoopFindLesser(ppTail, pTemplate); - if( ppTail==0 ) break; - pToDel = *ppTail; - if( pToDel==0 ) break; - *ppTail = pToDel->pNextLoop; -#if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(" delete: "); - whereLoopPrint(pToDel, pBuilder->pWC); - } -#endif - whereLoopDelete(db, pToDel); + rc = whereLoopXfer(db, p, pTemplate); + if ((p->wsFlags & WHERE_VIRTUALTABLE)==0) { + Index *pIndex = p->u.btree.pIndex; + if (pIndex && pIndex->idxType==SQLITE_IDXTYPE_IPK) { + p->u.btree.pIndex = 0; + } } - } - rc = whereLoopXfer(db, p, pTemplate); - if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ - Index *pIndex = p->u.btree.pIndex; - if( pIndex && pIndex->idxType==SQLITE_IDXTYPE_IPK ){ - p->u.btree.pIndex = 0; - } - } - return rc; + return rc; } /* @@ -2260,53 +2260,53 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ ** at 1/2 instead of 1/4. */ static void whereLoopOutputAdjust( - WhereClause *pWC, /* The WHERE clause */ - WhereLoop *pLoop, /* The loop to adjust downward */ - LogEst nRow /* Number of rows in the entire table */ -){ - WhereTerm *pTerm, *pX; - Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); - int i, j, k; - LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */ + WhereClause *pWC, /* The WHERE clause */ + WhereLoop *pLoop, /* The loop to adjust downward */ + LogEst nRow /* Number of rows in the entire table */ + ){ + WhereTerm *pTerm, *pX; + Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); + int i, j, k; + LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */ - assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); - for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){ - assert( pTerm!=0 ); - if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break; - if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; - if( (pTerm->prereqAll & notAllowed)!=0 ) continue; - for(j=pLoop->nLTerm-1; j>=0; j--){ - pX = pLoop->aLTerm[j]; - if( pX==0 ) continue; - if( pX==pTerm ) break; - if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; - } - if( j<0 ){ - if( pTerm->truthProb<=0 ){ - /* If a truth probability is specified using the likelihood() hints, - ** then use the probability provided by the application. */ - pLoop->nOut += pTerm->truthProb; - }else{ - /* In the absence of explicit truth probabilities, use heuristics to - ** guess a reasonable truth probability. */ - pLoop->nOut--; - if( pTerm->eOperator&(WO_EQ|WO_IS) ){ - Expr *pRight = pTerm->pExpr->pRight; - testcase( pTerm->pExpr->op==TK_IS ); - if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){ - k = 10; - }else{ - k = 20; - } - if( iReducewsFlags & WHERE_AUTO_INDEX)==0 ); + for (i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++) { + assert( pTerm!=0 ); + if ((pTerm->wtFlags & TERM_VIRTUAL)!=0) break; + if ((pTerm->prereqAll & pLoop->maskSelf)==0) continue; + if ((pTerm->prereqAll & notAllowed)!=0) continue; + for (j=pLoop->nLTerm-1; j>=0; j--) { + pX = pLoop->aLTerm[j]; + if (pX==0) continue; + if (pX==pTerm) break; + if (pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm) break; + } + if (j<0) { + if (pTerm->truthProb<=0) { + /* If a truth probability is specified using the likelihood() hints, + ** then use the probability provided by the application. */ + pLoop->nOut += pTerm->truthProb; + } else { + /* In the absence of explicit truth probabilities, use heuristics to + ** guess a reasonable truth probability. */ + pLoop->nOut--; + if (pTerm->eOperator&(WO_EQ|WO_IS)) { + Expr *pRight = pTerm->pExpr->pRight; + testcase( pTerm->pExpr->op==TK_IS ); + if (sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1) { + k = 10; + } else { + k = 20; + } + if (iReducenOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce; + if (pLoop->nOut > nRow-iReduce) pLoop->nOut = nRow - iReduce; } -/* +/* ** Term pTerm is a vector range comparison operation. The first comparison ** in the vector can be optimized using column nEq of the index. This ** function returns the total number of vector elements that can be used @@ -2324,52 +2324,52 @@ static void whereLoopOutputAdjust( ** this case is 3. */ static int whereRangeVectorLen( - Parse *pParse, /* Parsing context */ - int iCur, /* Cursor open on pIdx */ - Index *pIdx, /* The index to be used for a inequality constraint */ - int nEq, /* Number of prior equality constraints on same index */ - WhereTerm *pTerm /* The vector inequality constraint */ -){ - int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft); - int i; - - nCmp = MIN(nCmp, (pIdx->nColumn - nEq)); - for(i=1; ipExpr->pLeft->x.pList->a[i].pExpr; - Expr *pRhs = pTerm->pExpr->pRight; - if( pRhs->flags & EP_xIsSelect ){ - pRhs = pRhs->x.pSelect->pEList->a[i].pExpr; - }else{ - pRhs = pRhs->x.pList->a[i].pExpr; - } - - /* Check that the LHS of the comparison is a column reference to - ** the right column of the right source table. And that the sort - ** order of the index column is the same as the sort order of the - ** leftmost index column. */ - if( pLhs->op!=TK_COLUMN - || pLhs->iTable!=iCur - || pLhs->iColumn!=pIdx->aiColumn[i+nEq] - || pIdx->aSortOrder[i+nEq]!=pIdx->aSortOrder[nEq] + Parse *pParse, /* Parsing context */ + int iCur, /* Cursor open on pIdx */ + Index *pIdx, /* The index to be used for a inequality constraint */ + int nEq, /* Number of prior equality constraints on same index */ + WhereTerm *pTerm /* The vector inequality constraint */ ){ - break; + int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft); + int i; + + nCmp = MIN(nCmp, (pIdx->nColumn - nEq)); + for (i=1; ipExpr->pLeft->x.pList->a[i].pExpr; + Expr *pRhs = pTerm->pExpr->pRight; + if (pRhs->flags & EP_xIsSelect) { + pRhs = pRhs->x.pSelect->pEList->a[i].pExpr; + } else { + pRhs = pRhs->x.pList->a[i].pExpr; + } + + /* Check that the LHS of the comparison is a column reference to + ** the right column of the right source table. And that the sort + ** order of the index column is the same as the sort order of the + ** leftmost index column. */ + if (pLhs->op!=TK_COLUMN + || pLhs->iTable!=iCur + || pLhs->iColumn!=pIdx->aiColumn[i+nEq] + || pIdx->aSortOrder[i+nEq]!=pIdx->aSortOrder[nEq] + ) { + break; + } + + testcase( pLhs->iColumn==XN_ROWID ); + aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs)); + idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn); + if (aff!=idxaff) break; + + pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); + if (pColl==0) break; + if (sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq])) break; } - - testcase( pLhs->iColumn==XN_ROWID ); - aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs)); - idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn); - if( aff!=idxaff ) break; - - pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); - if( pColl==0 ) break; - if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break; - } - return i; + return i; } /* @@ -2383,369 +2383,369 @@ static int whereRangeVectorLen( #endif /* -** We have so far matched pBuilder->pNew->u.btree.nEq terms of the +** We have so far matched pBuilder->pNew->u.btree.nEq terms of the ** index pIndex. Try to match one more. ** -** When this function is called, pBuilder->pNew->nOut contains the -** number of rows expected to be visited by filtering using the nEq -** terms only. If it is modified, this value is restored before this +** When this function is called, pBuilder->pNew->nOut contains the +** number of rows expected to be visited by filtering using the nEq +** terms only. If it is modified, this value is restored before this ** function returns. ** -** If pProbe->idxType==SQLITE_IDXTYPE_IPK, that means pIndex is +** If pProbe->idxType==SQLITE_IDXTYPE_IPK, that means pIndex is ** a fake index used for the INTEGER PRIMARY KEY. */ static int whereLoopAddBtreeIndex( - WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ - struct SrcList_item *pSrc, /* FROM clause term being analyzed */ - Index *pProbe, /* An index on pSrc */ - LogEst nInMul /* log(Number of iterations due to IN) */ -){ - WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */ - Parse *pParse = pWInfo->pParse; /* Parsing context */ - sqlite3 *db = pParse->db; /* Database connection malloc context */ - WhereLoop *pNew; /* Template WhereLoop under construction */ - WhereTerm *pTerm; /* A WhereTerm under consideration */ - int opMask; /* Valid operators for constraints */ - WhereScan scan; /* Iterator for WHERE terms */ - Bitmask saved_prereq; /* Original value of pNew->prereq */ - u16 saved_nLTerm; /* Original value of pNew->nLTerm */ - u16 saved_nEq; /* Original value of pNew->u.btree.nEq */ - u16 saved_nBtm; /* Original value of pNew->u.btree.nBtm */ - u16 saved_nTop; /* Original value of pNew->u.btree.nTop */ - u16 saved_nSkip; /* Original value of pNew->nSkip */ - u32 saved_wsFlags; /* Original value of pNew->wsFlags */ - LogEst saved_nOut; /* Original value of pNew->nOut */ - int rc = SQLITE_OK; /* Return code */ - LogEst rSize; /* Number of rows in the table */ - LogEst rLogSize; /* Logarithm of table size */ - WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ + WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ + struct SrcList_item *pSrc, /* FROM clause term being analyzed */ + Index *pProbe, /* An index on pSrc */ + LogEst nInMul /* log(Number of iterations due to IN) */ + ){ + WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */ + Parse *pParse = pWInfo->pParse; /* Parsing context */ + sqlite3 *db = pParse->db; /* Database connection malloc context */ + WhereLoop *pNew; /* Template WhereLoop under construction */ + WhereTerm *pTerm; /* A WhereTerm under consideration */ + int opMask; /* Valid operators for constraints */ + WhereScan scan; /* Iterator for WHERE terms */ + Bitmask saved_prereq; /* Original value of pNew->prereq */ + u16 saved_nLTerm; /* Original value of pNew->nLTerm */ + u16 saved_nEq; /* Original value of pNew->u.btree.nEq */ + u16 saved_nBtm; /* Original value of pNew->u.btree.nBtm */ + u16 saved_nTop; /* Original value of pNew->u.btree.nTop */ + u16 saved_nSkip; /* Original value of pNew->nSkip */ + u32 saved_wsFlags; /* Original value of pNew->wsFlags */ + LogEst saved_nOut; /* Original value of pNew->nOut */ + int rc = SQLITE_OK; /* Return code */ + LogEst rSize; /* Number of rows in the table */ + LogEst rLogSize; /* Logarithm of table size */ + WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ - pNew = pBuilder->pNew; - if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; - WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n", - pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq)); + pNew = pBuilder->pNew; + if (db->mallocFailed) return SQLITE_NOMEM_BKPT; + WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n", + pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq)); - assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); - assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); - if( pNew->wsFlags & WHERE_BTM_LIMIT ){ - opMask = WO_LT|WO_LE; - }else{ - assert( pNew->u.btree.nBtm==0 ); - opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; - } - if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); + assert((pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); + assert((pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); + if (pNew->wsFlags & WHERE_BTM_LIMIT) { + opMask = WO_LT|WO_LE; + } else { + assert( pNew->u.btree.nBtm==0 ); + opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; + } + if (pProbe->bUnordered) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); - assert( pNew->u.btree.nEqnColumn ); + assert( pNew->u.btree.nEqnColumn ); - saved_nEq = pNew->u.btree.nEq; - saved_nBtm = pNew->u.btree.nBtm; - saved_nTop = pNew->u.btree.nTop; - saved_nSkip = pNew->nSkip; - saved_nLTerm = pNew->nLTerm; - saved_wsFlags = pNew->wsFlags; - saved_prereq = pNew->prereq; - saved_nOut = pNew->nOut; - pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, saved_nEq, - opMask, pProbe); - pNew->rSetup = 0; - rSize = pProbe->aiRowLogEst[0]; - rLogSize = estLog(rSize); - for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ - u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */ - LogEst rCostIdx; - LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */ - int nIn = 0; + saved_nEq = pNew->u.btree.nEq; + saved_nBtm = pNew->u.btree.nBtm; + saved_nTop = pNew->u.btree.nTop; + saved_nSkip = pNew->nSkip; + saved_nLTerm = pNew->nLTerm; + saved_wsFlags = pNew->wsFlags; + saved_prereq = pNew->prereq; + saved_nOut = pNew->nOut; + pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, saved_nEq, + opMask, pProbe); + pNew->rSetup = 0; + rSize = pProbe->aiRowLogEst[0]; + rLogSize = estLog(rSize); + for (; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)) { + u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */ + LogEst rCostIdx; + LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */ + int nIn = 0; #ifdef SQLITE_ENABLE_STAT4 - int nRecValid = pBuilder->nRecValid; + int nRecValid = pBuilder->nRecValid; #endif - if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) - && indexColumnNotNull(pProbe, saved_nEq) - ){ - continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */ - } - if( pTerm->prereqRight & pNew->maskSelf ) continue; + if ((eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) + && indexColumnNotNull(pProbe, saved_nEq) + ) { + continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */ + } + if (pTerm->prereqRight & pNew->maskSelf) continue; - /* Do not allow the upper bound of a LIKE optimization range constraint - ** to mix with a lower range bound from some other source */ - if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; + /* Do not allow the upper bound of a LIKE optimization range constraint + ** to mix with a lower range bound from some other source */ + if (pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT) continue; - /* Do not allow constraints from the WHERE clause to be used by the - ** right table of a LEFT JOIN. Only constraints in the ON clause are - ** allowed */ - if( (pSrc->fg.jointype & JT_LEFT)!=0 - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - ){ - continue; - } + /* Do not allow constraints from the WHERE clause to be used by the + ** right table of a LEFT JOIN. Only constraints in the ON clause are + ** allowed */ + if ((pSrc->fg.jointype & JT_LEFT)!=0 + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + ) { + continue; + } - if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ - pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE; - }else{ - pBuilder->bldFlags |= SQLITE_BLDF_INDEXED; + if (IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1) { + pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE; + } else { + pBuilder->bldFlags |= SQLITE_BLDF_INDEXED; + } + pNew->wsFlags = saved_wsFlags; + pNew->u.btree.nEq = saved_nEq; + pNew->u.btree.nBtm = saved_nBtm; + pNew->u.btree.nTop = saved_nTop; + pNew->nLTerm = saved_nLTerm; + if (whereLoopResize(db, pNew, pNew->nLTerm+1)) break; /* OOM */ + pNew->aLTerm[pNew->nLTerm++] = pTerm; + pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; + + assert( nInMul==0 + || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0 + || (pNew->wsFlags & WHERE_COLUMN_IN)!=0 + || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 + ); + + if (eOp & WO_IN) { + Expr *pExpr = pTerm->pExpr; + if (ExprHasProperty(pExpr, EP_xIsSelect)) { + /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ + int i; + nIn = 46; assert( 46==sqlite3LogEst(25)); + + /* The expression may actually be of the form (x, y) IN (SELECT...). + ** In this case there is a separate term for each of (x) and (y). + ** However, the nIn multiplier should only be applied once, not once + ** for each such term. The following loop checks that pTerm is the + ** first such term in use, and sets nIn back to 0 if it is not. */ + for (i=0; inLTerm-1; i++) { + if (pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr) nIn = 0; + } + } else if (ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr)) { + /* "x IN (value, value, ...)" */ + nIn = sqlite3LogEst(pExpr->x.pList->nExpr); + assert( nIn>0 ); /* RHS always has 2 or more terms... The parser + ** changes "x IN (?)" into "x=?". */ + } + if (pProbe->hasStat1) { + LogEst M, logK, safetyMargin; + /* Let: + ** N = the total number of rows in the table + ** K = the number of entries on the RHS of the IN operator + ** M = the number of rows in the table that match terms to the + ** to the left in the same index. If the IN operator is on + ** the left-most index column, M==N. + ** + ** Given the definitions above, it is better to omit the IN operator + ** from the index lookup and instead do a scan of the M elements, + ** testing each scanned row against the IN operator separately, if: + ** + ** M*log(K) < K*log(N) + ** + ** Our estimates for M, K, and N might be inaccurate, so we build in + ** a safety margin of 2 (LogEst: 10) that favors using the IN operator + ** with the index, as using an index has better worst-case behavior. + ** If we do not have real sqlite_stat1 data, always prefer to use + ** the index. + */ + M = pProbe->aiRowLogEst[saved_nEq]; + logK = estLog(nIn); + safetyMargin = 10; /* TUNING: extra weight for indexed IN */ + if (M + logK + safetyMargin < nIn + rLogSize) { + WHERETRACE(0x40, + ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n", + saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); + continue; + } else { + WHERETRACE(0x40, + ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n", + saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); + } + } + pNew->wsFlags |= WHERE_COLUMN_IN; + } else if (eOp & (WO_EQ|WO_IS)) { + int iCol = pProbe->aiColumn[saved_nEq]; + pNew->wsFlags |= WHERE_COLUMN_EQ; + assert( saved_nEq==pNew->u.btree.nEq ); + if (iCol==XN_ROWID + || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) + ) { + if (iCol==XN_ROWID || pProbe->uniqNotNull + || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) + ) { + pNew->wsFlags |= WHERE_ONEROW; + } else { + pNew->wsFlags |= WHERE_UNQ_WANTED; + } + } + } else if (eOp & WO_ISNULL) { + pNew->wsFlags |= WHERE_COLUMN_NULL; + } else if (eOp & (WO_GT|WO_GE)) { + testcase( eOp & WO_GT ); + testcase( eOp & WO_GE ); + pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; + pNew->u.btree.nBtm = whereRangeVectorLen( + pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm + ); + pBtm = pTerm; + pTop = 0; + if (pTerm->wtFlags & TERM_LIKEOPT) { + /* Range contraints that come from the LIKE optimization are + ** always used in pairs. */ + pTop = &pTerm[1]; + assert((pTop-(pTerm->pWC->a))pWC->nTerm ); + assert( pTop->wtFlags & TERM_LIKEOPT ); + assert( pTop->eOperator==WO_LT ); + if (whereLoopResize(db, pNew, pNew->nLTerm+1)) break; /* OOM */ + pNew->aLTerm[pNew->nLTerm++] = pTop; + pNew->wsFlags |= WHERE_TOP_LIMIT; + pNew->u.btree.nTop = 1; + } + } else { + assert( eOp & (WO_LT|WO_LE)); + testcase( eOp & WO_LT ); + testcase( eOp & WO_LE ); + pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; + pNew->u.btree.nTop = whereRangeVectorLen( + pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm + ); + pTop = pTerm; + pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? + pNew->aLTerm[pNew->nLTerm-2] : 0; + } + + /* At this point pNew->nOut is set to the number of rows expected to + ** be visited by the index scan before considering term pTerm, or the + ** values of nIn and nInMul. In other words, assuming that all + ** "x IN(...)" terms are replaced with "x = ?". This block updates + ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */ + assert( pNew->nOut==saved_nOut ); + if (pNew->wsFlags & WHERE_COLUMN_RANGE) { + /* Adjust nOut using stat4 data. Or, if there is no stat4 + ** data, using some other estimate. */ + whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); + } else { + int nEq = ++pNew->u.btree.nEq; + assert( eOp & (WO_ISNULL|WO_EQ|WO_IN|WO_IS)); + + assert( pNew->nOut==saved_nOut ); + if (pTerm->truthProb<=0 && pProbe->aiColumn[saved_nEq]>=0) { + assert((eOp & WO_IN) || nIn==0 ); + testcase( eOp & WO_IN ); + pNew->nOut += pTerm->truthProb; + pNew->nOut -= nIn; + } else { +#ifdef SQLITE_ENABLE_STAT4 + tRowcnt nOut = 0; + if (nInMul==0 + && pProbe->nSample + && pNew->u.btree.nEq<=pProbe->nSampleCol + && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) + && OptimizationEnabled(db, SQLITE_Stat4) + ) { + Expr *pExpr = pTerm->pExpr; + if ((eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0) { + testcase( eOp & WO_EQ ); + testcase( eOp & WO_IS ); + testcase( eOp & WO_ISNULL ); + rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); + } else { + rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); + } + if (rc==SQLITE_NOTFOUND) rc = SQLITE_OK; + if (rc!=SQLITE_OK) break; /* Jump out of the pTerm loop */ + if (nOut) { + pNew->nOut = sqlite3LogEst(nOut); + if (pNew->nOut>saved_nOut) pNew->nOut = saved_nOut; + pNew->nOut -= nIn; + } + } + if (nOut==0) +#endif + { + pNew->nOut += (pProbe->aiRowLogEst[nEq] - pProbe->aiRowLogEst[nEq-1]); + if (eOp & WO_ISNULL) { + /* TUNING: If there is no likelihood() value, assume that a + ** "col IS NULL" expression matches twice as many rows + ** as (col=?). */ + pNew->nOut += 10; + } + } + } + } + + /* Set rCostIdx to the cost of visiting selected rows in index. Add + ** it to pNew->rRun, which is currently set to the cost of the index + ** seek only. Then, if this is a non-covering index, add the cost of + ** visiting the rows in the main table. */ + rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow; + pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx); + if ((pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0) { + pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16); + } + ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult); + + nOutUnadjusted = pNew->nOut; + pNew->rRun += nInMul + nIn; + pNew->nOut += nInMul + nIn; + whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize); + rc = whereLoopInsert(pBuilder, pNew); + + if (pNew->wsFlags & WHERE_COLUMN_RANGE) { + pNew->nOut = saved_nOut; + } else { + pNew->nOut = nOutUnadjusted; + } + + if ((pNew->wsFlags & WHERE_TOP_LIMIT)==0 + && pNew->u.btree.nEqnColumn + ) { + whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); + } + pNew->nOut = saved_nOut; +#ifdef SQLITE_ENABLE_STAT4 + pBuilder->nRecValid = nRecValid; +#endif } - pNew->wsFlags = saved_wsFlags; + pNew->prereq = saved_prereq; pNew->u.btree.nEq = saved_nEq; pNew->u.btree.nBtm = saved_nBtm; pNew->u.btree.nTop = saved_nTop; - pNew->nLTerm = saved_nLTerm; - if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ - pNew->aLTerm[pNew->nLTerm++] = pTerm; - pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; - - assert( nInMul==0 - || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0 - || (pNew->wsFlags & WHERE_COLUMN_IN)!=0 - || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 - ); - - if( eOp & WO_IN ){ - Expr *pExpr = pTerm->pExpr; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ - int i; - nIn = 46; assert( 46==sqlite3LogEst(25) ); - - /* The expression may actually be of the form (x, y) IN (SELECT...). - ** In this case there is a separate term for each of (x) and (y). - ** However, the nIn multiplier should only be applied once, not once - ** for each such term. The following loop checks that pTerm is the - ** first such term in use, and sets nIn back to 0 if it is not. */ - for(i=0; inLTerm-1; i++){ - if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0; - } - }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ - /* "x IN (value, value, ...)" */ - nIn = sqlite3LogEst(pExpr->x.pList->nExpr); - assert( nIn>0 ); /* RHS always has 2 or more terms... The parser - ** changes "x IN (?)" into "x=?". */ - } - if( pProbe->hasStat1 ){ - LogEst M, logK, safetyMargin; - /* Let: - ** N = the total number of rows in the table - ** K = the number of entries on the RHS of the IN operator - ** M = the number of rows in the table that match terms to the - ** to the left in the same index. If the IN operator is on - ** the left-most index column, M==N. - ** - ** Given the definitions above, it is better to omit the IN operator - ** from the index lookup and instead do a scan of the M elements, - ** testing each scanned row against the IN operator separately, if: - ** - ** M*log(K) < K*log(N) - ** - ** Our estimates for M, K, and N might be inaccurate, so we build in - ** a safety margin of 2 (LogEst: 10) that favors using the IN operator - ** with the index, as using an index has better worst-case behavior. - ** If we do not have real sqlite_stat1 data, always prefer to use - ** the index. - */ - M = pProbe->aiRowLogEst[saved_nEq]; - logK = estLog(nIn); - safetyMargin = 10; /* TUNING: extra weight for indexed IN */ - if( M + logK + safetyMargin < nIn + rLogSize ){ - WHERETRACE(0x40, - ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n", - saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); - continue; - }else{ - WHERETRACE(0x40, - ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n", - saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); - } - } - pNew->wsFlags |= WHERE_COLUMN_IN; - }else if( eOp & (WO_EQ|WO_IS) ){ - int iCol = pProbe->aiColumn[saved_nEq]; - pNew->wsFlags |= WHERE_COLUMN_EQ; - assert( saved_nEq==pNew->u.btree.nEq ); - if( iCol==XN_ROWID - || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) - ){ - if( iCol==XN_ROWID || pProbe->uniqNotNull - || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) - ){ - pNew->wsFlags |= WHERE_ONEROW; - }else{ - pNew->wsFlags |= WHERE_UNQ_WANTED; - } - } - }else if( eOp & WO_ISNULL ){ - pNew->wsFlags |= WHERE_COLUMN_NULL; - }else if( eOp & (WO_GT|WO_GE) ){ - testcase( eOp & WO_GT ); - testcase( eOp & WO_GE ); - pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; - pNew->u.btree.nBtm = whereRangeVectorLen( - pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm - ); - pBtm = pTerm; - pTop = 0; - if( pTerm->wtFlags & TERM_LIKEOPT ){ - /* Range contraints that come from the LIKE optimization are - ** always used in pairs. */ - pTop = &pTerm[1]; - assert( (pTop-(pTerm->pWC->a))pWC->nTerm ); - assert( pTop->wtFlags & TERM_LIKEOPT ); - assert( pTop->eOperator==WO_LT ); - if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ - pNew->aLTerm[pNew->nLTerm++] = pTop; - pNew->wsFlags |= WHERE_TOP_LIMIT; - pNew->u.btree.nTop = 1; - } - }else{ - assert( eOp & (WO_LT|WO_LE) ); - testcase( eOp & WO_LT ); - testcase( eOp & WO_LE ); - pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; - pNew->u.btree.nTop = whereRangeVectorLen( - pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm - ); - pTop = pTerm; - pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? - pNew->aLTerm[pNew->nLTerm-2] : 0; - } - - /* At this point pNew->nOut is set to the number of rows expected to - ** be visited by the index scan before considering term pTerm, or the - ** values of nIn and nInMul. In other words, assuming that all - ** "x IN(...)" terms are replaced with "x = ?". This block updates - ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */ - assert( pNew->nOut==saved_nOut ); - if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ - /* Adjust nOut using stat4 data. Or, if there is no stat4 - ** data, using some other estimate. */ - whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); - }else{ - int nEq = ++pNew->u.btree.nEq; - assert( eOp & (WO_ISNULL|WO_EQ|WO_IN|WO_IS) ); - - assert( pNew->nOut==saved_nOut ); - if( pTerm->truthProb<=0 && pProbe->aiColumn[saved_nEq]>=0 ){ - assert( (eOp & WO_IN) || nIn==0 ); - testcase( eOp & WO_IN ); - pNew->nOut += pTerm->truthProb; - pNew->nOut -= nIn; - }else{ -#ifdef SQLITE_ENABLE_STAT4 - tRowcnt nOut = 0; - if( nInMul==0 - && pProbe->nSample - && pNew->u.btree.nEq<=pProbe->nSampleCol - && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) - && OptimizationEnabled(db, SQLITE_Stat4) - ){ - Expr *pExpr = pTerm->pExpr; - if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ - testcase( eOp & WO_EQ ); - testcase( eOp & WO_IS ); - testcase( eOp & WO_ISNULL ); - rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); - }else{ - rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); - } - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; - if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */ - if( nOut ){ - pNew->nOut = sqlite3LogEst(nOut); - if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut; - pNew->nOut -= nIn; - } - } - if( nOut==0 ) -#endif - { - pNew->nOut += (pProbe->aiRowLogEst[nEq] - pProbe->aiRowLogEst[nEq-1]); - if( eOp & WO_ISNULL ){ - /* TUNING: If there is no likelihood() value, assume that a - ** "col IS NULL" expression matches twice as many rows - ** as (col=?). */ - pNew->nOut += 10; - } - } - } - } - - /* Set rCostIdx to the cost of visiting selected rows in index. Add - ** it to pNew->rRun, which is currently set to the cost of the index - ** seek only. Then, if this is a non-covering index, add the cost of - ** visiting the rows in the main table. */ - rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow; - pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx); - if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ - pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16); - } - ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult); - - nOutUnadjusted = pNew->nOut; - pNew->rRun += nInMul + nIn; - pNew->nOut += nInMul + nIn; - whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize); - rc = whereLoopInsert(pBuilder, pNew); - - if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ - pNew->nOut = saved_nOut; - }else{ - pNew->nOut = nOutUnadjusted; - } - - if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 - && pNew->u.btree.nEqnColumn - ){ - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); - } - pNew->nOut = saved_nOut; -#ifdef SQLITE_ENABLE_STAT4 - pBuilder->nRecValid = nRecValid; -#endif - } - pNew->prereq = saved_prereq; - pNew->u.btree.nEq = saved_nEq; - pNew->u.btree.nBtm = saved_nBtm; - pNew->u.btree.nTop = saved_nTop; - pNew->nSkip = saved_nSkip; - pNew->wsFlags = saved_wsFlags; - pNew->nOut = saved_nOut; - pNew->nLTerm = saved_nLTerm; - - /* Consider using a skip-scan if there are no WHERE clause constraints - ** available for the left-most terms of the index, and if the average - ** number of repeats in the left-most terms is at least 18. - ** - ** The magic number 18 is selected on the basis that scanning 17 rows - ** is almost always quicker than an index seek (even though if the index - ** contains fewer than 2^17 rows we assume otherwise in other parts of - ** the code). And, even if it is not, it should not be too much slower. - ** On the other hand, the extra seeks could end up being significantly - ** more expensive. */ - assert( 42==sqlite3LogEst(18) ); - if( saved_nEq==saved_nSkip - && saved_nEq+1nKeyCol - && pProbe->noSkipScan==0 - && OptimizationEnabled(db, SQLITE_SkipScan) - && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ - && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK - ){ - LogEst nIter; - pNew->u.btree.nEq++; - pNew->nSkip++; - pNew->aLTerm[pNew->nLTerm++] = 0; - pNew->wsFlags |= WHERE_SKIPSCAN; - nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1]; - pNew->nOut -= nIter; - /* TUNING: Because uncertainties in the estimates for skip-scan queries, - ** add a 1.375 fudge factor to make skip-scan slightly less likely. */ - nIter += 5; - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); - pNew->nOut = saved_nOut; - pNew->u.btree.nEq = saved_nEq; pNew->nSkip = saved_nSkip; pNew->wsFlags = saved_wsFlags; - } + pNew->nOut = saved_nOut; + pNew->nLTerm = saved_nLTerm; - WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n", - pProbe->pTable->zName, pProbe->zName, saved_nEq, rc)); - return rc; + /* Consider using a skip-scan if there are no WHERE clause constraints + ** available for the left-most terms of the index, and if the average + ** number of repeats in the left-most terms is at least 18. + ** + ** The magic number 18 is selected on the basis that scanning 17 rows + ** is almost always quicker than an index seek (even though if the index + ** contains fewer than 2^17 rows we assume otherwise in other parts of + ** the code). And, even if it is not, it should not be too much slower. + ** On the other hand, the extra seeks could end up being significantly + ** more expensive. */ + assert( 42==sqlite3LogEst(18)); + if (saved_nEq==saved_nSkip + && saved_nEq+1nKeyCol + && pProbe->noSkipScan==0 + && OptimizationEnabled(db, SQLITE_SkipScan) + && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ + && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK + ) { + LogEst nIter; + pNew->u.btree.nEq++; + pNew->nSkip++; + pNew->aLTerm[pNew->nLTerm++] = 0; + pNew->wsFlags |= WHERE_SKIPSCAN; + nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1]; + pNew->nOut -= nIter; + /* TUNING: Because uncertainties in the estimates for skip-scan queries, + ** add a 1.375 fudge factor to make skip-scan slightly less likely. */ + nIter += 5; + whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); + pNew->nOut = saved_nOut; + pNew->u.btree.nEq = saved_nEq; + pNew->nSkip = saved_nSkip; + pNew->wsFlags = saved_wsFlags; + } + + WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n", + pProbe->pTable->zName, pProbe->zName, saved_nEq, rc)); + return rc; } /* @@ -2757,56 +2757,56 @@ static int whereLoopAddBtreeIndex( ** ORDER BY clause. */ static int indexMightHelpWithOrderBy( - WhereLoopBuilder *pBuilder, - Index *pIndex, - int iCursor -){ - ExprList *pOB; - ExprList *aColExpr; - int ii, jj; + WhereLoopBuilder *pBuilder, + Index *pIndex, + int iCursor + ){ + ExprList *pOB; + ExprList *aColExpr; + int ii, jj; - if( pIndex->bUnordered ) return 0; - if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; - for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr); - if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){ - if( pExpr->iColumn<0 ) return 1; - for(jj=0; jjnKeyCol; jj++){ - if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; - } - }else if( (aColExpr = pIndex->aColExpr)!=0 ){ - for(jj=0; jjnKeyCol; jj++){ - if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; - if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ - return 1; + if (pIndex->bUnordered) return 0; + if ((pOB = pBuilder->pWInfo->pOrderBy)==0) return 0; + for (ii=0; iinExpr; ii++) { + Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr); + if (pExpr->op==TK_COLUMN && pExpr->iTable==iCursor) { + if (pExpr->iColumn<0) return 1; + for (jj=0; jjnKeyCol; jj++) { + if (pExpr->iColumn==pIndex->aiColumn[jj]) return 1; + } + } else if ((aColExpr = pIndex->aColExpr)!=0) { + for (jj=0; jjnKeyCol; jj++) { + if (pIndex->aiColumn[jj]!=XN_EXPR) continue; + if (sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0) { + return 1; + } + } } - } } - } - return 0; + return 0; } /* Check to see if a partial index with pPartIndexWhere can be used ** in the current query. Return true if it can be and false if not. */ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ - int i; - WhereTerm *pTerm; - Parse *pParse = pWC->pWInfo->pParse; - while( pWhere->op==TK_AND ){ - if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0; - pWhere = pWhere->pRight; - } - if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0; - for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - Expr *pExpr = pTerm->pExpr; - if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) - && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) - ){ - return 1; + int i; + WhereTerm *pTerm; + Parse *pParse = pWC->pWInfo->pParse; + while (pWhere->op==TK_AND) { + if (!whereUsablePartialIndex(iTab,pWC,pWhere->pLeft)) return 0; + pWhere = pWhere->pRight; } - } - return 0; + if (pParse->db->flags & SQLITE_EnableQPSG) pParse = 0; + for (i=0, pTerm=pWC->a; inTerm; i++, pTerm++) { + Expr *pExpr = pTerm->pExpr; + if ((!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) + && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) + ) { + return 1; + } + } + return 0; } /* @@ -2823,18 +2823,18 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ ** cost = nRow * K // scan of covering index ** cost = nRow * (K+3.0) // scan of non-covering index ** -** where K is a value between 1.1 and 3.0 set based on the relative +** where K is a value between 1.1 and 3.0 set based on the relative ** estimated average size of the index and table records. ** ** For an index scan, where nVisit is the number of index rows visited -** by the scan, and nSeek is the number of seek operations required on +** by the scan, and nSeek is the number of seek operations required on ** the index b-tree: ** ** cost = nSeek * (log(nRow) + K * nVisit) // covering index ** cost = nSeek * (log(nRow) + (K+3.0) * nVisit) // non-covering index ** -** Normally, nSeek is 1. nSeek values greater than 1 come about if the -** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when +** Normally, nSeek is 1. nSeek values greater than 1 come about if the +** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when ** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans. ** ** The estimated values (nRow, nVisit, nSeek) often contain a large amount @@ -2846,235 +2846,235 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ ** of a full table scan. */ static int whereLoopAddBtree( - WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mPrereq /* Extra prerequesites for using this table */ -){ - WhereInfo *pWInfo; /* WHERE analysis context */ - Index *pProbe; /* An index we are evaluating */ - Index sPk; /* A fake index object for the primary key */ - LogEst aiRowEstPk[2]; /* The aiRowLogEst[] value for the sPk index */ - i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */ - SrcList *pTabList; /* The FROM clause */ - struct SrcList_item *pSrc; /* The FROM clause btree term to add */ - WhereLoop *pNew; /* Template WhereLoop object */ - int rc = SQLITE_OK; /* Return code */ - int iSortIdx = 1; /* Index number */ - int b; /* A boolean value */ - LogEst rSize; /* number of rows in the table */ - LogEst rLogSize; /* Logarithm of the number of rows in the table */ - WhereClause *pWC; /* The parsed WHERE clause */ - Table *pTab; /* Table being queried */ - - pNew = pBuilder->pNew; - pWInfo = pBuilder->pWInfo; - pTabList = pWInfo->pTabList; - pSrc = pTabList->a + pNew->iTab; - pTab = pSrc->pTab; - pWC = pBuilder->pWC; - assert( !IsVirtual(pSrc->pTab) ); + WhereLoopBuilder *pBuilder, /* WHERE clause information */ + Bitmask mPrereq /* Extra prerequesites for using this table */ + ){ + WhereInfo *pWInfo; /* WHERE analysis context */ + Index *pProbe; /* An index we are evaluating */ + Index sPk; /* A fake index object for the primary key */ + LogEst aiRowEstPk[2]; /* The aiRowLogEst[] value for the sPk index */ + i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */ + SrcList *pTabList; /* The FROM clause */ + struct SrcList_item *pSrc; /* The FROM clause btree term to add */ + WhereLoop *pNew; /* Template WhereLoop object */ + int rc = SQLITE_OK; /* Return code */ + int iSortIdx = 1; /* Index number */ + int b; /* A boolean value */ + LogEst rSize; /* number of rows in the table */ + LogEst rLogSize; /* Logarithm of the number of rows in the table */ + WhereClause *pWC; /* The parsed WHERE clause */ + Table *pTab; /* Table being queried */ - if( pSrc->pIBIndex ){ - /* An INDEXED BY clause specifies a particular index to use */ - pProbe = pSrc->pIBIndex; - }else if( !HasRowid(pTab) ){ - pProbe = pTab->pIndex; - }else{ - /* There is no INDEXED BY clause. Create a fake Index object in local - ** variable sPk to represent the rowid primary key index. Make this - ** fake index the first in a chain of Index objects with all of the real - ** indices to follow */ - Index *pFirst; /* First of real indices on the table */ - memset(&sPk, 0, sizeof(Index)); - sPk.nKeyCol = 1; - sPk.nColumn = 1; - sPk.aiColumn = &aiColumnPk; - sPk.aiRowLogEst = aiRowEstPk; - sPk.onError = OE_Replace; - sPk.pTable = pTab; - sPk.szIdxRow = pTab->szTabRow; - sPk.idxType = SQLITE_IDXTYPE_IPK; - aiRowEstPk[0] = pTab->nRowLogEst; - aiRowEstPk[1] = 0; - pFirst = pSrc->pTab->pIndex; - if( pSrc->fg.notIndexed==0 ){ - /* The real indices of the table are only considered if the - ** NOT INDEXED qualifier is omitted from the FROM clause */ - sPk.pNext = pFirst; + pNew = pBuilder->pNew; + pWInfo = pBuilder->pWInfo; + pTabList = pWInfo->pTabList; + pSrc = pTabList->a + pNew->iTab; + pTab = pSrc->pTab; + pWC = pBuilder->pWC; + assert( !IsVirtual(pSrc->pTab)); + + if (pSrc->pIBIndex) { + /* An INDEXED BY clause specifies a particular index to use */ + pProbe = pSrc->pIBIndex; + } else if (!HasRowid(pTab)) { + pProbe = pTab->pIndex; + } else { + /* There is no INDEXED BY clause. Create a fake Index object in local + ** variable sPk to represent the rowid primary key index. Make this + ** fake index the first in a chain of Index objects with all of the real + ** indices to follow */ + Index *pFirst; /* First of real indices on the table */ + memset(&sPk, 0, sizeof(Index)); + sPk.nKeyCol = 1; + sPk.nColumn = 1; + sPk.aiColumn = &aiColumnPk; + sPk.aiRowLogEst = aiRowEstPk; + sPk.onError = OE_Replace; + sPk.pTable = pTab; + sPk.szIdxRow = pTab->szTabRow; + sPk.idxType = SQLITE_IDXTYPE_IPK; + aiRowEstPk[0] = pTab->nRowLogEst; + aiRowEstPk[1] = 0; + pFirst = pSrc->pTab->pIndex; + if (pSrc->fg.notIndexed==0) { + /* The real indices of the table are only considered if the + ** NOT INDEXED qualifier is omitted from the FROM clause */ + sPk.pNext = pFirst; + } + pProbe = &sPk; } - pProbe = &sPk; - } - rSize = pTab->nRowLogEst; - rLogSize = estLog(rSize); + rSize = pTab->nRowLogEst; + rLogSize = estLog(rSize); #ifndef SQLITE_OMIT_AUTOMATIC_INDEX - /* Automatic indexes */ - if( !pBuilder->pOrSet /* Not part of an OR optimization */ - && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 - && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */ - && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ - && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ - && !pSrc->fg.isCorrelated /* Not a correlated subquery */ - && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ - ){ - /* Generate auto-index WhereLoops */ - WhereTerm *pTerm; - WhereTerm *pWCEnd = pWC->a + pWC->nTerm; - for(pTerm=pWC->a; rc==SQLITE_OK && pTermprereqRight & pNew->maskSelf ) continue; - if( termCanDriveIndex(pTerm, pSrc, 0) ){ - pNew->u.btree.nEq = 1; - pNew->nSkip = 0; - pNew->u.btree.pIndex = 0; - pNew->nLTerm = 1; - pNew->aLTerm[0] = pTerm; - /* TUNING: One-time cost for computing the automatic index is - ** estimated to be X*N*log2(N) where N is the number of rows in - ** the table being indexed and where X is 7 (LogEst=28) for normal - ** tables or 0.5 (LogEst=-10) for views and subqueries. The value - ** of X is smaller for views and subqueries so that the query planner - ** will be more aggressive about generating automatic indexes for - ** those objects, since there is no opportunity to add schema - ** indexes on subqueries and views. */ - pNew->rSetup = rLogSize + rSize; - if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){ - pNew->rSetup += 28; - }else{ - pNew->rSetup -= 10; + /* Automatic indexes */ + if (!pBuilder->pOrSet /* Not part of an OR optimization */ + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 + && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 + && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */ + && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ + && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ + && !pSrc->fg.isCorrelated /* Not a correlated subquery */ + && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ + ) { + /* Generate auto-index WhereLoops */ + WhereTerm *pTerm; + WhereTerm *pWCEnd = pWC->a + pWC->nTerm; + for (pTerm=pWC->a; rc==SQLITE_OK && pTermprereqRight & pNew->maskSelf) continue; + if (termCanDriveIndex(pTerm, pSrc, 0)) { + pNew->u.btree.nEq = 1; + pNew->nSkip = 0; + pNew->u.btree.pIndex = 0; + pNew->nLTerm = 1; + pNew->aLTerm[0] = pTerm; + /* TUNING: One-time cost for computing the automatic index is + ** estimated to be X*N*log2(N) where N is the number of rows in + ** the table being indexed and where X is 7 (LogEst=28) for normal + ** tables or 0.5 (LogEst=-10) for views and subqueries. The value + ** of X is smaller for views and subqueries so that the query planner + ** will be more aggressive about generating automatic indexes for + ** those objects, since there is no opportunity to add schema + ** indexes on subqueries and views. */ + pNew->rSetup = rLogSize + rSize; + if (pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0) { + pNew->rSetup += 28; + } else { + pNew->rSetup -= 10; + } + ApplyCostMultiplier(pNew->rSetup, pTab->costMult); + if (pNew->rSetup<0) pNew->rSetup = 0; + /* TUNING: Each index lookup yields 20 rows in the table. This + ** is more than the usual guess of 10 rows, since we have no way + ** of knowing how selective the index will ultimately be. It would + ** not be unreasonable to make this value much larger. */ + pNew->nOut = 43; assert( 43==sqlite3LogEst(20)); + pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut); + pNew->wsFlags = WHERE_AUTO_INDEX; + pNew->prereq = mPrereq | pTerm->prereqRight; + rc = whereLoopInsert(pBuilder, pNew); + } } - ApplyCostMultiplier(pNew->rSetup, pTab->costMult); - if( pNew->rSetup<0 ) pNew->rSetup = 0; - /* TUNING: Each index lookup yields 20 rows in the table. This - ** is more than the usual guess of 10 rows, since we have no way - ** of knowing how selective the index will ultimately be. It would - ** not be unreasonable to make this value much larger. */ - pNew->nOut = 43; assert( 43==sqlite3LogEst(20) ); - pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut); - pNew->wsFlags = WHERE_AUTO_INDEX; - pNew->prereq = mPrereq | pTerm->prereqRight; - rc = whereLoopInsert(pBuilder, pNew); - } } - } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - /* Loop over all indices. If there was an INDEXED BY clause, then only - ** consider index pProbe. */ - for(; rc==SQLITE_OK && pProbe; - pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++ - ){ - if( pProbe->pPartIdxWhere!=0 - && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){ - testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ - continue; /* Partial index inappropriate for this query */ - } - if( pProbe->bNoQuery ) continue; - rSize = pProbe->aiRowLogEst[0]; - pNew->u.btree.nEq = 0; - pNew->u.btree.nBtm = 0; - pNew->u.btree.nTop = 0; - pNew->nSkip = 0; - pNew->nLTerm = 0; - pNew->iSortIdx = 0; - pNew->rSetup = 0; - pNew->prereq = mPrereq; - pNew->nOut = rSize; - pNew->u.btree.pIndex = pProbe; - b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor); - /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */ - assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 ); - if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ - /* Integer primary key index */ - pNew->wsFlags = WHERE_IPK; - - /* Full table scan */ - pNew->iSortIdx = b ? iSortIdx : 0; - /* TUNING: Cost of full table scan is (N*3.0). */ - pNew->rRun = rSize + 16; - ApplyCostMultiplier(pNew->rRun, pTab->costMult); - whereLoopOutputAdjust(pWC, pNew, rSize); - rc = whereLoopInsert(pBuilder, pNew); - pNew->nOut = rSize; - if( rc ) break; - }else{ - Bitmask m; - if( pProbe->isCovering ){ - pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; - m = 0; - }else{ - m = pSrc->colUsed & pProbe->colNotIdxed; - pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED; - } - - /* Full scan via index */ - if( b - || !HasRowid(pTab) - || pProbe->pPartIdxWhere!=0 - || ( m==0 - && pProbe->bUnordered==0 - && (pProbe->szIdxRowszTabRow) - && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 - && sqlite3GlobalConfig.bUseCis - && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan) - ) - ){ - pNew->iSortIdx = b ? iSortIdx : 0; - - /* The cost of visiting the index rows is N*K, where K is - ** between 1.1 and 3.0, depending on the relative sizes of the - ** index and table rows. */ - pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; - if( m!=0 ){ - /* If this is a non-covering index scan, add in the cost of - ** doing table lookups. The cost will be 3x the number of - ** lookups. Take into account WHERE clause terms that can be - ** satisfied using just the index, and that do not require a - ** table lookup. */ - LogEst nLookup = rSize + 16; /* Base cost: N*3 */ - int ii; - int iCur = pSrc->iCursor; - WhereClause *pWC2 = &pWInfo->sWC; - for(ii=0; iinTerm; ii++){ - WhereTerm *pTerm = &pWC2->a[ii]; - if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){ - break; - } - /* pTerm can be evaluated using just the index. So reduce - ** the expected number of table lookups accordingly */ - if( pTerm->truthProb<=0 ){ - nLookup += pTerm->truthProb; - }else{ - nLookup--; - if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19; - } - } - - pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup); + /* Loop over all indices. If there was an INDEXED BY clause, then only + ** consider index pProbe. */ + for (; rc==SQLITE_OK && pProbe; + pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++ + ) { + if (pProbe->pPartIdxWhere!=0 + && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere)) { + testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ + continue; /* Partial index inappropriate for this query */ } - ApplyCostMultiplier(pNew->rRun, pTab->costMult); - whereLoopOutputAdjust(pWC, pNew, rSize); - rc = whereLoopInsert(pBuilder, pNew); + if (pProbe->bNoQuery) continue; + rSize = pProbe->aiRowLogEst[0]; + pNew->u.btree.nEq = 0; + pNew->u.btree.nBtm = 0; + pNew->u.btree.nTop = 0; + pNew->nSkip = 0; + pNew->nLTerm = 0; + pNew->iSortIdx = 0; + pNew->rSetup = 0; + pNew->prereq = mPrereq; pNew->nOut = rSize; - if( rc ) break; - } - } + pNew->u.btree.pIndex = pProbe; + b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor); + /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */ + assert((pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 ); + if (pProbe->idxType==SQLITE_IDXTYPE_IPK) { + /* Integer primary key index */ + pNew->wsFlags = WHERE_IPK; - pBuilder->bldFlags = 0; - rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); - if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){ - /* If a non-unique index is used, or if a prefix of the key for - ** unique index is used (making the index functionally non-unique) - ** then the sqlite_stat1 data becomes important for scoring the - ** plan */ - pTab->tabFlags |= TF_StatsUsed; - } + /* Full table scan */ + pNew->iSortIdx = b ? iSortIdx : 0; + /* TUNING: Cost of full table scan is (N*3.0). */ + pNew->rRun = rSize + 16; + ApplyCostMultiplier(pNew->rRun, pTab->costMult); + whereLoopOutputAdjust(pWC, pNew, rSize); + rc = whereLoopInsert(pBuilder, pNew); + pNew->nOut = rSize; + if (rc) break; + } else { + Bitmask m; + if (pProbe->isCovering) { + pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; + m = 0; + } else { + m = pSrc->colUsed & pProbe->colNotIdxed; + pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED; + } + + /* Full scan via index */ + if (b + || !HasRowid(pTab) + || pProbe->pPartIdxWhere!=0 + || (m==0 + && pProbe->bUnordered==0 + && (pProbe->szIdxRowszTabRow) + && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 + && sqlite3GlobalConfig.bUseCis + && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan) + ) + ) { + pNew->iSortIdx = b ? iSortIdx : 0; + + /* The cost of visiting the index rows is N*K, where K is + ** between 1.1 and 3.0, depending on the relative sizes of the + ** index and table rows. */ + pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; + if (m!=0) { + /* If this is a non-covering index scan, add in the cost of + ** doing table lookups. The cost will be 3x the number of + ** lookups. Take into account WHERE clause terms that can be + ** satisfied using just the index, and that do not require a + ** table lookup. */ + LogEst nLookup = rSize + 16; /* Base cost: N*3 */ + int ii; + int iCur = pSrc->iCursor; + WhereClause *pWC2 = &pWInfo->sWC; + for (ii=0; iinTerm; ii++) { + WhereTerm *pTerm = &pWC2->a[ii]; + if (!sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe)) { + break; + } + /* pTerm can be evaluated using just the index. So reduce + ** the expected number of table lookups accordingly */ + if (pTerm->truthProb<=0) { + nLookup += pTerm->truthProb; + } else { + nLookup--; + if (pTerm->eOperator & (WO_EQ|WO_IS)) nLookup -= 19; + } + } + + pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup); + } + ApplyCostMultiplier(pNew->rRun, pTab->costMult); + whereLoopOutputAdjust(pWC, pNew, rSize); + rc = whereLoopInsert(pBuilder, pNew); + pNew->nOut = rSize; + if (rc) break; + } + } + + pBuilder->bldFlags = 0; + rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); + if (pBuilder->bldFlags==SQLITE_BLDF_INDEXED) { + /* If a non-unique index is used, or if a prefix of the key for + ** unique index is used (making the index functionally non-unique) + ** then the sqlite_stat1 data becomes important for scoring the + ** plan */ + pTab->tabFlags |= TF_StatsUsed; + } #ifdef SQLITE_ENABLE_STAT4 - sqlite3Stat4ProbeFree(pBuilder->pRec); - pBuilder->nRecValid = 0; - pBuilder->pRec = 0; + sqlite3Stat4ProbeFree(pBuilder->pRec); + pBuilder->nRecValid = 0; + pBuilder->pRec = 0; #endif - } - return rc; + } + return rc; } #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -3100,150 +3100,150 @@ static int whereLoopAddBtree( ** uses one or more WO_IN terms, or false otherwise. */ static int whereLoopAddVirtualOne( - WhereLoopBuilder *pBuilder, - Bitmask mPrereq, /* Mask of tables that must be used. */ - Bitmask mUsable, /* Mask of usable tables */ - u16 mExclude, /* Exclude terms using these operators */ - sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ - u16 mNoOmit, /* Do not omit these constraints */ - int *pbIn /* OUT: True if plan uses an IN(...) op */ -){ - WhereClause *pWC = pBuilder->pWC; - struct sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage; - int i; - int mxTerm; - int rc = SQLITE_OK; - WhereLoop *pNew = pBuilder->pNew; - Parse *pParse = pBuilder->pWInfo->pParse; - struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab]; - int nConstraint = pIdxInfo->nConstraint; - - assert( (mUsable & mPrereq)==mPrereq ); - *pbIn = 0; - pNew->prereq = mPrereq; - - /* Set the usable flag on the subset of constraints identified by - ** arguments mUsable and mExclude. */ - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; - for(i=0; ia[pIdxCons->iTermOffset]; - pIdxCons->usable = 0; - if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight - && (pTerm->eOperator & mExclude)==0 + WhereLoopBuilder *pBuilder, + Bitmask mPrereq, /* Mask of tables that must be used. */ + Bitmask mUsable, /* Mask of usable tables */ + u16 mExclude, /* Exclude terms using these operators */ + sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ + u16 mNoOmit, /* Do not omit these constraints */ + int *pbIn /* OUT: True if plan uses an IN(...) op */ ){ - pIdxCons->usable = 1; - } - } + WhereClause *pWC = pBuilder->pWC; + struct sqlite3_index_constraint *pIdxCons; + struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage; + int i; + int mxTerm; + int rc = SQLITE_OK; + WhereLoop *pNew = pBuilder->pNew; + Parse *pParse = pBuilder->pWInfo->pParse; + struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab]; + int nConstraint = pIdxInfo->nConstraint; - /* Initialize the output fields of the sqlite3_index_info structure */ - memset(pUsage, 0, sizeof(pUsage[0])*nConstraint); - assert( pIdxInfo->needToFreeIdxStr==0 ); - pIdxInfo->idxStr = 0; - pIdxInfo->idxNum = 0; - pIdxInfo->orderByConsumed = 0; - pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; - pIdxInfo->estimatedRows = 25; - pIdxInfo->idxFlags = 0; - pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; + assert((mUsable & mPrereq)==mPrereq ); + *pbIn = 0; + pNew->prereq = mPrereq; - /* Invoke the virtual table xBestIndex() method */ - rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); - if( rc ){ - if( rc==SQLITE_CONSTRAINT ){ - /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means - ** that the particular combination of parameters provided is unusable. - ** Make no entries in the loop table. - */ - WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); - return SQLITE_OK; + /* Set the usable flag on the subset of constraints identified by + ** arguments mUsable and mExclude. */ + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; + for (i=0; ia[pIdxCons->iTermOffset]; + pIdxCons->usable = 0; + if ((pTerm->prereqRight & mUsable)==pTerm->prereqRight + && (pTerm->eOperator & mExclude)==0 + ) { + pIdxCons->usable = 1; + } } + + /* Initialize the output fields of the sqlite3_index_info structure */ + memset(pUsage, 0, sizeof(pUsage[0])*nConstraint); + assert( pIdxInfo->needToFreeIdxStr==0 ); + pIdxInfo->idxStr = 0; + pIdxInfo->idxNum = 0; + pIdxInfo->orderByConsumed = 0; + pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; + pIdxInfo->estimatedRows = 25; + pIdxInfo->idxFlags = 0; + pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; + + /* Invoke the virtual table xBestIndex() method */ + rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); + if (rc) { + if (rc==SQLITE_CONSTRAINT) { + /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means + ** that the particular combination of parameters provided is unusable. + ** Make no entries in the loop table. + */ + WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); + return SQLITE_OK; + } + return rc; + } + + mxTerm = -1; + assert( pNew->nLSlot>=nConstraint ); + for (i=0; iaLTerm[i] = 0; + pNew->u.vtab.omitMask = 0; + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; + for (i=0; i=0) { + WhereTerm *pTerm; + int j = pIdxCons->iTermOffset; + if (iTerm>=nConstraint + || j<0 + || j>=pWC->nTerm + || pNew->aLTerm[iTerm]!=0 + || pIdxCons->usable==0 + ) { + sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); + testcase( pIdxInfo->needToFreeIdxStr ); + return SQLITE_ERROR; + } + testcase( iTerm==nConstraint-1 ); + testcase( j==0 ); + testcase( j==pWC->nTerm-1 ); + pTerm = &pWC->a[j]; + pNew->prereq |= pTerm->prereqRight; + assert( iTermnLSlot ); + pNew->aLTerm[iTerm] = pTerm; + if (iTerm>mxTerm) mxTerm = iTerm; + testcase( iTerm==15 ); + testcase( iTerm==16 ); + if (iTerm<16 && pUsage[i].omit) pNew->u.vtab.omitMask |= 1<eOperator & WO_IN)!=0) { + /* A virtual table that is constrained by an IN clause may not + ** consume the ORDER BY clause because (1) the order of IN terms + ** is not necessarily related to the order of output terms and + ** (2) Multiple outputs from a single IN value will not merge + ** together. */ + pIdxInfo->orderByConsumed = 0; + pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; + *pbIn = 1; assert((mExclude & WO_IN)==0 ); + } + } + } + pNew->u.vtab.omitMask &= ~mNoOmit; + + pNew->nLTerm = mxTerm+1; + for (i=0; i<=mxTerm; i++) { + if (pNew->aLTerm[i]==0) { + /* The non-zero argvIdx values must be contiguous. Raise an + ** error if they are not */ + sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); + testcase( pIdxInfo->needToFreeIdxStr ); + return SQLITE_ERROR; + } + } + assert( pNew->nLTerm<=pNew->nLSlot ); + pNew->u.vtab.idxNum = pIdxInfo->idxNum; + pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; + pIdxInfo->needToFreeIdxStr = 0; + pNew->u.vtab.idxStr = pIdxInfo->idxStr; + pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? + pIdxInfo->nOrderBy : 0); + pNew->rSetup = 0; + pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); + pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); + + /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated + ** that the scan will visit at most one row. Clear it otherwise. */ + if (pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE) { + pNew->wsFlags |= WHERE_ONEROW; + } else { + pNew->wsFlags &= ~WHERE_ONEROW; + } + rc = whereLoopInsert(pBuilder, pNew); + if (pNew->u.vtab.needFree) { + sqlite3_free(pNew->u.vtab.idxStr); + pNew->u.vtab.needFree = 0; + } + WHERETRACE(0xffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n", + *pbIn, (sqlite3_uint64)mPrereq, + (sqlite3_uint64)(pNew->prereq & ~mPrereq))); + return rc; - } - - mxTerm = -1; - assert( pNew->nLSlot>=nConstraint ); - for(i=0; iaLTerm[i] = 0; - pNew->u.vtab.omitMask = 0; - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; - for(i=0; i=0 ){ - WhereTerm *pTerm; - int j = pIdxCons->iTermOffset; - if( iTerm>=nConstraint - || j<0 - || j>=pWC->nTerm - || pNew->aLTerm[iTerm]!=0 - || pIdxCons->usable==0 - ){ - sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); - testcase( pIdxInfo->needToFreeIdxStr ); - return SQLITE_ERROR; - } - testcase( iTerm==nConstraint-1 ); - testcase( j==0 ); - testcase( j==pWC->nTerm-1 ); - pTerm = &pWC->a[j]; - pNew->prereq |= pTerm->prereqRight; - assert( iTermnLSlot ); - pNew->aLTerm[iTerm] = pTerm; - if( iTerm>mxTerm ) mxTerm = iTerm; - testcase( iTerm==15 ); - testcase( iTerm==16 ); - if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<eOperator & WO_IN)!=0 ){ - /* A virtual table that is constrained by an IN clause may not - ** consume the ORDER BY clause because (1) the order of IN terms - ** is not necessarily related to the order of output terms and - ** (2) Multiple outputs from a single IN value will not merge - ** together. */ - pIdxInfo->orderByConsumed = 0; - pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; - *pbIn = 1; assert( (mExclude & WO_IN)==0 ); - } - } - } - pNew->u.vtab.omitMask &= ~mNoOmit; - - pNew->nLTerm = mxTerm+1; - for(i=0; i<=mxTerm; i++){ - if( pNew->aLTerm[i]==0 ){ - /* The non-zero argvIdx values must be contiguous. Raise an - ** error if they are not */ - sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); - testcase( pIdxInfo->needToFreeIdxStr ); - return SQLITE_ERROR; - } - } - assert( pNew->nLTerm<=pNew->nLSlot ); - pNew->u.vtab.idxNum = pIdxInfo->idxNum; - pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; - pIdxInfo->needToFreeIdxStr = 0; - pNew->u.vtab.idxStr = pIdxInfo->idxStr; - pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? - pIdxInfo->nOrderBy : 0); - pNew->rSetup = 0; - pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); - pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows); - - /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated - ** that the scan will visit at most one row. Clear it otherwise. */ - if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){ - pNew->wsFlags |= WHERE_ONEROW; - }else{ - pNew->wsFlags &= ~WHERE_ONEROW; - } - rc = whereLoopInsert(pBuilder, pNew); - if( pNew->u.vtab.needFree ){ - sqlite3_free(pNew->u.vtab.idxStr); - pNew->u.vtab.needFree = 0; - } - WHERETRACE(0xffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n", - *pbIn, (sqlite3_uint64)mPrereq, - (sqlite3_uint64)(pNew->prereq & ~mPrereq))); - - return rc; } /* @@ -3254,18 +3254,18 @@ static int whereLoopAddVirtualOne( ** call, return NULL. */ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ - HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; - const char *zRet = 0; - if( iCons>=0 && iConsnConstraint ){ - CollSeq *pC = 0; - int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset; - Expr *pX = pHidden->pWC->a[iTerm].pExpr; - if( pX->pLeft ){ - pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight); + HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; + const char *zRet = 0; + if (iCons>=0 && iConsnConstraint) { + CollSeq *pC = 0; + int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset; + Expr *pX = pHidden->pWC->a[iTerm].pExpr; + if (pX->pLeft) { + pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight); + } + zRet = (pC ? pC->zName : sqlite3StrBINARY); } - zRet = (pC ? pC->zName : sqlite3StrBINARY); - } - return zRet; + return zRet; } /* @@ -3277,8 +3277,8 @@ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ ** entries that occur before the virtual table in the FROM clause and are ** separated from it by at least one LEFT or CROSS JOIN. Similarly, the ** mUnusable mask contains all FROM clause entries that occur after the -** virtual table and are separated from it by at least one LEFT or -** CROSS JOIN. +** virtual table and are separated from it by at least one LEFT or +** CROSS JOIN. ** ** For example, if the query were: ** @@ -3286,129 +3286,129 @@ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ ** ** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6). ** -** All the tables in mPrereq must be scanned before the current virtual -** table. So any terms for which all prerequisites are satisfied by -** mPrereq may be specified as "usable" in all calls to xBestIndex. +** All the tables in mPrereq must be scanned before the current virtual +** table. So any terms for which all prerequisites are satisfied by +** mPrereq may be specified as "usable" in all calls to xBestIndex. ** Conversely, all tables in mUnusable must be scanned after the current ** virtual table, so any terms for which the prerequisites overlap with ** mUnusable should always be configured as "not-usable" for xBestIndex. */ static int whereLoopAddVirtual( - WhereLoopBuilder *pBuilder, /* WHERE clause information */ - Bitmask mPrereq, /* Tables that must be scanned before this one */ - Bitmask mUnusable /* Tables that must be scanned after this one */ -){ - int rc = SQLITE_OK; /* Return code */ - WhereInfo *pWInfo; /* WHERE analysis context */ - Parse *pParse; /* The parsing context */ - WhereClause *pWC; /* The WHERE clause */ - struct SrcList_item *pSrc; /* The FROM clause term to search */ - sqlite3_index_info *p; /* Object to pass to xBestIndex() */ - int nConstraint; /* Number of constraints in p */ - int bIn; /* True if plan uses IN(...) operator */ - WhereLoop *pNew; - Bitmask mBest; /* Tables used by best possible plan */ - u16 mNoOmit; + WhereLoopBuilder *pBuilder, /* WHERE clause information */ + Bitmask mPrereq, /* Tables that must be scanned before this one */ + Bitmask mUnusable /* Tables that must be scanned after this one */ + ){ + int rc = SQLITE_OK; /* Return code */ + WhereInfo *pWInfo; /* WHERE analysis context */ + Parse *pParse; /* The parsing context */ + WhereClause *pWC; /* The WHERE clause */ + struct SrcList_item *pSrc; /* The FROM clause term to search */ + sqlite3_index_info *p; /* Object to pass to xBestIndex() */ + int nConstraint; /* Number of constraints in p */ + int bIn; /* True if plan uses IN(...) operator */ + WhereLoop *pNew; + Bitmask mBest; /* Tables used by best possible plan */ + u16 mNoOmit; - assert( (mPrereq & mUnusable)==0 ); - pWInfo = pBuilder->pWInfo; - pParse = pWInfo->pParse; - pWC = pBuilder->pWC; - pNew = pBuilder->pNew; - pSrc = &pWInfo->pTabList->a[pNew->iTab]; - assert( IsVirtual(pSrc->pTab) ); - p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy, - &mNoOmit); - if( p==0 ) return SQLITE_NOMEM_BKPT; - pNew->rSetup = 0; - pNew->wsFlags = WHERE_VIRTUALTABLE; - pNew->nLTerm = 0; - pNew->u.vtab.needFree = 0; - nConstraint = p->nConstraint; - if( whereLoopResize(pParse->db, pNew, nConstraint) ){ - sqlite3DbFree(pParse->db, p); - return SQLITE_NOMEM_BKPT; - } - - /* First call xBestIndex() with all constraints usable. */ - WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName)); - WHERETRACE(0x40, (" VirtualOne: all usable\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); - - /* If the call to xBestIndex() with all terms enabled produced a plan - ** that does not require any source tables (IOW: a plan with mBest==0) - ** and does not use an IN(...) operator, then there is no point in making - ** any further calls to xBestIndex() since they will all return the same - ** result (if the xBestIndex() implementation is sane). */ - if( rc==SQLITE_OK && ((mBest = (pNew->prereq & ~mPrereq))!=0 || bIn) ){ - int seenZero = 0; /* True if a plan with no prereqs seen */ - int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */ - Bitmask mPrev = 0; - Bitmask mBestNoIn = 0; - - /* If the plan produced by the earlier call uses an IN(...) term, call - ** xBestIndex again, this time with IN(...) terms disabled. */ - if( bIn ){ - WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n")); - rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn); - assert( bIn==0 ); - mBestNoIn = pNew->prereq & ~mPrereq; - if( mBestNoIn==0 ){ - seenZero = 1; - seenZeroNoIN = 1; - } + assert((mPrereq & mUnusable)==0 ); + pWInfo = pBuilder->pWInfo; + pParse = pWInfo->pParse; + pWC = pBuilder->pWC; + pNew = pBuilder->pNew; + pSrc = &pWInfo->pTabList->a[pNew->iTab]; + assert( IsVirtual(pSrc->pTab)); + p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy, + &mNoOmit); + if (p==0) return SQLITE_NOMEM_BKPT; + pNew->rSetup = 0; + pNew->wsFlags = WHERE_VIRTUALTABLE; + pNew->nLTerm = 0; + pNew->u.vtab.needFree = 0; + nConstraint = p->nConstraint; + if (whereLoopResize(pParse->db, pNew, nConstraint)) { + sqlite3DbFree(pParse->db, p); + return SQLITE_NOMEM_BKPT; } - /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq) - ** in the set of terms that apply to the current virtual table. */ - while( rc==SQLITE_OK ){ - int i; - Bitmask mNext = ALLBITS; - assert( mNext>0 ); - for(i=0; ia[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq - ); - if( mThis>mPrev && mThisprereq==mPrereq ){ - seenZero = 1; - if( bIn==0 ) seenZeroNoIN = 1; - } + /* First call xBestIndex() with all constraints usable. */ + WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName)); + WHERETRACE(0x40, (" VirtualOne: all usable\n")); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); + + /* If the call to xBestIndex() with all terms enabled produced a plan + ** that does not require any source tables (IOW: a plan with mBest==0) + ** and does not use an IN(...) operator, then there is no point in making + ** any further calls to xBestIndex() since they will all return the same + ** result (if the xBestIndex() implementation is sane). */ + if (rc==SQLITE_OK && ((mBest = (pNew->prereq & ~mPrereq))!=0 || bIn)) { + int seenZero = 0; /* True if a plan with no prereqs seen */ + int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */ + Bitmask mPrev = 0; + Bitmask mBestNoIn = 0; + + /* If the plan produced by the earlier call uses an IN(...) term, call + ** xBestIndex again, this time with IN(...) terms disabled. */ + if (bIn) { + WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n")); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn); + assert( bIn==0 ); + mBestNoIn = pNew->prereq & ~mPrereq; + if (mBestNoIn==0) { + seenZero = 1; + seenZeroNoIN = 1; + } + } + + /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq) + ** in the set of terms that apply to the current virtual table. */ + while (rc==SQLITE_OK) { + int i; + Bitmask mNext = ALLBITS; + assert( mNext>0 ); + for (i=0; ia[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq + ); + if (mThis>mPrev && mThisprereq==mPrereq) { + seenZero = 1; + if (bIn==0) seenZeroNoIN = 1; + } + } + + /* If the calls to xBestIndex() in the above loop did not find a plan + ** that requires no source tables at all (i.e. one guaranteed to be + ** usable), make a call here with all source tables disabled */ + if (rc==SQLITE_OK && seenZero==0) { + WHERETRACE(0x40, (" VirtualOne: all disabled\n")); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn); + if (bIn==0) seenZeroNoIN = 1; + } + + /* If the calls to xBestIndex() have so far failed to find a plan + ** that requires no source tables at all and does not use an IN(...) + ** operator, make a final call to obtain one here. */ + if (rc==SQLITE_OK && seenZeroNoIN==0) { + WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n")); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn); + } } - /* If the calls to xBestIndex() in the above loop did not find a plan - ** that requires no source tables at all (i.e. one guaranteed to be - ** usable), make a call here with all source tables disabled */ - if( rc==SQLITE_OK && seenZero==0 ){ - WHERETRACE(0x40, (" VirtualOne: all disabled\n")); - rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn); - if( bIn==0 ) seenZeroNoIN = 1; - } - - /* If the calls to xBestIndex() have so far failed to find a plan - ** that requires no source tables at all and does not use an IN(...) - ** operator, make a final call to obtain one here. */ - if( rc==SQLITE_OK && seenZeroNoIN==0 ){ - WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n")); - rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn); - } - } - - if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); - sqlite3DbFreeNN(pParse->db, p); - WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc)); - return rc; + if (p->needToFreeIdxStr) sqlite3_free(p->idxStr); + sqlite3DbFreeNN(pParse->db, p); + WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc)); + return rc; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -3417,495 +3417,495 @@ static int whereLoopAddVirtual( ** btrees or virtual tables. */ static int whereLoopAddOr( - WhereLoopBuilder *pBuilder, - Bitmask mPrereq, - Bitmask mUnusable -){ - WhereInfo *pWInfo = pBuilder->pWInfo; - WhereClause *pWC; - WhereLoop *pNew; - WhereTerm *pTerm, *pWCEnd; - int rc = SQLITE_OK; - int iCur; - WhereClause tempWC; - WhereLoopBuilder sSubBuild; - WhereOrSet sSum, sCur; - struct SrcList_item *pItem; - - pWC = pBuilder->pWC; - pWCEnd = pWC->a + pWC->nTerm; - pNew = pBuilder->pNew; - memset(&sSum, 0, sizeof(sSum)); - pItem = pWInfo->pTabList->a + pNew->iTab; - iCur = pItem->iCursor; - - for(pTerm=pWC->a; pTermeOperator & WO_OR)!=0 - && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 + WhereLoopBuilder *pBuilder, + Bitmask mPrereq, + Bitmask mUnusable ){ - WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; - WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; - WhereTerm *pOrTerm; - int once = 1; - int i, j; - - sSubBuild = *pBuilder; - sSubBuild.pOrderBy = 0; - sSubBuild.pOrSet = &sCur; + WhereInfo *pWInfo = pBuilder->pWInfo; + WhereClause *pWC; + WhereLoop *pNew; + WhereTerm *pTerm, *pWCEnd; + int rc = SQLITE_OK; + int iCur; + WhereClause tempWC; + WhereLoopBuilder sSubBuild; + WhereOrSet sSum, sCur; + struct SrcList_item *pItem; - WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm)); - for(pOrTerm=pOrWC->a; pOrTermeOperator & WO_AND)!=0 ){ - sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; - }else if( pOrTerm->leftCursor==iCur ){ - tempWC.pWInfo = pWC->pWInfo; - tempWC.pOuter = pWC; - tempWC.op = TK_AND; - tempWC.nTerm = 1; - tempWC.a = pOrTerm; - sSubBuild.pWC = &tempWC; - }else{ - continue; - } - sCur.n = 0; + pWC = pBuilder->pWC; + pWCEnd = pWC->a + pWC->nTerm; + pNew = pBuilder->pNew; + memset(&sSum, 0, sizeof(sSum)); + pItem = pWInfo->pTabList->a + pNew->iTab; + iCur = pItem->iCursor; + + for (pTerm=pWC->a; pTermeOperator & WO_OR)!=0 + && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 + ) { + WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; + WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; + WhereTerm *pOrTerm; + int once = 1; + int i, j; + + sSubBuild = *pBuilder; + sSubBuild.pOrderBy = 0; + sSubBuild.pOrSet = &sCur; + + WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm)); + for (pOrTerm=pOrWC->a; pOrTermeOperator & WO_AND)!=0) { + sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; + } else if (pOrTerm->leftCursor==iCur) { + tempWC.pWInfo = pWC->pWInfo; + tempWC.pOuter = pWC; + tempWC.op = TK_AND; + tempWC.nTerm = 1; + tempWC.a = pOrTerm; + sSubBuild.pWC = &tempWC; + } else { + continue; + } + sCur.n = 0; #ifdef WHERETRACE_ENABLED - WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n", - (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm)); - if( sqlite3WhereTrace & 0x400 ){ - sqlite3WhereClausePrint(sSubBuild.pWC); - } + WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n", + (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm)); + if (sqlite3WhereTrace & 0x400) { + sqlite3WhereClausePrint(sSubBuild.pWC); + } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pItem->pTab) ){ - rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable); - }else + if (IsVirtual(pItem->pTab)) { + rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable); + } else #endif - { - rc = whereLoopAddBtree(&sSubBuild, mPrereq); - } - if( rc==SQLITE_OK ){ - rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable); - } - assert( rc==SQLITE_OK || sCur.n==0 ); - if( sCur.n==0 ){ - sSum.n = 0; - break; - }else if( once ){ - whereOrMove(&sSum, &sCur); - once = 0; - }else{ - WhereOrSet sPrev; - whereOrMove(&sPrev, &sSum); - sSum.n = 0; - for(i=0; inLTerm = 1; + pNew->aLTerm[0] = pTerm; + pNew->wsFlags = WHERE_MULTI_OR; + pNew->rSetup = 0; + pNew->iSortIdx = 0; + memset(&pNew->u, 0, sizeof(pNew->u)); + for (i=0; rc==SQLITE_OK && irRun = sSum.a[i].rRun + 1; + pNew->nOut = sSum.a[i].nOut; + pNew->prereq = sSum.a[i].prereq; + rc = whereLoopInsert(pBuilder, pNew); + } + WHERETRACE(0x200, ("End processing OR-clause %p\n", pTerm)); } - } - pNew->nLTerm = 1; - pNew->aLTerm[0] = pTerm; - pNew->wsFlags = WHERE_MULTI_OR; - pNew->rSetup = 0; - pNew->iSortIdx = 0; - memset(&pNew->u, 0, sizeof(pNew->u)); - for(i=0; rc==SQLITE_OK && irRun = sSum.a[i].rRun + 1; - pNew->nOut = sSum.a[i].nOut; - pNew->prereq = sSum.a[i].prereq; - rc = whereLoopInsert(pBuilder, pNew); - } - WHERETRACE(0x200, ("End processing OR-clause %p\n", pTerm)); } - } - return rc; + return rc; } /* -** Add all WhereLoop objects for all tables +** Add all WhereLoop objects for all tables */ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ - WhereInfo *pWInfo = pBuilder->pWInfo; - Bitmask mPrereq = 0; - Bitmask mPrior = 0; - int iTab; - SrcList *pTabList = pWInfo->pTabList; - struct SrcList_item *pItem; - struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel]; - sqlite3 *db = pWInfo->pParse->db; - int rc = SQLITE_OK; - WhereLoop *pNew; - u8 priorJointype = 0; + WhereInfo *pWInfo = pBuilder->pWInfo; + Bitmask mPrereq = 0; + Bitmask mPrior = 0; + int iTab; + SrcList *pTabList = pWInfo->pTabList; + struct SrcList_item *pItem; + struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel]; + sqlite3 *db = pWInfo->pParse->db; + int rc = SQLITE_OK; + WhereLoop *pNew; + u8 priorJointype = 0; - /* Loop over the tables in the join, from left to right */ - pNew = pBuilder->pNew; - whereLoopInit(pNew); - pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; - for(iTab=0, pItem=pTabList->a; pItemiTab = iTab; - pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; - pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); - if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ - /* This condition is true when pItem is the FROM clause term on the - ** right-hand-side of a LEFT or CROSS JOIN. */ - mPrereq = mPrior; - } - priorJointype = pItem->fg.jointype; -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pItem->pTab) ){ - struct SrcList_item *p; - for(p=&pItem[1]; pfg.jointype & (JT_LEFT|JT_CROSS)) ){ - mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); + /* Loop over the tables in the join, from left to right */ + pNew = pBuilder->pNew; + whereLoopInit(pNew); + pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; + for (iTab=0, pItem=pTabList->a; pItemiTab = iTab; + pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; + pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); + if (((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0) { + /* This condition is true when pItem is the FROM clause term on the + ** right-hand-side of a LEFT or CROSS JOIN. */ + mPrereq = mPrior; } - } - rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable); - }else + priorJointype = pItem->fg.jointype; +#ifndef SQLITE_OMIT_VIRTUALTABLE + if (IsVirtual(pItem->pTab)) { + struct SrcList_item *p; + for (p=&pItem[1]; pfg.jointype & (JT_LEFT|JT_CROSS))) { + mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); + } + } + rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable); + } else #endif /* SQLITE_OMIT_VIRTUALTABLE */ - { - rc = whereLoopAddBtree(pBuilder, mPrereq); + { + rc = whereLoopAddBtree(pBuilder, mPrereq); + } + if (rc==SQLITE_OK && pBuilder->pWC->hasOr) { + rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); + } + mPrior |= pNew->maskSelf; + if (rc || db->mallocFailed) { + if (rc==SQLITE_DONE) { + /* We hit the query planner search limit set by iPlanLimit */ + sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); + rc = SQLITE_OK; + } else { + break; + } + } } - if( rc==SQLITE_OK && pBuilder->pWC->hasOr ){ - rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); - } - mPrior |= pNew->maskSelf; - if( rc || db->mallocFailed ){ - if( rc==SQLITE_DONE ){ - /* We hit the query planner search limit set by iPlanLimit */ - sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); - rc = SQLITE_OK; - }else{ - break; - } - } - } - whereLoopClear(db, pNew); - return rc; + whereLoopClear(db, pNew); + return rc; } /* ** Examine a WherePath (with the addition of the extra WhereLoop of the 6th ** parameters) to see if it outputs rows in the requested ORDER BY ** (or GROUP BY) without requiring a separate sort operation. Return N: -** +** ** N>0: N terms of the ORDER BY clause are satisfied ** N==0: No terms of the ORDER BY clause are satisfied -** N<0: Unknown yet how many terms of ORDER BY might be satisfied. +** N<0: Unknown yet how many terms of ORDER BY might be satisfied. ** ** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as ** strict. With GROUP BY and DISTINCT the only requirement is that ** equivalent rows appear immediately adjacent to one another. GROUP BY ** and DISTINCT do not require rows to appear in any particular order as long ** as equivalent rows are grouped together. Thus for GROUP BY and DISTINCT -** the pOrderBy terms can be matched in any order. With ORDER BY, the +** the pOrderBy terms can be matched in any order. With ORDER BY, the ** pOrderBy terms must be matched in strict left-to-right order. */ static i8 wherePathSatisfiesOrderBy( - WhereInfo *pWInfo, /* The WHERE clause */ - ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */ - WherePath *pPath, /* The WherePath to check */ - u16 wctrlFlags, /* WHERE_GROUPBY or _DISTINCTBY or _ORDERBY_LIMIT */ - u16 nLoop, /* Number of entries in pPath->aLoop[] */ - WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */ - Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */ -){ - u8 revSet; /* True if rev is known */ - u8 rev; /* Composite sort order */ - u8 revIdx; /* Index sort order */ - u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */ - u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */ - u8 isMatch; /* iColumn matches a term of the ORDER BY clause */ - u16 eqOpMask; /* Allowed equality operators */ - u16 nKeyCol; /* Number of key columns in pIndex */ - u16 nColumn; /* Total number of ordered columns in the index */ - u16 nOrderBy; /* Number terms in the ORDER BY clause */ - int iLoop; /* Index of WhereLoop in pPath being processed */ - int i, j; /* Loop counters */ - int iCur; /* Cursor number for current WhereLoop */ - int iColumn; /* A column number within table iCur */ - WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - Expr *pOBExpr; /* An expression from the ORDER BY clause */ - CollSeq *pColl; /* COLLATE function from an ORDER BY clause term */ - Index *pIndex; /* The index associated with pLoop */ - sqlite3 *db = pWInfo->pParse->db; /* Database connection */ - Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */ - Bitmask obDone; /* Mask of all ORDER BY terms */ - Bitmask orderDistinctMask; /* Mask of all well-ordered loops */ - Bitmask ready; /* Mask of inner loops */ + WhereInfo *pWInfo, /* The WHERE clause */ + ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */ + WherePath *pPath, /* The WherePath to check */ + u16 wctrlFlags, /* WHERE_GROUPBY or _DISTINCTBY or _ORDERBY_LIMIT */ + u16 nLoop, /* Number of entries in pPath->aLoop[] */ + WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */ + Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */ + ){ + u8 revSet; /* True if rev is known */ + u8 rev; /* Composite sort order */ + u8 revIdx; /* Index sort order */ + u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */ + u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */ + u8 isMatch; /* iColumn matches a term of the ORDER BY clause */ + u16 eqOpMask; /* Allowed equality operators */ + u16 nKeyCol; /* Number of key columns in pIndex */ + u16 nColumn; /* Total number of ordered columns in the index */ + u16 nOrderBy; /* Number terms in the ORDER BY clause */ + int iLoop; /* Index of WhereLoop in pPath being processed */ + int i, j; /* Loop counters */ + int iCur; /* Cursor number for current WhereLoop */ + int iColumn; /* A column number within table iCur */ + WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */ + WhereTerm *pTerm; /* A single term of the WHERE clause */ + Expr *pOBExpr; /* An expression from the ORDER BY clause */ + CollSeq *pColl; /* COLLATE function from an ORDER BY clause term */ + Index *pIndex; /* The index associated with pLoop */ + sqlite3 *db = pWInfo->pParse->db; /* Database connection */ + Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */ + Bitmask obDone; /* Mask of all ORDER BY terms */ + Bitmask orderDistinctMask; /* Mask of all well-ordered loops */ + Bitmask ready; /* Mask of inner loops */ - /* - ** We say the WhereLoop is "one-row" if it generates no more than one - ** row of output. A WhereLoop is one-row if all of the following are true: - ** (a) All index columns match with WHERE_COLUMN_EQ. - ** (b) The index is unique - ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row. - ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags. - ** - ** We say the WhereLoop is "order-distinct" if the set of columns from - ** that WhereLoop that are in the ORDER BY clause are different for every - ** row of the WhereLoop. Every one-row WhereLoop is automatically - ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause - ** is not order-distinct. To be order-distinct is not quite the same as being - ** UNIQUE since a UNIQUE column or index can have multiple rows that - ** are NULL and NULL values are equivalent for the purpose of order-distinct. - ** To be order-distinct, the columns must be UNIQUE and NOT NULL. - ** - ** The rowid for a table is always UNIQUE and NOT NULL so whenever the - ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is - ** automatically order-distinct. - */ - - assert( pOrderBy!=0 ); - if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0; - - nOrderBy = pOrderBy->nExpr; - testcase( nOrderBy==BMS-1 ); - if( nOrderBy>BMS-1 ) return 0; /* Cannot optimize overly large ORDER BYs */ - isOrderDistinct = 1; - obDone = MASKBIT(nOrderBy)-1; - orderDistinctMask = 0; - ready = 0; - eqOpMask = WO_EQ | WO_IS | WO_ISNULL; - if( wctrlFlags & WHERE_ORDERBY_LIMIT ) eqOpMask |= WO_IN; - for(iLoop=0; isOrderDistinct && obSat0 ) ready |= pLoop->maskSelf; - if( iLoopaLoop[iLoop]; - if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue; - }else{ - pLoop = pLast; - } - if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ - if( pLoop->u.vtab.isOrdered ) obSat = obDone; - break; - }else if( wctrlFlags & WHERE_DISTINCTBY ){ - pLoop->u.btree.nDistinctCol = 0; - } - iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; - - /* Mark off any ORDER BY term X that is a column in the table of - ** the current loop for which there is term in the WHERE - ** clause of the form X IS NULL or X=? that reference only outer - ** loops. + /* + ** We say the WhereLoop is "one-row" if it generates no more than one + ** row of output. A WhereLoop is one-row if all of the following are true: + ** (a) All index columns match with WHERE_COLUMN_EQ. + ** (b) The index is unique + ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row. + ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags. + ** + ** We say the WhereLoop is "order-distinct" if the set of columns from + ** that WhereLoop that are in the ORDER BY clause are different for every + ** row of the WhereLoop. Every one-row WhereLoop is automatically + ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause + ** is not order-distinct. To be order-distinct is not quite the same as being + ** UNIQUE since a UNIQUE column or index can have multiple rows that + ** are NULL and NULL values are equivalent for the purpose of order-distinct. + ** To be order-distinct, the columns must be UNIQUE and NOT NULL. + ** + ** The rowid for a table is always UNIQUE and NOT NULL so whenever the + ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is + ** automatically order-distinct. */ - for(i=0; ia[i].pExpr); - if( pOBExpr->op!=TK_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, - ~ready, eqOpMask, 0); - if( pTerm==0 ) continue; - if( pTerm->eOperator==WO_IN ){ - /* IN terms are only valid for sorting in the ORDER BY LIMIT - ** optimization, and then only if they are actually used - ** by the query plan */ - assert( wctrlFlags & WHERE_ORDERBY_LIMIT ); - for(j=0; jnLTerm && pTerm!=pLoop->aLTerm[j]; j++){} - if( j>=pLoop->nLTerm ) continue; - } - if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){ - if( sqlite3ExprCollSeqMatch(pWInfo->pParse, - pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){ - continue; - } - testcase( pTerm->pExpr->op==TK_IS ); - } - obSat |= MASKBIT(i); - } - if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){ - if( pLoop->wsFlags & WHERE_IPK ){ - pIndex = 0; - nKeyCol = 0; - nColumn = 1; - }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){ + assert( pOrderBy!=0 ); + if (nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin)) return 0; + + nOrderBy = pOrderBy->nExpr; + testcase( nOrderBy==BMS-1 ); + if (nOrderBy>BMS-1) return 0; /* Cannot optimize overly large ORDER BYs */ + isOrderDistinct = 1; + obDone = MASKBIT(nOrderBy)-1; + orderDistinctMask = 0; + ready = 0; + eqOpMask = WO_EQ | WO_IS | WO_ISNULL; + if (wctrlFlags & WHERE_ORDERBY_LIMIT) eqOpMask |= WO_IN; + for (iLoop=0; isOrderDistinct && obSat0) ready |= pLoop->maskSelf; + if (iLoopaLoop[iLoop]; + if (wctrlFlags & WHERE_ORDERBY_LIMIT) continue; + } else { + pLoop = pLast; + } + if (pLoop->wsFlags & WHERE_VIRTUALTABLE) { + if (pLoop->u.vtab.isOrdered) obSat = obDone; + break; + } else if (wctrlFlags & WHERE_DISTINCTBY) { + pLoop->u.btree.nDistinctCol = 0; + } + iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; + + /* Mark off any ORDER BY term X that is a column in the table of + ** the current loop for which there is term in the WHERE + ** clause of the form X IS NULL or X=? that reference only outer + ** loops. + */ + for (i=0; ia[i].pExpr); + if (pOBExpr->op!=TK_COLUMN) continue; + if (pOBExpr->iTable!=iCur) continue; + pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, + ~ready, eqOpMask, 0); + if (pTerm==0) continue; + if (pTerm->eOperator==WO_IN) { + /* IN terms are only valid for sorting in the ORDER BY LIMIT + ** optimization, and then only if they are actually used + ** by the query plan */ + assert( wctrlFlags & WHERE_ORDERBY_LIMIT ); + for (j=0; jnLTerm && pTerm!=pLoop->aLTerm[j]; j++) {} + if (j>=pLoop->nLTerm) continue; + } + if ((pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0) { + if (sqlite3ExprCollSeqMatch(pWInfo->pParse, + pOrderBy->a[i].pExpr, pTerm->pExpr)==0) { + continue; + } + testcase( pTerm->pExpr->op==TK_IS ); + } + obSat |= MASKBIT(i); + } + + if ((pLoop->wsFlags & WHERE_ONEROW)==0) { + if (pLoop->wsFlags & WHERE_IPK) { + pIndex = 0; + nKeyCol = 0; + nColumn = 1; + } else if ((pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered) { + return 0; + } else { + nKeyCol = pIndex->nKeyCol; + nColumn = pIndex->nColumn; + assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable)); + assert( pIndex->aiColumn[nColumn-1]==XN_ROWID + || !HasRowid(pIndex->pTable)); + isOrderDistinct = IsUniqueIndex(pIndex) + && (pLoop->wsFlags & WHERE_SKIPSCAN)==0; + } + + /* Loop through all columns of the index and deal with the ones + ** that are not constrained by == or IN. + */ + rev = revSet = 0; + distinctColumns = 0; + for (j=0; j=pLoop->u.btree.nEq + || (pLoop->aLTerm[j]==0)==(jnSkip) + ); + if (ju.btree.nEq && j>=pLoop->nSkip) { + u16 eOp = pLoop->aLTerm[j]->eOperator; + + /* Skip over == and IS and ISNULL terms. (Also skip IN terms when + ** doing WHERE_ORDERBY_LIMIT processing). + ** + ** If the current term is a column of an ((?,?) IN (SELECT...)) + ** expression for which the SELECT returns more than one column, + ** check that it is the only column used by this loop. Otherwise, + ** if it is one of two or more, none of the columns can be + ** considered to match an ORDER BY term. */ + if ((eOp & eqOpMask)!=0) { + if (eOp & WO_ISNULL) { + testcase( isOrderDistinct ); + isOrderDistinct = 0; + } + continue; + } else if (ALWAYS(eOp & WO_IN)) { + /* ALWAYS() justification: eOp is an equality operator due to the + ** ju.btree.nEq constraint above. Any equality other + ** than WO_IN is captured by the previous "if". So this one + ** always has to be WO_IN. */ + Expr *pX = pLoop->aLTerm[j]->pExpr; + for (i=j+1; iu.btree.nEq; i++) { + if (pLoop->aLTerm[i]->pExpr==pX) { + assert((pLoop->aLTerm[i]->eOperator & WO_IN)); + bOnce = 0; + break; + } + } + } + } + + /* Get the column number in the table (iColumn) and sort order + ** (revIdx) for the j-th column of the index. + */ + if (pIndex) { + iColumn = pIndex->aiColumn[j]; + revIdx = pIndex->aSortOrder[j]; + if (iColumn==pIndex->pTable->iPKey) iColumn = XN_ROWID; + } else { + iColumn = XN_ROWID; + revIdx = 0; + } + + /* An unconstrained column that might be NULL means that this + ** WhereLoop is not well-ordered + */ + if (isOrderDistinct + && iColumn>=0 + && j>=pLoop->u.btree.nEq + && pIndex->pTable->aCol[iColumn].notNull==0 + ) { + isOrderDistinct = 0; + } + + /* Find the ORDER BY term that corresponds to the j-th column + ** of the index and mark that ORDER BY term off + */ + isMatch = 0; + for (i=0; bOnce && ia[i].pExpr); + testcase( wctrlFlags & WHERE_GROUPBY ); + testcase( wctrlFlags & WHERE_DISTINCTBY ); + if ((wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0) bOnce = 0; + if (iColumn>=XN_ROWID) { + if (pOBExpr->op!=TK_COLUMN) continue; + if (pOBExpr->iTable!=iCur) continue; + if (pOBExpr->iColumn!=iColumn) continue; + } else { + Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr; + if (sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur)) { + continue; + } + } + if (iColumn!=XN_ROWID) { + pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); + if (sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0) continue; + } + if (wctrlFlags & WHERE_DISTINCTBY) { + pLoop->u.btree.nDistinctCol = j+1; + } + isMatch = 1; + break; + } + if (isMatch && (wctrlFlags & WHERE_GROUPBY)==0) { + /* Make sure the sort order is compatible in an ORDER BY clause. + ** Sort order is irrelevant for a GROUP BY clause. */ + if (revSet) { + if ((rev ^ revIdx)!=pOrderBy->a[i].sortOrder) isMatch = 0; + } else { + rev = revIdx ^ pOrderBy->a[i].sortOrder; + if (rev) *pRevMask |= MASKBIT(iLoop); + revSet = 1; + } + } + if (isMatch) { + if (iColumn==XN_ROWID) { + testcase( distinctColumns==0 ); + distinctColumns = 1; + } + obSat |= MASKBIT(i); + if ((wctrlFlags & WHERE_ORDERBY_MIN) && j==pLoop->u.btree.nEq) { + pLoop->wsFlags |= WHERE_MIN_ORDERED; + } + } else { + /* No match found */ + if (j==0 || jmaskSelf; + for (i=0; ia[i].pExpr; + mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); + if (mTerm==0 && !sqlite3ExprIsConstant(p)) continue; + if ((mTerm&~orderDistinctMask)==0) { + obSat |= MASKBIT(i); + } + } + } + } /* End the loop over all WhereLoops from outer-most down to inner-most */ + if (obSat==obDone) return (i8)nOrderBy; + if (!isOrderDistinct) { + for (i=nOrderBy-1; i>0; i--) { + Bitmask m = MASKBIT(i) - 1; + if ((obSat&m)==m) return i; + } return 0; - }else{ - nKeyCol = pIndex->nKeyCol; - nColumn = pIndex->nColumn; - assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) ); - assert( pIndex->aiColumn[nColumn-1]==XN_ROWID - || !HasRowid(pIndex->pTable)); - isOrderDistinct = IsUniqueIndex(pIndex) - && (pLoop->wsFlags & WHERE_SKIPSCAN)==0; - } - - /* Loop through all columns of the index and deal with the ones - ** that are not constrained by == or IN. - */ - rev = revSet = 0; - distinctColumns = 0; - for(j=0; j=pLoop->u.btree.nEq - || (pLoop->aLTerm[j]==0)==(jnSkip) - ); - if( ju.btree.nEq && j>=pLoop->nSkip ){ - u16 eOp = pLoop->aLTerm[j]->eOperator; - - /* Skip over == and IS and ISNULL terms. (Also skip IN terms when - ** doing WHERE_ORDERBY_LIMIT processing). - ** - ** If the current term is a column of an ((?,?) IN (SELECT...)) - ** expression for which the SELECT returns more than one column, - ** check that it is the only column used by this loop. Otherwise, - ** if it is one of two or more, none of the columns can be - ** considered to match an ORDER BY term. */ - if( (eOp & eqOpMask)!=0 ){ - if( eOp & WO_ISNULL ){ - testcase( isOrderDistinct ); - isOrderDistinct = 0; - } - continue; - }else if( ALWAYS(eOp & WO_IN) ){ - /* ALWAYS() justification: eOp is an equality operator due to the - ** ju.btree.nEq constraint above. Any equality other - ** than WO_IN is captured by the previous "if". So this one - ** always has to be WO_IN. */ - Expr *pX = pLoop->aLTerm[j]->pExpr; - for(i=j+1; iu.btree.nEq; i++){ - if( pLoop->aLTerm[i]->pExpr==pX ){ - assert( (pLoop->aLTerm[i]->eOperator & WO_IN) ); - bOnce = 0; - break; - } - } - } - } - - /* Get the column number in the table (iColumn) and sort order - ** (revIdx) for the j-th column of the index. - */ - if( pIndex ){ - iColumn = pIndex->aiColumn[j]; - revIdx = pIndex->aSortOrder[j]; - if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID; - }else{ - iColumn = XN_ROWID; - revIdx = 0; - } - - /* An unconstrained column that might be NULL means that this - ** WhereLoop is not well-ordered - */ - if( isOrderDistinct - && iColumn>=0 - && j>=pLoop->u.btree.nEq - && pIndex->pTable->aCol[iColumn].notNull==0 - ){ - isOrderDistinct = 0; - } - - /* Find the ORDER BY term that corresponds to the j-th column - ** of the index and mark that ORDER BY term off - */ - isMatch = 0; - for(i=0; bOnce && ia[i].pExpr); - testcase( wctrlFlags & WHERE_GROUPBY ); - testcase( wctrlFlags & WHERE_DISTINCTBY ); - if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; - if( iColumn>=XN_ROWID ){ - if( pOBExpr->op!=TK_COLUMN ) continue; - if( pOBExpr->iTable!=iCur ) continue; - if( pOBExpr->iColumn!=iColumn ) continue; - }else{ - Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr; - if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){ - continue; - } - } - if( iColumn!=XN_ROWID ){ - pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); - if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue; - } - if( wctrlFlags & WHERE_DISTINCTBY ){ - pLoop->u.btree.nDistinctCol = j+1; - } - isMatch = 1; - break; - } - if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){ - /* Make sure the sort order is compatible in an ORDER BY clause. - ** Sort order is irrelevant for a GROUP BY clause. */ - if( revSet ){ - if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0; - }else{ - rev = revIdx ^ pOrderBy->a[i].sortOrder; - if( rev ) *pRevMask |= MASKBIT(iLoop); - revSet = 1; - } - } - if( isMatch ){ - if( iColumn==XN_ROWID ){ - testcase( distinctColumns==0 ); - distinctColumns = 1; - } - obSat |= MASKBIT(i); - if( (wctrlFlags & WHERE_ORDERBY_MIN) && j==pLoop->u.btree.nEq ){ - pLoop->wsFlags |= WHERE_MIN_ORDERED; - } - }else{ - /* No match found */ - if( j==0 || jmaskSelf; - for(i=0; ia[i].pExpr; - mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); - if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; - if( (mTerm&~orderDistinctMask)==0 ){ - obSat |= MASKBIT(i); - } - } } - } /* End the loop over all WhereLoops from outer-most down to inner-most */ - if( obSat==obDone ) return (i8)nOrderBy; - if( !isOrderDistinct ){ - for(i=nOrderBy-1; i>0; i--){ - Bitmask m = MASKBIT(i) - 1; - if( (obSat&m)==m ) return i; - } - return 0; - } - return -1; + return -1; } @@ -3933,59 +3933,59 @@ static i8 wherePathSatisfiesOrderBy( ** SELECT * FROM t1 GROUP BY y,x ORDER BY y,x; -- IsSorted()==0 */ int sqlite3WhereIsSorted(WhereInfo *pWInfo){ - assert( pWInfo->wctrlFlags & WHERE_GROUPBY ); - assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP ); - return pWInfo->sorted; + assert( pWInfo->wctrlFlags & WHERE_GROUPBY ); + assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP ); + return pWInfo->sorted; } #ifdef WHERETRACE_ENABLED /* For debugging use only: */ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){ - static char zName[65]; - int i; - for(i=0; iaLoop[i]->cId; } - if( pLast ) zName[i++] = pLast->cId; - zName[i] = 0; - return zName; + static char zName[65]; + int i; + for (i=0; iaLoop[i]->cId; } + if (pLast) zName[i++] = pLast->cId; + zName[i] = 0; + return zName; } #endif /* -** Return the cost of sorting nRow rows, assuming that the keys have +** Return the cost of sorting nRow rows, assuming that the keys have ** nOrderby columns and that the first nSorted columns are already in ** order. */ static LogEst whereSortingCost( - WhereInfo *pWInfo, - LogEst nRow, - int nOrderBy, - int nSorted -){ - /* TUNING: Estimated cost of a full external sort, where N is - ** the number of rows to sort is: - ** - ** cost = (3.0 * N * log(N)). - ** - ** Or, if the order-by clause has X terms but only the last Y - ** terms are out of order, then block-sorting will reduce the - ** sorting cost to: - ** - ** cost = (3.0 * N * log(N)) * (Y/X) - ** - ** The (Y/X) term is implemented using stack variable rScale - ** below. */ - LogEst rScale, rSortCost; - assert( nOrderBy>0 && 66==sqlite3LogEst(100) ); - rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; - rSortCost = nRow + rScale + 16; + WhereInfo *pWInfo, + LogEst nRow, + int nOrderBy, + int nSorted + ){ + /* TUNING: Estimated cost of a full external sort, where N is + ** the number of rows to sort is: + ** + ** cost = (3.0 * N * log(N)). + ** + ** Or, if the order-by clause has X terms but only the last Y + ** terms are out of order, then block-sorting will reduce the + ** sorting cost to: + ** + ** cost = (3.0 * N * log(N)) * (Y/X) + ** + ** The (Y/X) term is implemented using stack variable rScale + ** below. */ + LogEst rScale, rSortCost; + assert( nOrderBy>0 && 66==sqlite3LogEst(100)); + rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; + rSortCost = nRow + rScale + 16; - /* Multiple by log(M) where M is the number of output rows. - ** Use the LIMIT for M if it is smaller */ - if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimitiLimit; - } - rSortCost += estLog(nRow); - return rSortCost; + /* Multiple by log(M) where M is the number of output rows. + ** Use the LIMIT for M if it is smaller */ + if ((pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimitiLimit; + } + rSortCost += estLog(nRow); + return rSortCost; } /* @@ -4001,379 +4001,379 @@ static LogEst whereSortingCost( ** error occurs. */ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ - int mxChoice; /* Maximum number of simultaneous paths tracked */ - int nLoop; /* Number of terms in the join */ - Parse *pParse; /* Parsing context */ - sqlite3 *db; /* The database connection */ - int iLoop; /* Loop counter over the terms of the join */ - int ii, jj; /* Loop counters */ - int mxI = 0; /* Index of next entry to replace */ - int nOrderBy; /* Number of ORDER BY clause terms */ - LogEst mxCost = 0; /* Maximum cost of a set of paths */ - LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */ - int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ - WherePath *aFrom; /* All nFrom paths at the previous level */ - WherePath *aTo; /* The nTo best paths at the current level */ - WherePath *pFrom; /* An element of aFrom[] that we are working on */ - WherePath *pTo; /* An element of aTo[] that we are working on */ - WhereLoop *pWLoop; /* One of the WhereLoop objects */ - WhereLoop **pX; /* Used to divy up the pSpace memory */ - LogEst *aSortCost = 0; /* Sorting and partial sorting costs */ - char *pSpace; /* Temporary memory used by this routine */ - int nSpace; /* Bytes of space allocated at pSpace */ + int mxChoice; /* Maximum number of simultaneous paths tracked */ + int nLoop; /* Number of terms in the join */ + Parse *pParse; /* Parsing context */ + sqlite3 *db; /* The database connection */ + int iLoop; /* Loop counter over the terms of the join */ + int ii, jj; /* Loop counters */ + int mxI = 0; /* Index of next entry to replace */ + int nOrderBy; /* Number of ORDER BY clause terms */ + LogEst mxCost = 0; /* Maximum cost of a set of paths */ + LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */ + int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ + WherePath *aFrom; /* All nFrom paths at the previous level */ + WherePath *aTo; /* The nTo best paths at the current level */ + WherePath *pFrom; /* An element of aFrom[] that we are working on */ + WherePath *pTo; /* An element of aTo[] that we are working on */ + WhereLoop *pWLoop; /* One of the WhereLoop objects */ + WhereLoop **pX; /* Used to divy up the pSpace memory */ + LogEst *aSortCost = 0; /* Sorting and partial sorting costs */ + char *pSpace; /* Temporary memory used by this routine */ + int nSpace; /* Bytes of space allocated at pSpace */ - pParse = pWInfo->pParse; - db = pParse->db; - nLoop = pWInfo->nLevel; - /* TUNING: For simple queries, only the best path is tracked. - ** For 2-way joins, the 5 best paths are followed. - ** For joins of 3 or more tables, track the 10 best paths */ - mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10); - assert( nLoop<=pWInfo->pTabList->nSrc ); - WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst)); + pParse = pWInfo->pParse; + db = pParse->db; + nLoop = pWInfo->nLevel; + /* TUNING: For simple queries, only the best path is tracked. + ** For 2-way joins, the 5 best paths are followed. + ** For joins of 3 or more tables, track the 10 best paths */ + mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10); + assert( nLoop<=pWInfo->pTabList->nSrc ); + WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst)); - /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this - ** case the purpose of this call is to estimate the number of rows returned - ** by the overall query. Once this estimate has been obtained, the caller - ** will invoke this function a second time, passing the estimate as the - ** nRowEst parameter. */ - if( pWInfo->pOrderBy==0 || nRowEst==0 ){ - nOrderBy = 0; - }else{ - nOrderBy = pWInfo->pOrderBy->nExpr; - } - - /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ - nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; - nSpace += sizeof(LogEst) * nOrderBy; - pSpace = sqlite3DbMallocRawNN(db, nSpace); - if( pSpace==0 ) return SQLITE_NOMEM_BKPT; - aTo = (WherePath*)pSpace; - aFrom = aTo+mxChoice; - memset(aFrom, 0, sizeof(aFrom[0])); - pX = (WhereLoop**)(aFrom+mxChoice); - for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){ - pFrom->aLoop = pX; - } - if( nOrderBy ){ - /* If there is an ORDER BY clause and it is not being ignored, set up - ** space for the aSortCost[] array. Each element of the aSortCost array - ** is either zero - meaning it has not yet been initialized - or the - ** cost of sorting nRowEst rows of data where the first X terms of - ** the ORDER BY clause are already in order, where X is the array - ** index. */ - aSortCost = (LogEst*)pX; - memset(aSortCost, 0, sizeof(LogEst) * nOrderBy); - } - assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] ); - assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX ); - - /* Seed the search with a single WherePath containing zero WhereLoops. - ** - ** TUNING: Do not let the number of iterations go above 28. If the cost - ** of computing an automatic index is not paid back within the first 28 - ** rows, then do not use the automatic index. */ - aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) ); - nFrom = 1; - assert( aFrom[0].isOrdered==0 ); - if( nOrderBy ){ - /* If nLoop is zero, then there are no FROM terms in the query. Since - ** in this case the query may return a maximum of one row, the results - ** are already in the requested order. Set isOrdered to nOrderBy to - ** indicate this. Or, if nLoop is greater than zero, set isOrdered to - ** -1, indicating that the result set may or may not be ordered, - ** depending on the loops added to the current plan. */ - aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy; - } - - /* Compute successively longer WherePaths using the previous generation - ** of WherePaths as the basis for the next. Keep track of the mxChoice - ** best paths at each generation */ - for(iLoop=0; iLooppLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ - LogEst nOut; /* Rows visited by (pFrom+pWLoop) */ - LogEst rCost; /* Cost of path (pFrom+pWLoop) */ - LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */ - i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */ - Bitmask maskNew; /* Mask of src visited by (..) */ - Bitmask revMask = 0; /* Mask of rev-order loops for (..) */ - - if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; - if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; - if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){ - /* Do not use an automatic index if the this loop is expected - ** to run less than 1.25 times. It is tempting to also exclude - ** automatic index usage on an outer loop, but sometimes an automatic - ** index is useful in the outer loop of a correlated subquery. */ - assert( 10==sqlite3LogEst(2) ); - continue; - } - - /* At this point, pWLoop is a candidate to be the next loop. - ** Compute its cost */ - rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); - rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted); - nOut = pFrom->nRow + pWLoop->nOut; - maskNew = pFrom->maskLoop | pWLoop->maskSelf; - if( isOrdered<0 ){ - isOrdered = wherePathSatisfiesOrderBy(pWInfo, - pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, - iLoop, pWLoop, &revMask); - }else{ - revMask = pFrom->revLoop; - } - if( isOrdered>=0 && isOrderedisOrdered^isOrdered)&0x80)==0" is equivalent - ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range - ** of legal values for isOrdered, -1..64. - */ - for(jj=0, pTo=aTo; jjmaskLoop==maskNew - && ((pTo->isOrdered^isOrdered)&0x80)==0 - ){ - testcase( jj==nTo-1 ); - break; - } - } - if( jj>=nTo ){ - /* None of the existing best-so-far paths match the candidate. */ - if( nTo>=mxChoice - && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted)) - ){ - /* The current candidate is no better than any of the mxChoice - ** paths currently in the best-so-far buffer. So discard - ** this candidate as not viable. */ -#ifdef WHERETRACE_ENABLED /* 0x4 */ - if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, - isOrdered>=0 ? isOrdered+'0' : '?'); - } -#endif - continue; - } - /* If we reach this points it means that the new candidate path - ** needs to be added to the set of best-so-far paths. */ - if( nTo=0 ? isOrdered+'0' : '?'); - } -#endif - }else{ - /* Control reaches here if best-so-far path pTo=aTo[jj] covers the - ** same set of loops and has the same isOrdered setting as the - ** candidate path. Check to see if the candidate should replace - ** pTo or if the candidate should be skipped. - ** - ** The conditional is an expanded vector comparison equivalent to: - ** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted) - */ - if( pTo->rCostrCost==rCost - && (pTo->nRownRow==nOut && pTo->rUnsorted<=rUnsorted) - ) - ) - ){ -#ifdef WHERETRACE_ENABLED /* 0x4 */ - if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf( - "Skip %s cost=%-3d,%3d,%3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, - isOrdered>=0 ? isOrdered+'0' : '?'); - sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); - } -#endif - /* Discard the candidate path from further consideration */ - testcase( pTo->rCost==rCost ); - continue; - } - testcase( pTo->rCost==rCost+1 ); - /* Control reaches here if the candidate path is better than the - ** pTo path. Replace pTo with the candidate. */ -#ifdef WHERETRACE_ENABLED /* 0x4 */ - if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf( - "Update %s cost=%-3d,%3d,%3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, - isOrdered>=0 ? isOrdered+'0' : '?'); - sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); - } -#endif - } - /* pWLoop is a winner. Add it to the set of best so far */ - pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf; - pTo->revLoop = revMask; - pTo->nRow = nOut; - pTo->rCost = rCost; - pTo->rUnsorted = rUnsorted; - pTo->isOrdered = isOrdered; - memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); - pTo->aLoop[iLoop] = pWLoop; - if( nTo>=mxChoice ){ - mxI = 0; - mxCost = aTo[0].rCost; - mxUnsorted = aTo[0].nRow; - for(jj=1, pTo=&aTo[1]; jjrCost>mxCost - || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted) - ){ - mxCost = pTo->rCost; - mxUnsorted = pTo->rUnsorted; - mxI = jj; - } - } - } - } + /* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this + ** case the purpose of this call is to estimate the number of rows returned + ** by the overall query. Once this estimate has been obtained, the caller + ** will invoke this function a second time, passing the estimate as the + ** nRowEst parameter. */ + if (pWInfo->pOrderBy==0 || nRowEst==0) { + nOrderBy = 0; + } else { + nOrderBy = pWInfo->pOrderBy->nExpr; } + /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ + nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; + nSpace += sizeof(LogEst) * nOrderBy; + pSpace = sqlite3DbMallocRawNN(db, nSpace); + if (pSpace==0) return SQLITE_NOMEM_BKPT; + aTo = (WherePath*)pSpace; + aFrom = aTo+mxChoice; + memset(aFrom, 0, sizeof(aFrom[0])); + pX = (WhereLoop**)(aFrom+mxChoice); + for (ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop) { + pFrom->aLoop = pX; + } + if (nOrderBy) { + /* If there is an ORDER BY clause and it is not being ignored, set up + ** space for the aSortCost[] array. Each element of the aSortCost array + ** is either zero - meaning it has not yet been initialized - or the + ** cost of sorting nRowEst rows of data where the first X terms of + ** the ORDER BY clause are already in order, where X is the array + ** index. */ + aSortCost = (LogEst*)pX; + memset(aSortCost, 0, sizeof(LogEst) * nOrderBy); + } + assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] ); + assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX ); + + /* Seed the search with a single WherePath containing zero WhereLoops. + ** + ** TUNING: Do not let the number of iterations go above 28. If the cost + ** of computing an automatic index is not paid back within the first 28 + ** rows, then do not use the automatic index. */ + aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28)); + nFrom = 1; + assert( aFrom[0].isOrdered==0 ); + if (nOrderBy) { + /* If nLoop is zero, then there are no FROM terms in the query. Since + ** in this case the query may return a maximum of one row, the results + ** are already in the requested order. Set isOrdered to nOrderBy to + ** indicate this. Or, if nLoop is greater than zero, set isOrdered to + ** -1, indicating that the result set may or may not be ordered, + ** depending on the loops added to the current plan. */ + aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy; + } + + /* Compute successively longer WherePaths using the previous generation + ** of WherePaths as the basis for the next. Keep track of the mxChoice + ** best paths at each generation */ + for (iLoop=0; iLooppLoops; pWLoop; pWLoop=pWLoop->pNextLoop) { + LogEst nOut; /* Rows visited by (pFrom+pWLoop) */ + LogEst rCost; /* Cost of path (pFrom+pWLoop) */ + LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */ + i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */ + Bitmask maskNew; /* Mask of src visited by (..) */ + Bitmask revMask = 0; /* Mask of rev-order loops for (..) */ + + if ((pWLoop->prereq & ~pFrom->maskLoop)!=0) continue; + if ((pWLoop->maskSelf & pFrom->maskLoop)!=0) continue; + if ((pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3) { + /* Do not use an automatic index if the this loop is expected + ** to run less than 1.25 times. It is tempting to also exclude + ** automatic index usage on an outer loop, but sometimes an automatic + ** index is useful in the outer loop of a correlated subquery. */ + assert( 10==sqlite3LogEst(2)); + continue; + } + + /* At this point, pWLoop is a candidate to be the next loop. + ** Compute its cost */ + rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); + rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted); + nOut = pFrom->nRow + pWLoop->nOut; + maskNew = pFrom->maskLoop | pWLoop->maskSelf; + if (isOrdered<0) { + isOrdered = wherePathSatisfiesOrderBy(pWInfo, + pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, + iLoop, pWLoop, &revMask); + } else { + revMask = pFrom->revLoop; + } + if (isOrdered>=0 && isOrderedisOrdered^isOrdered)&0x80)==0" is equivalent + ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range + ** of legal values for isOrdered, -1..64. + */ + for (jj=0, pTo=aTo; jjmaskLoop==maskNew + && ((pTo->isOrdered^isOrdered)&0x80)==0 + ) { + testcase( jj==nTo-1 ); + break; + } + } + if (jj>=nTo) { + /* None of the existing best-so-far paths match the candidate. */ + if (nTo>=mxChoice + && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted)) + ) { + /* The current candidate is no better than any of the mxChoice + ** paths currently in the best-so-far buffer. So discard + ** this candidate as not viable. */ +#ifdef WHERETRACE_ENABLED /* 0x4 */ + if (sqlite3WhereTrace&0x4) { + sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, + isOrdered>=0 ? isOrdered+'0' : '?'); + } +#endif + continue; + } + /* If we reach this points it means that the new candidate path + ** needs to be added to the set of best-so-far paths. */ + if (nTo=0 ? isOrdered+'0' : '?'); + } +#endif + } else { + /* Control reaches here if best-so-far path pTo=aTo[jj] covers the + ** same set of loops and has the same isOrdered setting as the + ** candidate path. Check to see if the candidate should replace + ** pTo or if the candidate should be skipped. + ** + ** The conditional is an expanded vector comparison equivalent to: + ** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted) + */ + if (pTo->rCostrCost==rCost + && (pTo->nRownRow==nOut && pTo->rUnsorted<=rUnsorted) + ) + ) + ) { +#ifdef WHERETRACE_ENABLED /* 0x4 */ + if (sqlite3WhereTrace&0x4) { + sqlite3DebugPrintf( + "Skip %s cost=%-3d,%3d,%3d order=%c", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, + isOrdered>=0 ? isOrdered+'0' : '?'); + sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n", + wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, + pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); + } +#endif + /* Discard the candidate path from further consideration */ + testcase( pTo->rCost==rCost ); + continue; + } + testcase( pTo->rCost==rCost+1 ); + /* Control reaches here if the candidate path is better than the + ** pTo path. Replace pTo with the candidate. */ +#ifdef WHERETRACE_ENABLED /* 0x4 */ + if (sqlite3WhereTrace&0x4) { + sqlite3DebugPrintf( + "Update %s cost=%-3d,%3d,%3d order=%c", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, + isOrdered>=0 ? isOrdered+'0' : '?'); + sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n", + wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, + pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); + } +#endif + } + /* pWLoop is a winner. Add it to the set of best so far */ + pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf; + pTo->revLoop = revMask; + pTo->nRow = nOut; + pTo->rCost = rCost; + pTo->rUnsorted = rUnsorted; + pTo->isOrdered = isOrdered; + memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); + pTo->aLoop[iLoop] = pWLoop; + if (nTo>=mxChoice) { + mxI = 0; + mxCost = aTo[0].rCost; + mxUnsorted = aTo[0].nRow; + for (jj=1, pTo=&aTo[1]; jjrCost>mxCost + || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted) + ) { + mxCost = pTo->rCost; + mxUnsorted = pTo->rUnsorted; + mxI = jj; + } + } + } + } + } + #ifdef WHERETRACE_ENABLED /* >=2 */ - if( sqlite3WhereTrace & 0x02 ){ - sqlite3DebugPrintf("---- after round %d ----\n", iLoop); - for(ii=0, pTo=aTo; iirCost, pTo->nRow, - pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?'); - if( pTo->isOrdered>0 ){ - sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop); - }else{ - sqlite3DebugPrintf("\n"); + if (sqlite3WhereTrace & 0x02) { + sqlite3DebugPrintf("---- after round %d ----\n", iLoop); + for (ii=0, pTo=aTo; iirCost, pTo->nRow, + pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?'); + if (pTo->isOrdered>0) { + sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop); + } else { + sqlite3DebugPrintf("\n"); + } + } } - } - } #endif - /* Swap the roles of aFrom and aTo for the next generation */ - pFrom = aTo; - aTo = aFrom; - aFrom = pFrom; - nFrom = nTo; - } - - if( nFrom==0 ){ - sqlite3ErrorMsg(pParse, "no query solution"); - sqlite3DbFreeNN(db, pSpace); - return SQLITE_ERROR; - } - - /* Find the lowest cost path. pFrom will be left pointing to that path */ - pFrom = aFrom; - for(ii=1; iirCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; - } - assert( pWInfo->nLevel==nLoop ); - /* Load the lowest cost path into pWInfo */ - for(iLoop=0; iLoopa + iLoop; - pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop]; - pLevel->iFrom = pWLoop->iTab; - pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor; - } - if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 - && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 - && pWInfo->eDistinct==WHERE_DISTINCT_NOOP - && nRowEst - ){ - Bitmask notUsed; - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom, - WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); - if( rc==pWInfo->pResultSet->nExpr ){ - pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; + /* Swap the roles of aFrom and aTo for the next generation */ + pFrom = aTo; + aTo = aFrom; + aFrom = pFrom; + nFrom = nTo; } - } - pWInfo->bOrderedInnerLoop = 0; - if( pWInfo->pOrderBy ){ - if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ - if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ - pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; - } - }else{ - pWInfo->nOBSat = pFrom->isOrdered; - pWInfo->revMask = pFrom->revLoop; - if( pWInfo->nOBSat<=0 ){ - pWInfo->nOBSat = 0; - if( nLoop>0 ){ - u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; - if( (wsFlags & WHERE_ONEROW)==0 - && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) - ){ - Bitmask m = 0; - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, - WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); - testcase( wsFlags & WHERE_IPK ); - testcase( wsFlags & WHERE_COLUMN_IN ); - if( rc==pWInfo->pOrderBy->nExpr ){ - pWInfo->bOrderedInnerLoop = 1; - pWInfo->revMask = m; - } - } + + if (nFrom==0) { + sqlite3ErrorMsg(pParse, "no query solution"); + sqlite3DbFreeNN(db, pSpace); + return SQLITE_ERROR; + } + + /* Find the lowest cost path. pFrom will be left pointing to that path */ + pFrom = aFrom; + for (ii=1; iirCost>aFrom[ii].rCost) pFrom = &aFrom[ii]; + } + assert( pWInfo->nLevel==nLoop ); + /* Load the lowest cost path into pWInfo */ + for (iLoop=0; iLoopa + iLoop; + pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop]; + pLevel->iFrom = pWLoop->iTab; + pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor; + } + if ((pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 + && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 + && pWInfo->eDistinct==WHERE_DISTINCT_NOOP + && nRowEst + ) { + Bitmask notUsed; + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom, + WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); + if (rc==pWInfo->pResultSet->nExpr) { + pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } - } } - if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) - && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 - ){ - Bitmask revMask = 0; - int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, - pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &revMask - ); - assert( pWInfo->sorted==0 ); - if( nOrder==pWInfo->pOrderBy->nExpr ){ - pWInfo->sorted = 1; - pWInfo->revMask = revMask; - } + pWInfo->bOrderedInnerLoop = 0; + if (pWInfo->pOrderBy) { + if (pWInfo->wctrlFlags & WHERE_DISTINCTBY) { + if (pFrom->isOrdered==pWInfo->pOrderBy->nExpr) { + pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; + } + } else { + pWInfo->nOBSat = pFrom->isOrdered; + pWInfo->revMask = pFrom->revLoop; + if (pWInfo->nOBSat<=0) { + pWInfo->nOBSat = 0; + if (nLoop>0) { + u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; + if ((wsFlags & WHERE_ONEROW)==0 + && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) + ) { + Bitmask m = 0; + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, + WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); + testcase( wsFlags & WHERE_IPK ); + testcase( wsFlags & WHERE_COLUMN_IN ); + if (rc==pWInfo->pOrderBy->nExpr) { + pWInfo->bOrderedInnerLoop = 1; + pWInfo->revMask = m; + } + } + } + } + } + if ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP) + && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 + ) { + Bitmask revMask = 0; + int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, + pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &revMask + ); + assert( pWInfo->sorted==0 ); + if (nOrder==pWInfo->pOrderBy->nExpr) { + pWInfo->sorted = 1; + pWInfo->revMask = revMask; + } + } } - } - pWInfo->nRowOut = pFrom->nRow; + pWInfo->nRowOut = pFrom->nRow; - /* Free temporary memory and return success */ - sqlite3DbFreeNN(db, pSpace); - return SQLITE_OK; + /* Free temporary memory and return success */ + sqlite3DbFreeNN(db, pSpace); + return SQLITE_OK; } /* @@ -4384,112 +4384,112 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ** times for the common case. ** ** Return non-zero on success, if this query can be handled by this -** no-frills query planner. Return zero if this query needs the +** no-frills query planner. Return zero if this query needs the ** general-purpose query planner. */ static int whereShortCut(WhereLoopBuilder *pBuilder){ - WhereInfo *pWInfo; - struct SrcList_item *pItem; - WhereClause *pWC; - WhereTerm *pTerm; - WhereLoop *pLoop; - int iCur; - int j; - Table *pTab; - Index *pIdx; + WhereInfo *pWInfo; + struct SrcList_item *pItem; + WhereClause *pWC; + WhereTerm *pTerm; + WhereLoop *pLoop; + int iCur; + int j; + Table *pTab; + Index *pIdx; - pWInfo = pBuilder->pWInfo; - if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0; - assert( pWInfo->pTabList->nSrc>=1 ); - pItem = pWInfo->pTabList->a; - pTab = pItem->pTab; - if( IsVirtual(pTab) ) return 0; - if( pItem->fg.isIndexedBy ) return 0; - iCur = pItem->iCursor; - pWC = &pWInfo->sWC; - pLoop = pBuilder->pNew; - pLoop->wsFlags = 0; - pLoop->nSkip = 0; - pTerm = sqlite3WhereFindTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0); - if( pTerm ){ - testcase( pTerm->eOperator & WO_IS ); - pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW; - pLoop->aLTerm[0] = pTerm; - pLoop->nLTerm = 1; - pLoop->u.btree.nEq = 1; - /* TUNING: Cost of a rowid lookup is 10 */ - pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */ - }else{ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int opMask; - assert( pLoop->aLTermSpace==pLoop->aLTerm ); - if( !IsUniqueIndex(pIdx) - || pIdx->pPartIdxWhere!=0 - || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) - ) continue; - opMask = pIdx->uniqNotNull ? (WO_EQ|WO_IS) : WO_EQ; - for(j=0; jnKeyCol; j++){ - pTerm = sqlite3WhereFindTerm(pWC, iCur, j, 0, opMask, pIdx); - if( pTerm==0 ) break; + pWInfo = pBuilder->pWInfo; + if (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) return 0; + assert( pWInfo->pTabList->nSrc>=1 ); + pItem = pWInfo->pTabList->a; + pTab = pItem->pTab; + if (IsVirtual(pTab)) return 0; + if (pItem->fg.isIndexedBy) return 0; + iCur = pItem->iCursor; + pWC = &pWInfo->sWC; + pLoop = pBuilder->pNew; + pLoop->wsFlags = 0; + pLoop->nSkip = 0; + pTerm = sqlite3WhereFindTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0); + if (pTerm) { testcase( pTerm->eOperator & WO_IS ); - pLoop->aLTerm[j] = pTerm; - } - if( j!=pIdx->nKeyCol ) continue; - pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; - if( pIdx->isCovering || (pItem->colUsed & pIdx->colNotIdxed)==0 ){ - pLoop->wsFlags |= WHERE_IDX_ONLY; - } - pLoop->nLTerm = j; - pLoop->u.btree.nEq = j; - pLoop->u.btree.pIndex = pIdx; - /* TUNING: Cost of a unique index lookup is 15 */ - pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */ - break; - } - } - if( pLoop->wsFlags ){ - pLoop->nOut = (LogEst)1; - pWInfo->a[0].pWLoop = pLoop; - assert( pWInfo->sMaskSet.n==1 && iCur==pWInfo->sMaskSet.ix[0] ); - pLoop->maskSelf = 1; /* sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); */ - pWInfo->a[0].iTabCur = iCur; - pWInfo->nRowOut = 1; - if( pWInfo->pOrderBy ) pWInfo->nOBSat = pWInfo->pOrderBy->nExpr; - if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; + pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW; + pLoop->aLTerm[0] = pTerm; + pLoop->nLTerm = 1; + pLoop->u.btree.nEq = 1; + /* TUNING: Cost of a rowid lookup is 10 */ + pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */ + } else { + for (pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext) { + int opMask; + assert( pLoop->aLTermSpace==pLoop->aLTerm ); + if (!IsUniqueIndex(pIdx) + || pIdx->pPartIdxWhere!=0 + || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) + ) continue; + opMask = pIdx->uniqNotNull ? (WO_EQ|WO_IS) : WO_EQ; + for (j=0; jnKeyCol; j++) { + pTerm = sqlite3WhereFindTerm(pWC, iCur, j, 0, opMask, pIdx); + if (pTerm==0) break; + testcase( pTerm->eOperator & WO_IS ); + pLoop->aLTerm[j] = pTerm; + } + if (j!=pIdx->nKeyCol) continue; + pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; + if (pIdx->isCovering || (pItem->colUsed & pIdx->colNotIdxed)==0) { + pLoop->wsFlags |= WHERE_IDX_ONLY; + } + pLoop->nLTerm = j; + pLoop->u.btree.nEq = j; + pLoop->u.btree.pIndex = pIdx; + /* TUNING: Cost of a unique index lookup is 15 */ + pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */ + break; + } } + if (pLoop->wsFlags) { + pLoop->nOut = (LogEst)1; + pWInfo->a[0].pWLoop = pLoop; + assert( pWInfo->sMaskSet.n==1 && iCur==pWInfo->sMaskSet.ix[0] ); + pLoop->maskSelf = 1; /* sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); */ + pWInfo->a[0].iTabCur = iCur; + pWInfo->nRowOut = 1; + if (pWInfo->pOrderBy) pWInfo->nOBSat = pWInfo->pOrderBy->nExpr; + if (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) { + pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; + } #ifdef SQLITE_DEBUG - pLoop->cId = '0'; + pLoop->cId = '0'; #endif - return 1; - } - return 0; + return 1; + } + return 0; } /* ** Helper function for exprIsDeterministic(). */ static int exprNodeIsDeterministic(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_ConstFunc)==0 ){ - pWalker->eCode = 0; - return WRC_Abort; - } - return WRC_Continue; + if (pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_ConstFunc)==0) { + pWalker->eCode = 0; + return WRC_Abort; + } + return WRC_Continue; } /* -** Return true if the expression contains no non-deterministic SQL -** functions. Do not consider non-deterministic SQL functions that are +** Return true if the expression contains no non-deterministic SQL +** functions. Do not consider non-deterministic SQL functions that are ** part of sub-select statements. */ static int exprIsDeterministic(Expr *p){ - Walker w; - memset(&w, 0, sizeof(w)); - w.eCode = 1; - w.xExprCallback = exprNodeIsDeterministic; - w.xSelectCallback = sqlite3SelectWalkFail; - sqlite3WalkExpr(&w, p); - return w.eCode; + Walker w; + memset(&w, 0, sizeof(w)); + w.eCode = 1; + w.xExprCallback = exprNodeIsDeterministic; + w.xSelectCallback = sqlite3SelectWalkFail; + sqlite3WalkExpr(&w, p); + return w.eCode; } /* @@ -4572,7 +4572,7 @@ static int exprIsDeterministic(Expr *p){ ** if there is one. If there is no ORDER BY clause or if this routine ** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. ** -** The iIdxCur parameter is the cursor number of an index. If +** The iIdxCur parameter is the cursor number of an index. If ** WHERE_OR_SUBCLAUSE is set, iIdxCur is the cursor number of an index ** to use for OR clause processing. The WHERE clause should use this ** specific cursor. If WHERE_ONEPASS_DESIRED is set, then iIdxCur is @@ -4581,550 +4581,550 @@ static int exprIsDeterministic(Expr *p){ ** used. */ WhereInfo *sqlite3WhereBegin( - Parse *pParse, /* The parser context */ - SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ - Expr *pWhere, /* The WHERE clause */ - ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ - ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ - u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ - int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number + Parse *pParse, /* The parser context */ + SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ + Expr *pWhere, /* The WHERE clause */ + ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ + ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ + u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ + int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number ** If WHERE_USE_LIMIT, then the limit amount */ -){ - int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ - int nTabList; /* Number of elements in pTabList */ - WhereInfo *pWInfo; /* Will become the return value of this function */ - Vdbe *v = pParse->pVdbe; /* The virtual database engine */ - Bitmask notReady; /* Cursors that are not yet positioned */ - WhereLoopBuilder sWLB; /* The WhereLoop builder */ - WhereMaskSet *pMaskSet; /* The expression mask set */ - WhereLevel *pLevel; /* A single level in pWInfo->a[] */ - WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ - int ii; /* Loop counter */ - sqlite3 *db; /* Database connection */ - int rc; /* Return code */ - u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */ + ){ + int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ + int nTabList; /* Number of elements in pTabList */ + WhereInfo *pWInfo; /* Will become the return value of this function */ + Vdbe *v = pParse->pVdbe; /* The virtual database engine */ + Bitmask notReady; /* Cursors that are not yet positioned */ + WhereLoopBuilder sWLB; /* The WhereLoop builder */ + WhereMaskSet *pMaskSet; /* The expression mask set */ + WhereLevel *pLevel; /* A single level in pWInfo->a[] */ + WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ + int ii; /* Loop counter */ + sqlite3 *db; /* Database connection */ + int rc; /* Return code */ + u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */ - assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( - (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 - && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - )); + assert((wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( + (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 + && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 + )); - /* Only one of WHERE_OR_SUBCLAUSE or WHERE_USE_LIMIT */ - assert( (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - || (wctrlFlags & WHERE_USE_LIMIT)==0 ); + /* Only one of WHERE_OR_SUBCLAUSE or WHERE_USE_LIMIT */ + assert((wctrlFlags & WHERE_OR_SUBCLAUSE)==0 + || (wctrlFlags & WHERE_USE_LIMIT)==0 ); - /* Variable initialization */ - db = pParse->db; - memset(&sWLB, 0, sizeof(sWLB)); + /* Variable initialization */ + db = pParse->db; + memset(&sWLB, 0, sizeof(sWLB)); - /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ - testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); - if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; - sWLB.pOrderBy = pOrderBy; + /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ + testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); + if (pOrderBy && pOrderBy->nExpr>=BMS) pOrderBy = 0; + sWLB.pOrderBy = pOrderBy; - /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via - ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ - if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ - wctrlFlags &= ~WHERE_WANT_DISTINCT; - } - - /* The number of tables in the FROM clause is limited by the number of - ** bits in a Bitmask - */ - testcase( pTabList->nSrc==BMS ); - if( pTabList->nSrc>BMS ){ - sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); - return 0; - } - - /* This function normally generates a nested loop for all tables in - ** pTabList. But if the WHERE_OR_SUBCLAUSE flag is set, then we should - ** only generate code for the first table in pTabList and assume that - ** any cursors associated with subsequent tables are uninitialized. - */ - nTabList = (wctrlFlags & WHERE_OR_SUBCLAUSE) ? 1 : pTabList->nSrc; - - /* Allocate and initialize the WhereInfo structure that will become the - ** return value. A single allocation is used to store the WhereInfo - ** struct, the contents of WhereInfo.a[], the WhereClause structure - ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte - ** field (type Bitmask) it must be aligned on an 8-byte boundary on - ** some architectures. Hence the ROUND8() below. - */ - nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); - pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); - if( db->mallocFailed ){ - sqlite3DbFree(db, pWInfo); - pWInfo = 0; - goto whereBeginError; - } - pWInfo->pParse = pParse; - pWInfo->pTabList = pTabList; - pWInfo->pOrderBy = pOrderBy; - pWInfo->pWhere = pWhere; - pWInfo->pResultSet = pResultSet; - pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; - pWInfo->nLevel = nTabList; - pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse); - pWInfo->wctrlFlags = wctrlFlags; - pWInfo->iLimit = iAuxArg; - pWInfo->savedNQueryLoop = pParse->nQueryLoop; - memset(&pWInfo->nOBSat, 0, - offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); - memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); - assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ - pMaskSet = &pWInfo->sMaskSet; - sWLB.pWInfo = pWInfo; - sWLB.pWC = &pWInfo->sWC; - sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); - assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) ); - whereLoopInit(sWLB.pNew); -#ifdef SQLITE_DEBUG - sWLB.pNew->cId = '*'; -#endif - - /* Split the WHERE clause into separate subexpressions where each - ** subexpression is separated by an AND operator. - */ - initMaskSet(pMaskSet); - sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); - sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); - - /* Special case: No FROM clause - */ - if( nTabList==0 ){ - if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr; - if( wctrlFlags & WHERE_WANT_DISTINCT ){ - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; + /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via + ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ + if (OptimizationDisabled(db, SQLITE_DistinctOpt)) { + wctrlFlags &= ~WHERE_WANT_DISTINCT; } - ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); - }else{ - /* Assign a bit from the bitmask to every term in the FROM clause. - ** - ** The N-th term of the FROM clause is assigned a bitmask of 1<nSrc tables in - ** pTabList, not just the first nTabList tables. nTabList is normally - ** equal to pTabList->nSrc but might be shortened to 1 if the - ** WHERE_OR_SUBCLAUSE flag is set. + + /* The number of tables in the FROM clause is limited by the number of + ** bits in a Bitmask */ - ii = 0; - do{ - createMask(pMaskSet, pTabList->a[ii].iCursor); - sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); - }while( (++ii)nSrc ); + testcase( pTabList->nSrc==BMS ); + if (pTabList->nSrc>BMS) { + sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); + return 0; + } + + /* This function normally generates a nested loop for all tables in + ** pTabList. But if the WHERE_OR_SUBCLAUSE flag is set, then we should + ** only generate code for the first table in pTabList and assume that + ** any cursors associated with subsequent tables are uninitialized. + */ + nTabList = (wctrlFlags & WHERE_OR_SUBCLAUSE) ? 1 : pTabList->nSrc; + + /* Allocate and initialize the WhereInfo structure that will become the + ** return value. A single allocation is used to store the WhereInfo + ** struct, the contents of WhereInfo.a[], the WhereClause structure + ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte + ** field (type Bitmask) it must be aligned on an 8-byte boundary on + ** some architectures. Hence the ROUND8() below. + */ + nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); + pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); + if (db->mallocFailed) { + sqlite3DbFree(db, pWInfo); + pWInfo = 0; + goto whereBeginError; + } + pWInfo->pParse = pParse; + pWInfo->pTabList = pTabList; + pWInfo->pOrderBy = pOrderBy; + pWInfo->pWhere = pWhere; + pWInfo->pResultSet = pResultSet; + pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; + pWInfo->nLevel = nTabList; + pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse); + pWInfo->wctrlFlags = wctrlFlags; + pWInfo->iLimit = iAuxArg; + pWInfo->savedNQueryLoop = pParse->nQueryLoop; + memset(&pWInfo->nOBSat, 0, + offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); + memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); + assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ + pMaskSet = &pWInfo->sMaskSet; + sWLB.pWInfo = pWInfo; + sWLB.pWC = &pWInfo->sWC; + sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); + assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew)); + whereLoopInit(sWLB.pNew); +#ifdef SQLITE_DEBUG + sWLB.pNew->cId = '*'; +#endif + + /* Split the WHERE clause into separate subexpressions where each + ** subexpression is separated by an AND operator. + */ + initMaskSet(pMaskSet); + sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); + sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); + + /* Special case: No FROM clause + */ + if (nTabList==0) { + if (pOrderBy) pWInfo->nOBSat = pOrderBy->nExpr; + if (wctrlFlags & WHERE_WANT_DISTINCT) { + pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; + } + ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); + } else { + /* Assign a bit from the bitmask to every term in the FROM clause. + ** + ** The N-th term of the FROM clause is assigned a bitmask of 1<nSrc tables in + ** pTabList, not just the first nTabList tables. nTabList is normally + ** equal to pTabList->nSrc but might be shortened to 1 if the + ** WHERE_OR_SUBCLAUSE flag is set. + */ + ii = 0; + do{ + createMask(pMaskSet, pTabList->a[ii].iCursor); + sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); + }while ((++ii)nSrc); #ifdef SQLITE_DEBUG - { - Bitmask mx = 0; - for(ii=0; iinSrc; ii++){ - Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); - assert( m>=mx ); - mx = m; - } - } - #endif - } - - /* Analyze all of the subexpressions. */ - sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); - if( db->mallocFailed ) goto whereBeginError; - - /* Special case: WHERE terms that do not refer to any tables in the join - ** (constant expressions). Evaluate each such term, and jump over all the - ** generated code if the result is not true. - ** - ** Do not do this if the expression contains non-deterministic functions - ** that are not within a sub-select. This is not strictly required, but - ** preserves SQLite's legacy behaviour in the following two cases: - ** - ** FROM ... WHERE random()>0; -- eval random() once per row - ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall - */ - for(ii=0; iinTerm; ii++){ - WhereTerm *pT = &sWLB.pWC->a[ii]; - if( pT->wtFlags & TERM_VIRTUAL ) continue; - if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ - sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); - pT->wtFlags |= TERM_CODED; - } - } - - if( wctrlFlags & WHERE_WANT_DISTINCT ){ - if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ - /* The DISTINCT marking is pointless. Ignore it. */ - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; - }else if( pOrderBy==0 ){ - /* Try to ORDER BY the result set to make distinct processing easier */ - pWInfo->wctrlFlags |= WHERE_DISTINCTBY; - pWInfo->pOrderBy = pResultSet; - } - } - - /* Construct the WhereLoop objects */ -#if defined(WHERETRACE_ENABLED) - if( sqlite3WhereTrace & 0xffff ){ - sqlite3DebugPrintf("*** Optimizer Start *** (wctrlFlags: 0x%x",wctrlFlags); - if( wctrlFlags & WHERE_USE_LIMIT ){ - sqlite3DebugPrintf(", limit: %d", iAuxArg); - } - sqlite3DebugPrintf(")\n"); - if( sqlite3WhereTrace & 0x100 ){ - Select sSelect; - memset(&sSelect, 0, sizeof(sSelect)); - sSelect.selFlags = SF_WhereBegin; - sSelect.pSrc = pTabList; - sSelect.pWhere = pWhere; - sSelect.pOrderBy = pOrderBy; - sSelect.pEList = pResultSet; - sqlite3TreeViewSelect(0, &sSelect, 0); - } - } - if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ - sqlite3WhereClausePrint(sWLB.pWC); - } -#endif - - if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ - rc = whereLoopAddAll(&sWLB); - if( rc ) goto whereBeginError; - -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */ - WhereLoop *p; - int i; - static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" - "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; - for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ - p->cId = zLabel[i%(sizeof(zLabel)-1)]; - whereLoopPrint(p, sWLB.pWC); - } - } -#endif - - wherePathSolver(pWInfo, 0); - if( db->mallocFailed ) goto whereBeginError; - if( pWInfo->pOrderBy ){ - wherePathSolver(pWInfo, pWInfo->nRowOut+1); - if( db->mallocFailed ) goto whereBeginError; - } - } - if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ - pWInfo->revMask = ALLBITS; - } - if( pParse->nErr || NEVER(db->mallocFailed) ){ - goto whereBeginError; - } -#ifdef WHERETRACE_ENABLED - if( sqlite3WhereTrace ){ - sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); - if( pWInfo->nOBSat>0 ){ - sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); - } - switch( pWInfo->eDistinct ){ - case WHERE_DISTINCT_UNIQUE: { - sqlite3DebugPrintf(" DISTINCT=unique"); - break; - } - case WHERE_DISTINCT_ORDERED: { - sqlite3DebugPrintf(" DISTINCT=ordered"); - break; - } - case WHERE_DISTINCT_UNORDERED: { - sqlite3DebugPrintf(" DISTINCT=unordered"); - break; - } - } - sqlite3DebugPrintf("\n"); - for(ii=0; iinLevel; ii++){ - whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC); - } - } -#endif - - /* Attempt to omit tables from the join that do not affect the result. - ** For a table to not affect the result, the following must be true: - ** - ** 1) The query must not be an aggregate. - ** 2) The table must be the RHS of a LEFT JOIN. - ** 3) Either the query must be DISTINCT, or else the ON or USING clause - ** must contain a constraint that limits the scan of the table to - ** at most a single row. - ** 4) The table must not be referenced by any part of the query apart - ** from its own USING or ON clause. - ** - ** For example, given: - ** - ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); - ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); - ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); - ** - ** then table t2 can be omitted from the following: - ** - ** SELECT v1, v3 FROM t1 - ** LEFT JOIN t2 USING (t1.ipk=t2.ipk) - ** LEFT JOIN t3 USING (t1.ipk=t3.ipk) - ** - ** or from: - ** - ** SELECT DISTINCT v1, v3 FROM t1 - ** LEFT JOIN t2 - ** LEFT JOIN t3 USING (t1.ipk=t3.ipk) - */ - notReady = ~(Bitmask)0; - if( pWInfo->nLevel>=2 - && pResultSet!=0 /* guarantees condition (1) above */ - && OptimizationEnabled(db, SQLITE_OmitNoopJoin) - ){ - int i; - Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); - if( sWLB.pOrderBy ){ - tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); - } - for(i=pWInfo->nLevel-1; i>=1; i--){ - WhereTerm *pTerm, *pEnd; - struct SrcList_item *pItem; - pLoop = pWInfo->a[i].pWLoop; - pItem = &pWInfo->pTabList->a[pLoop->iTab]; - if( (pItem->fg.jointype & JT_LEFT)==0 ) continue; - if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 - && (pLoop->wsFlags & WHERE_ONEROW)==0 - ){ - continue; - } - if( (tabUsed & pLoop->maskSelf)!=0 ) continue; - pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; - for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 ){ - if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - || pTerm->pExpr->iRightJoinTable!=pItem->iCursor - ){ - break; - } - } - } - if( pTerm drop loop %c not used\n", pLoop->cId)); - notReady &= ~pLoop->maskSelf; - for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 ){ - pTerm->wtFlags |= TERM_CODED; - } - } - if( i!=pWInfo->nLevel-1 ){ - int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); - memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); - } - pWInfo->nLevel--; - nTabList--; - } - } - WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); - pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; - - /* If the caller is an UPDATE or DELETE statement that is requesting - ** to use a one-pass algorithm, determine if this is appropriate. - ** - ** A one-pass approach can be used if the caller has requested one - ** and either (a) the scan visits at most one row or (b) each - ** of the following are true: - ** - ** * the caller has indicated that a one-pass approach can be used - ** with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and - ** * the table is not a virtual table, and - ** * either the scan does not use the OR optimization or the caller - ** is a DELETE operation (WHERE_DUPLICATES_OK is only specified - ** for DELETE). - ** - ** The last qualification is because an UPDATE statement uses - ** WhereInfo.aiCurOnePass[1] to determine whether or not it really can - ** use a one-pass approach, and this is not set accurately for scans - ** that use the OR optimization. - */ - assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); - if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ - int wsFlags = pWInfo->a[0].pWLoop->wsFlags; - int bOnerow = (wsFlags & WHERE_ONEROW)!=0; - assert( !(wsFlags & WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pTab) ); - if( bOnerow || ( - 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) - && !IsVirtual(pTabList->a[0].pTab) - && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) - )){ - pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; - if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ - if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ - bFordelete = OPFLAG_FORDELETE; - } - pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY); - } - } - } - - /* Open all tables in the pTabList and any indices selected for - ** searching those tables. - */ - for(ii=0, pLevel=pWInfo->a; iia[pLevel->iFrom]; - pTab = pTabItem->pTab; - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pLoop = pLevel->pWLoop; - if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ - /* Do nothing */ - }else -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ - const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); - int iCur = pTabItem->iCursor; - sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); - }else if( IsVirtual(pTab) ){ - /* noop */ - }else -#endif - if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 - && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){ - int op = OP_OpenRead; - if( pWInfo->eOnePass!=ONEPASS_OFF ){ - op = OP_OpenWrite; - pWInfo->aiCurOnePass[0] = pTabItem->iCursor; - }; - sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); - assert( pTabItem->iCursor==pLevel->iTabCur ); - testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 ); - testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS ); - if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nColcolUsed; - int n = 0; - for(; b; b=b>>1, n++){} - sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32); - assert( n<=pTab->nCol ); - } -#ifdef SQLITE_ENABLE_CURSOR_HINTS - if( pLoop->u.btree.pIndex!=0 ){ - sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete); - }else -#endif - { - sqlite3VdbeChangeP5(v, bFordelete); - } -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK - sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0, - (const u8*)&pTabItem->colUsed, P4_INT64); -#endif - }else{ - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - } - if( pLoop->wsFlags & WHERE_INDEXED ){ - Index *pIx = pLoop->u.btree.pIndex; - int iIndexCur; - int op = OP_OpenRead; - /* iAuxArg is always set to a positive value if ONEPASS is possible */ - assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); - if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx) - && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 - ){ - /* This is one term of an OR-optimization using the PRIMARY KEY of a - ** WITHOUT ROWID table. No need for a separate index */ - iIndexCur = pLevel->iTabCur; - op = 0; - }else if( pWInfo->eOnePass!=ONEPASS_OFF ){ - Index *pJ = pTabItem->pTab->pIndex; - iIndexCur = iAuxArg; - assert( wctrlFlags & WHERE_ONEPASS_DESIRED ); - while( ALWAYS(pJ) && pJ!=pIx ){ - iIndexCur++; - pJ = pJ->pNext; - } - op = OP_OpenWrite; - pWInfo->aiCurOnePass[1] = iIndexCur; - }else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){ - iIndexCur = iAuxArg; - op = OP_ReopenIdx; - }else{ - iIndexCur = pParse->nTab++; - } - pLevel->iIdxCur = iIndexCur; - assert( pIx->pSchema==pTab->pSchema ); - assert( iIndexCur>=0 ); - if( op ){ - sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); - sqlite3VdbeSetP4KeyInfo(pParse, pIx); - if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0 - && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 - && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 - && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED - ){ - sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */ - } - VdbeComment((v, "%s", pIx->zName)); -#ifdef SQLITE_ENABLE_COLUMN_USED_MASK { - u64 colUsed = 0; - int ii, jj; - for(ii=0; iinColumn; ii++){ - jj = pIx->aiColumn[ii]; - if( jj<0 ) continue; - if( jj>63 ) jj = 63; - if( (pTabItem->colUsed & MASKBIT(jj))==0 ) continue; - colUsed |= ((u64)1)<<(ii<63 ? ii : 63); - } - sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0, - (u8*)&colUsed, P4_INT64); + Bitmask mx = 0; + for (ii=0; iinSrc; ii++) { + Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); + assert( m>=mx ); + mx = m; + } } -#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */ - } + #endif } - if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); - } - pWInfo->iTop = sqlite3VdbeCurrentAddr(v); - if( db->mallocFailed ) goto whereBeginError; - /* Generate the code to do the search. Each iteration of the for - ** loop below generates code for a single nested loop of the VM - ** program. - */ - for(ii=0; iia[ii]; - wsFlags = pLevel->pWLoop->wsFlags; -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX - if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ - constructAutomaticIndex(pParse, &pWInfo->sWC, - &pTabList->a[pLevel->iFrom], notReady, pLevel); - if( db->mallocFailed ) goto whereBeginError; + /* Analyze all of the subexpressions. */ + sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); + if (db->mallocFailed) goto whereBeginError; + + /* Special case: WHERE terms that do not refer to any tables in the join + ** (constant expressions). Evaluate each such term, and jump over all the + ** generated code if the result is not true. + ** + ** Do not do this if the expression contains non-deterministic functions + ** that are not within a sub-select. This is not strictly required, but + ** preserves SQLite's legacy behaviour in the following two cases: + ** + ** FROM ... WHERE random()>0; -- eval random() once per row + ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall + */ + for (ii=0; iinTerm; ii++) { + WhereTerm *pT = &sWLB.pWC->a[ii]; + if (pT->wtFlags & TERM_VIRTUAL) continue; + if (pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr))) { + sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); + pT->wtFlags |= TERM_CODED; + } + } + + if (wctrlFlags & WHERE_WANT_DISTINCT) { + if (isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet)) { + /* The DISTINCT marking is pointless. Ignore it. */ + pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; + } else if (pOrderBy==0) { + /* Try to ORDER BY the result set to make distinct processing easier */ + pWInfo->wctrlFlags |= WHERE_DISTINCTBY; + pWInfo->pOrderBy = pResultSet; + } + } + + /* Construct the WhereLoop objects */ +#if defined(WHERETRACE_ENABLED) + if (sqlite3WhereTrace & 0xffff) { + sqlite3DebugPrintf("*** Optimizer Start *** (wctrlFlags: 0x%x",wctrlFlags); + if (wctrlFlags & WHERE_USE_LIMIT) { + sqlite3DebugPrintf(", limit: %d", iAuxArg); + } + sqlite3DebugPrintf(")\n"); + if (sqlite3WhereTrace & 0x100) { + Select sSelect; + memset(&sSelect, 0, sizeof(sSelect)); + sSelect.selFlags = SF_WhereBegin; + sSelect.pSrc = pTabList; + sSelect.pWhere = pWhere; + sSelect.pOrderBy = pOrderBy; + sSelect.pEList = pResultSet; + sqlite3TreeViewSelect(0, &sSelect, 0); + } + } + if (sqlite3WhereTrace & 0x100) { /* Display all terms of the WHERE clause */ + sqlite3WhereClausePrint(sWLB.pWC); } #endif - addrExplain = sqlite3WhereExplainOneScan( - pParse, pTabList, pLevel, wctrlFlags - ); - pLevel->addrBody = sqlite3VdbeCurrentAddr(v); - notReady = sqlite3WhereCodeOneLoopStart(pParse,v,pWInfo,ii,pLevel,notReady); - pWInfo->iContinue = pLevel->addrCont; - if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){ - sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain); + + if (nTabList!=1 || whereShortCut(&sWLB)==0) { + rc = whereLoopAddAll(&sWLB); + if (rc) goto whereBeginError; + +#ifdef WHERETRACE_ENABLED + if (sqlite3WhereTrace) { /* Display all of the WhereLoop objects */ + WhereLoop *p; + int i; + static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" + "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; + for (p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++) { + p->cId = zLabel[i%(sizeof(zLabel)-1)]; + whereLoopPrint(p, sWLB.pWC); + } + } +#endif + + wherePathSolver(pWInfo, 0); + if (db->mallocFailed) goto whereBeginError; + if (pWInfo->pOrderBy) { + wherePathSolver(pWInfo, pWInfo->nRowOut+1); + if (db->mallocFailed) goto whereBeginError; + } } - } + if (pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0) { + pWInfo->revMask = ALLBITS; + } + if (pParse->nErr || NEVER(db->mallocFailed)) { + goto whereBeginError; + } +#ifdef WHERETRACE_ENABLED + if (sqlite3WhereTrace) { + sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); + if (pWInfo->nOBSat>0) { + sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); + } + switch (pWInfo->eDistinct) { + case WHERE_DISTINCT_UNIQUE: { + sqlite3DebugPrintf(" DISTINCT=unique"); + break; + } + case WHERE_DISTINCT_ORDERED: { + sqlite3DebugPrintf(" DISTINCT=ordered"); + break; + } + case WHERE_DISTINCT_UNORDERED: { + sqlite3DebugPrintf(" DISTINCT=unordered"); + break; + } + } + sqlite3DebugPrintf("\n"); + for (ii=0; iinLevel; ii++) { + whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC); + } + } +#endif - /* Done. */ - VdbeModuleComment((v, "Begin WHERE-core")); - return pWInfo; + /* Attempt to omit tables from the join that do not affect the result. + ** For a table to not affect the result, the following must be true: + ** + ** 1) The query must not be an aggregate. + ** 2) The table must be the RHS of a LEFT JOIN. + ** 3) Either the query must be DISTINCT, or else the ON or USING clause + ** must contain a constraint that limits the scan of the table to + ** at most a single row. + ** 4) The table must not be referenced by any part of the query apart + ** from its own USING or ON clause. + ** + ** For example, given: + ** + ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); + ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); + ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); + ** + ** then table t2 can be omitted from the following: + ** + ** SELECT v1, v3 FROM t1 + ** LEFT JOIN t2 USING (t1.ipk=t2.ipk) + ** LEFT JOIN t3 USING (t1.ipk=t3.ipk) + ** + ** or from: + ** + ** SELECT DISTINCT v1, v3 FROM t1 + ** LEFT JOIN t2 + ** LEFT JOIN t3 USING (t1.ipk=t3.ipk) + */ + notReady = ~(Bitmask)0; + if (pWInfo->nLevel>=2 + && pResultSet!=0 /* guarantees condition (1) above */ + && OptimizationEnabled(db, SQLITE_OmitNoopJoin) + ) { + int i; + Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); + if (sWLB.pOrderBy) { + tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); + } + for (i=pWInfo->nLevel-1; i>=1; i--) { + WhereTerm *pTerm, *pEnd; + struct SrcList_item *pItem; + pLoop = pWInfo->a[i].pWLoop; + pItem = &pWInfo->pTabList->a[pLoop->iTab]; + if ((pItem->fg.jointype & JT_LEFT)==0) continue; + if ((wctrlFlags & WHERE_WANT_DISTINCT)==0 + && (pLoop->wsFlags & WHERE_ONEROW)==0 + ) { + continue; + } + if ((tabUsed & pLoop->maskSelf)!=0) continue; + pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; + for (pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0) { + if (!ExprHasProperty(pTerm->pExpr, EP_FromJoin) + || pTerm->pExpr->iRightJoinTable!=pItem->iCursor + ) { + break; + } + } + } + if (pTerm drop loop %c not used\n", pLoop->cId)); + notReady &= ~pLoop->maskSelf; + for (pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0) { + pTerm->wtFlags |= TERM_CODED; + } + } + if (i!=pWInfo->nLevel-1) { + int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); + memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); + } + pWInfo->nLevel--; + nTabList--; + } + } + WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); + pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; - /* Jump here if malloc fails */ + /* If the caller is an UPDATE or DELETE statement that is requesting + ** to use a one-pass algorithm, determine if this is appropriate. + ** + ** A one-pass approach can be used if the caller has requested one + ** and either (a) the scan visits at most one row or (b) each + ** of the following are true: + ** + ** * the caller has indicated that a one-pass approach can be used + ** with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and + ** * the table is not a virtual table, and + ** * either the scan does not use the OR optimization or the caller + ** is a DELETE operation (WHERE_DUPLICATES_OK is only specified + ** for DELETE). + ** + ** The last qualification is because an UPDATE statement uses + ** WhereInfo.aiCurOnePass[1] to determine whether or not it really can + ** use a one-pass approach, and this is not set accurately for scans + ** that use the OR optimization. + */ + assert((wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); + if ((wctrlFlags & WHERE_ONEPASS_DESIRED)!=0) { + int wsFlags = pWInfo->a[0].pWLoop->wsFlags; + int bOnerow = (wsFlags & WHERE_ONEROW)!=0; + assert( !(wsFlags & WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pTab)); + if (bOnerow || ( + 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) + && !IsVirtual(pTabList->a[0].pTab) + && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) + )) { + pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; + if (HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY)) { + if (wctrlFlags & WHERE_ONEPASS_MULTIROW) { + bFordelete = OPFLAG_FORDELETE; + } + pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY); + } + } + } + + /* Open all tables in the pTabList and any indices selected for + ** searching those tables. + */ + for (ii=0, pLevel=pWInfo->a; iia[pLevel->iFrom]; + pTab = pTabItem->pTab; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + pLoop = pLevel->pWLoop; + if ((pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect) { + /* Do nothing */ + } else +#ifndef SQLITE_OMIT_VIRTUALTABLE + if ((pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0) { + const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); + int iCur = pTabItem->iCursor; + sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); + } else if (IsVirtual(pTab)) { + /* noop */ + } else +#endif + if ((pLoop->wsFlags & WHERE_IDX_ONLY)==0 + && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0) { + int op = OP_OpenRead; + if (pWInfo->eOnePass!=ONEPASS_OFF) { + op = OP_OpenWrite; + pWInfo->aiCurOnePass[0] = pTabItem->iCursor; + }; + sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); + assert( pTabItem->iCursor==pLevel->iTabCur ); + testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 ); + testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS ); + if (pWInfo->eOnePass==ONEPASS_OFF && pTab->nColcolUsed; + int n = 0; + for (; b; b=b>>1, n++) {} + sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32); + assert( n<=pTab->nCol ); + } +#ifdef SQLITE_ENABLE_CURSOR_HINTS + if (pLoop->u.btree.pIndex!=0) { + sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete); + } else +#endif + { + sqlite3VdbeChangeP5(v, bFordelete); + } +#ifdef SQLITE_ENABLE_COLUMN_USED_MASK + sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0, + (const u8*)&pTabItem->colUsed, P4_INT64); +#endif + } else { + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + } + if (pLoop->wsFlags & WHERE_INDEXED) { + Index *pIx = pLoop->u.btree.pIndex; + int iIndexCur; + int op = OP_OpenRead; + /* iAuxArg is always set to a positive value if ONEPASS is possible */ + assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); + if (!HasRowid(pTab) && IsPrimaryKeyIndex(pIx) + && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 + ) { + /* This is one term of an OR-optimization using the PRIMARY KEY of a + ** WITHOUT ROWID table. No need for a separate index */ + iIndexCur = pLevel->iTabCur; + op = 0; + } else if (pWInfo->eOnePass!=ONEPASS_OFF) { + Index *pJ = pTabItem->pTab->pIndex; + iIndexCur = iAuxArg; + assert( wctrlFlags & WHERE_ONEPASS_DESIRED ); + while (ALWAYS(pJ) && pJ!=pIx) { + iIndexCur++; + pJ = pJ->pNext; + } + op = OP_OpenWrite; + pWInfo->aiCurOnePass[1] = iIndexCur; + } else if (iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0) { + iIndexCur = iAuxArg; + op = OP_ReopenIdx; + } else { + iIndexCur = pParse->nTab++; + } + pLevel->iIdxCur = iIndexCur; + assert( pIx->pSchema==pTab->pSchema ); + assert( iIndexCur>=0 ); + if (op) { + sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIx); + if ((pLoop->wsFlags & WHERE_CONSTRAINT)!=0 + && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 + && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 + && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED + ) { + sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */ + } + VdbeComment((v, "%s", pIx->zName)); +#ifdef SQLITE_ENABLE_COLUMN_USED_MASK + { + u64 colUsed = 0; + int ii, jj; + for (ii=0; iinColumn; ii++) { + jj = pIx->aiColumn[ii]; + if (jj<0) continue; + if (jj>63) jj = 63; + if ((pTabItem->colUsed & MASKBIT(jj))==0) continue; + colUsed |= ((u64)1)<<(ii<63 ? ii : 63); + } + sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0, + (u8*)&colUsed, P4_INT64); + } +#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */ + } + } + if (iDb>=0) sqlite3CodeVerifySchema(pParse, iDb); + } + pWInfo->iTop = sqlite3VdbeCurrentAddr(v); + if (db->mallocFailed) goto whereBeginError; + + /* Generate the code to do the search. Each iteration of the for + ** loop below generates code for a single nested loop of the VM + ** program. + */ + for (ii=0; iia[ii]; + wsFlags = pLevel->pWLoop->wsFlags; +#ifndef SQLITE_OMIT_AUTOMATIC_INDEX + if ((pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0) { + constructAutomaticIndex(pParse, &pWInfo->sWC, + &pTabList->a[pLevel->iFrom], notReady, pLevel); + if (db->mallocFailed) goto whereBeginError; + } +#endif + addrExplain = sqlite3WhereExplainOneScan( + pParse, pTabList, pLevel, wctrlFlags + ); + pLevel->addrBody = sqlite3VdbeCurrentAddr(v); + notReady = sqlite3WhereCodeOneLoopStart(pParse,v,pWInfo,ii,pLevel,notReady); + pWInfo->iContinue = pLevel->addrCont; + if ((wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0) { + sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain); + } + } + + /* Done. */ + VdbeModuleComment((v, "Begin WHERE-core")); + return pWInfo; + + /* Jump here if malloc fails */ whereBeginError: - if( pWInfo ){ - pParse->nQueryLoop = pWInfo->savedNQueryLoop; - whereInfoFree(db, pWInfo); - } - return 0; + if (pWInfo) { + pParse->nQueryLoop = pWInfo->savedNQueryLoop; + whereInfoFree(db, pWInfo); + } + return 0; } /* @@ -5137,252 +5137,252 @@ whereBeginError: # define OpcodeRewriteTrace(D,K,P) /* no-op */ #else # define OpcodeRewriteTrace(D,K,P) sqlite3WhereOpcodeRewriteTrace(D,K,P) - static void sqlite3WhereOpcodeRewriteTrace( +static void sqlite3WhereOpcodeRewriteTrace( sqlite3 *db, int pc, VdbeOp *pOp - ){ - if( (db->flags & SQLITE_VdbeAddopTrace)==0 ) return; + ){ + if ((db->flags & SQLITE_VdbeAddopTrace)==0) return; sqlite3VdbePrintOp(0, pc, pOp); - } +} #endif /* -** Generate the end of the WHERE loop. See comments on +** Generate the end of the WHERE loop. See comments on ** sqlite3WhereBegin() for additional information. */ void sqlite3WhereEnd(WhereInfo *pWInfo){ - Parse *pParse = pWInfo->pParse; - Vdbe *v = pParse->pVdbe; - int i; - WhereLevel *pLevel; - WhereLoop *pLoop; - SrcList *pTabList = pWInfo->pTabList; - sqlite3 *db = pParse->db; + Parse *pParse = pWInfo->pParse; + Vdbe *v = pParse->pVdbe; + int i; + WhereLevel *pLevel; + WhereLoop *pLoop; + SrcList *pTabList = pWInfo->pTabList; + sqlite3 *db = pParse->db; - /* Generate loop termination code. - */ - VdbeModuleComment((v, "End WHERE-core")); - for(i=pWInfo->nLevel-1; i>=0; i--){ - int addr; - pLevel = &pWInfo->a[i]; - pLoop = pLevel->pWLoop; - if( pLevel->op!=OP_Noop ){ + /* Generate loop termination code. + */ + VdbeModuleComment((v, "End WHERE-core")); + for (i=pWInfo->nLevel-1; i>=0; i--) { + int addr; + pLevel = &pWInfo->a[i]; + pLoop = pLevel->pWLoop; + if (pLevel->op!=OP_Noop) { #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT - int addrSeek = 0; - Index *pIdx; - int n; - if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED - && i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */ - && (pLoop->wsFlags & WHERE_INDEXED)!=0 - && (pIdx = pLoop->u.btree.pIndex)->hasStat1 - && (n = pLoop->u.btree.nDistinctCol)>0 - && pIdx->aiRowLogEst[n]>=36 - ){ - int r1 = pParse->nMem+1; - int j, op; - for(j=0; jiIdxCur, j, r1+j); - } - pParse->nMem += n+1; - op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT; - addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n); - VdbeCoverageIf(v, op==OP_SeekLT); - VdbeCoverageIf(v, op==OP_SeekGT); - sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2); - } + int addrSeek = 0; + Index *pIdx; + int n; + if (pWInfo->eDistinct==WHERE_DISTINCT_ORDERED + && i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */ + && (pLoop->wsFlags & WHERE_INDEXED)!=0 + && (pIdx = pLoop->u.btree.pIndex)->hasStat1 + && (n = pLoop->u.btree.nDistinctCol)>0 + && pIdx->aiRowLogEst[n]>=36 + ) { + int r1 = pParse->nMem+1; + int j, op; + for (j=0; jiIdxCur, j, r1+j); + } + pParse->nMem += n+1; + op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT; + addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n); + VdbeCoverageIf(v, op==OP_SeekLT); + VdbeCoverageIf(v, op==OP_SeekGT); + sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2); + } #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */ - /* The common case: Advance to the next row */ - sqlite3VdbeResolveLabel(v, pLevel->addrCont); - sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); - sqlite3VdbeChangeP5(v, pLevel->p5); - VdbeCoverage(v); - VdbeCoverageIf(v, pLevel->op==OP_Next); - VdbeCoverageIf(v, pLevel->op==OP_Prev); - VdbeCoverageIf(v, pLevel->op==OP_VNext); -#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT - if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek); -#endif - }else{ - sqlite3VdbeResolveLabel(v, pLevel->addrCont); - } - if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ - struct InLoop *pIn; - int j; - sqlite3VdbeResolveLabel(v, pLevel->addrNxt); - for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ - sqlite3VdbeJumpHere(v, pIn->addrInTop+1); - if( pIn->eEndLoopOp!=OP_Noop ){ - if( pIn->nPrefix ){ - assert( pLoop->wsFlags & WHERE_IN_EARLYOUT ); - sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur, - sqlite3VdbeCurrentAddr(v)+2, - pIn->iBase, pIn->nPrefix); + /* The common case: Advance to the next row */ + sqlite3VdbeResolveLabel(v, pLevel->addrCont); + sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); + sqlite3VdbeChangeP5(v, pLevel->p5); VdbeCoverage(v); - } - sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); - VdbeCoverage(v); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev); - VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next); - } - sqlite3VdbeJumpHere(v, pIn->addrInTop-1); - } - } - sqlite3VdbeResolveLabel(v, pLevel->addrBrk); - if( pLevel->addrSkip ){ - sqlite3VdbeGoto(v, pLevel->addrSkip); - VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName)); - sqlite3VdbeJumpHere(v, pLevel->addrSkip); - sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); - } -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS - if( pLevel->addrLikeRep ){ - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1), - pLevel->addrLikeRep); - VdbeCoverage(v); - } + VdbeCoverageIf(v, pLevel->op==OP_Next); + VdbeCoverageIf(v, pLevel->op==OP_Prev); + VdbeCoverageIf(v, pLevel->op==OP_VNext); +#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT + if (addrSeek) sqlite3VdbeJumpHere(v, addrSeek); #endif - if( pLevel->iLeftJoin ){ - int ws = pLoop->wsFlags; - addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); - assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); - if( (ws & WHERE_IDX_ONLY)==0 ){ - assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); - sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); - } - if( (ws & WHERE_INDEXED) - || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) - ){ - sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); - } - if( pLevel->op==OP_Return ){ - sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); - }else{ - sqlite3VdbeGoto(v, pLevel->addrFirst); - } - sqlite3VdbeJumpHere(v, addr); + } else { + sqlite3VdbeResolveLabel(v, pLevel->addrCont); + } + if (pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0) { + struct InLoop *pIn; + int j; + sqlite3VdbeResolveLabel(v, pLevel->addrNxt); + for (j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--) { + sqlite3VdbeJumpHere(v, pIn->addrInTop+1); + if (pIn->eEndLoopOp!=OP_Noop) { + if (pIn->nPrefix) { + assert( pLoop->wsFlags & WHERE_IN_EARLYOUT ); + sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur, + sqlite3VdbeCurrentAddr(v)+2, + pIn->iBase, pIn->nPrefix); + VdbeCoverage(v); + } + sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); + VdbeCoverage(v); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev); + VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next); + } + sqlite3VdbeJumpHere(v, pIn->addrInTop-1); + } + } + sqlite3VdbeResolveLabel(v, pLevel->addrBrk); + if (pLevel->addrSkip) { + sqlite3VdbeGoto(v, pLevel->addrSkip); + VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName)); + sqlite3VdbeJumpHere(v, pLevel->addrSkip); + sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); + } +#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS + if (pLevel->addrLikeRep) { + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1), + pLevel->addrLikeRep); + VdbeCoverage(v); + } +#endif + if (pLevel->iLeftJoin) { + int ws = pLoop->wsFlags; + addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); + assert((ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); + if ((ws & WHERE_IDX_ONLY)==0) { + assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); + sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); + } + if ((ws & WHERE_INDEXED) + || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) + ) { + sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); + } + if (pLevel->op==OP_Return) { + sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); + } else { + sqlite3VdbeGoto(v, pLevel->addrFirst); + } + sqlite3VdbeJumpHere(v, addr); + } + VdbeModuleComment((v, "End WHERE-loop%d: %s", i, + pWInfo->pTabList->a[pLevel->iFrom].pTab->zName)); } - VdbeModuleComment((v, "End WHERE-loop%d: %s", i, - pWInfo->pTabList->a[pLevel->iFrom].pTab->zName)); - } - /* The "break" point is here, just past the end of the outer loop. - ** Set it. - */ - sqlite3VdbeResolveLabel(v, pWInfo->iBreak); - - assert( pWInfo->nLevel<=pTabList->nSrc ); - for(i=0, pLevel=pWInfo->a; inLevel; i++, pLevel++){ - int k, last; - VdbeOp *pOp; - Index *pIdx = 0; - struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom]; - Table *pTab = pTabItem->pTab; - assert( pTab!=0 ); - pLoop = pLevel->pWLoop; - - /* For a co-routine, change all OP_Column references to the table of - ** the co-routine into OP_Copy of result contained in a register. - ** OP_Rowid becomes OP_Null. + /* The "break" point is here, just past the end of the outer loop. + ** Set it. */ - if( pTabItem->fg.viaCoroutine ){ - testcase( pParse->db->mallocFailed ); - translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, - pTabItem->regResult, 0); - continue; - } + sqlite3VdbeResolveLabel(v, pWInfo->iBreak); + + assert( pWInfo->nLevel<=pTabList->nSrc ); + for (i=0, pLevel=pWInfo->a; inLevel; i++, pLevel++) { + int k, last; + VdbeOp *pOp; + Index *pIdx = 0; + struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom]; + Table *pTab = pTabItem->pTab; + assert( pTab!=0 ); + pLoop = pLevel->pWLoop; + + /* For a co-routine, change all OP_Column references to the table of + ** the co-routine into OP_Copy of result contained in a register. + ** OP_Rowid becomes OP_Null. + */ + if (pTabItem->fg.viaCoroutine) { + testcase( pParse->db->mallocFailed ); + translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, + pTabItem->regResult, 0); + continue; + } #ifdef SQLITE_ENABLE_EARLY_CURSOR_CLOSE - /* Close all of the cursors that were opened by sqlite3WhereBegin. - ** Except, do not close cursors that will be reused by the OR optimization - ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors - ** created for the ONEPASS optimization. - */ - if( (pTab->tabFlags & TF_Ephemeral)==0 - && pTab->pSelect==0 - && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - ){ - int ws = pLoop->wsFlags; - if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){ - sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); - } - if( (ws & WHERE_INDEXED)!=0 - && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 - && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1] - ){ - sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); - } - } -#endif - - /* If this scan uses an index, make VDBE code substitutions to read data - ** from the index instead of from the table where possible. In some cases - ** this optimization prevents the table from ever being read, which can - ** yield a significant performance boost. - ** - ** Calls to the code generator in between sqlite3WhereBegin and - ** sqlite3WhereEnd will have created code that references the table - ** directly. This loop scans all that code looking for opcodes - ** that reference the table and converts them into opcodes that - ** reference the index. - */ - if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){ - pIdx = pLoop->u.btree.pIndex; - }else if( pLoop->wsFlags & WHERE_MULTI_OR ){ - pIdx = pLevel->u.pCovidx; - } - if( pIdx - && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable)) - && !db->mallocFailed - ){ - last = sqlite3VdbeCurrentAddr(v); - k = pLevel->addrBody; -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_VdbeAddopTrace ){ - printf("TRANSLATE opcodes in range %d..%d\n", k, last-1); - } -#endif - pOp = sqlite3VdbeGetOp(v, k); - for(; kp1!=pLevel->iTabCur ) continue; - if( pOp->opcode==OP_Column -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - || pOp->opcode==OP_Offset -#endif - ){ - int x = pOp->p2; - assert( pIdx->pTable==pTab ); - if( !HasRowid(pTab) ){ - Index *pPk = sqlite3PrimaryKeyIndex(pTab); - x = pPk->aiColumn[x]; - assert( x>=0 ); - } - x = sqlite3ColumnOfIndex(pIdx, x); - if( x>=0 ){ - pOp->p2 = x; - pOp->p1 = pLevel->iIdxCur; - OpcodeRewriteTrace(db, k, pOp); - } - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 - || pWInfo->eOnePass ); - }else if( pOp->opcode==OP_Rowid ){ - pOp->p1 = pLevel->iIdxCur; - pOp->opcode = OP_IdxRowid; - OpcodeRewriteTrace(db, k, pOp); - }else if( pOp->opcode==OP_IfNullRow ){ - pOp->p1 = pLevel->iIdxCur; - OpcodeRewriteTrace(db, k, pOp); + /* Close all of the cursors that were opened by sqlite3WhereBegin. + ** Except, do not close cursors that will be reused by the OR optimization + ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors + ** created for the ONEPASS optimization. + */ + if ((pTab->tabFlags & TF_Ephemeral)==0 + && pTab->pSelect==0 + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 + ) { + int ws = pLoop->wsFlags; + if (pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0) { + sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); + } + if ((ws & WHERE_INDEXED)!=0 + && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 + && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1] + ) { + sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); + } } - } -#ifdef SQLITE_DEBUG - if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n"); #endif - } - } - /* Final cleanup - */ - pParse->nQueryLoop = pWInfo->savedNQueryLoop; - whereInfoFree(db, pWInfo); - return; + /* If this scan uses an index, make VDBE code substitutions to read data + ** from the index instead of from the table where possible. In some cases + ** this optimization prevents the table from ever being read, which can + ** yield a significant performance boost. + ** + ** Calls to the code generator in between sqlite3WhereBegin and + ** sqlite3WhereEnd will have created code that references the table + ** directly. This loop scans all that code looking for opcodes + ** that reference the table and converts them into opcodes that + ** reference the index. + */ + if (pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY)) { + pIdx = pLoop->u.btree.pIndex; + } else if (pLoop->wsFlags & WHERE_MULTI_OR) { + pIdx = pLevel->u.pCovidx; + } + if (pIdx + && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable)) + && !db->mallocFailed + ) { + last = sqlite3VdbeCurrentAddr(v); + k = pLevel->addrBody; +#ifdef SQLITE_DEBUG + if (db->flags & SQLITE_VdbeAddopTrace) { + printf("TRANSLATE opcodes in range %d..%d\n", k, last-1); + } +#endif + pOp = sqlite3VdbeGetOp(v, k); + for (; kp1!=pLevel->iTabCur) continue; + if (pOp->opcode==OP_Column +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + || pOp->opcode==OP_Offset +#endif + ) { + int x = pOp->p2; + assert( pIdx->pTable==pTab ); + if (!HasRowid(pTab)) { + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + x = pPk->aiColumn[x]; + assert( x>=0 ); + } + x = sqlite3ColumnOfIndex(pIdx, x); + if (x>=0) { + pOp->p2 = x; + pOp->p1 = pLevel->iIdxCur; + OpcodeRewriteTrace(db, k, pOp); + } + assert((pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 + || pWInfo->eOnePass ); + } else if (pOp->opcode==OP_Rowid) { + pOp->p1 = pLevel->iIdxCur; + pOp->opcode = OP_IdxRowid; + OpcodeRewriteTrace(db, k, pOp); + } else if (pOp->opcode==OP_IfNullRow) { + pOp->p1 = pLevel->iIdxCur; + OpcodeRewriteTrace(db, k, pOp); + } + } +#ifdef SQLITE_DEBUG + if (db->flags & SQLITE_VdbeAddopTrace) printf("TRANSLATE complete\n"); +#endif + } + } + + /* Final cleanup + */ + pParse->nQueryLoop = pWInfo->savedNQueryLoop; + whereInfoFree(db, pWInfo); + return; } diff --git a/test/bug-hunting/cve/CVE-2019-19334/parser.c b/test/bug-hunting/cve/CVE-2019-19334/parser.c index e5d7ebbd6..c9ae171b4 100644 --- a/test/bug-hunting/cve/CVE-2019-19334/parser.c +++ b/test/bug-hunting/cve/CVE-2019-19334/parser.c @@ -534,14 +534,14 @@ validate_length_range(uint8_t kind, uint64_t unum, int64_t snum, int64_t fnum, u } if (((kind == 0) && (unum < tmp_intv->value.uval.min)) - || ((kind == 1) && (snum < tmp_intv->value.sval.min)) - || ((kind == 2) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.min, cur_type->info.dec64.dig) < 0))) { + || ((kind == 1) && (snum < tmp_intv->value.sval.min)) + || ((kind == 2) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.min, cur_type->info.dec64.dig) < 0))) { break; } if (((kind == 0) && (unum >= tmp_intv->value.uval.min) && (unum <= tmp_intv->value.uval.max)) - || ((kind == 1) && (snum >= tmp_intv->value.sval.min) && (snum <= tmp_intv->value.sval.max)) - || ((kind == 2) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.min, cur_type->info.dec64.dig) > -1) + || ((kind == 1) && (snum >= tmp_intv->value.sval.min) && (snum <= tmp_intv->value.sval.max)) + || ((kind == 2) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.min, cur_type->info.dec64.dig) > -1) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.max, cur_type->info.dec64.dig) < 1))) { match = 1; } @@ -1096,16 +1096,16 @@ make_canonical(struct ly_ctx *ctx, int type, const char **value, void *data1, vo num = *((int64_t *)data1); c = *((uint8_t *)data2); if (num) { - count = sprintf(buf, "%"PRId64" ", num); - if ( (num > 0 && (count - 1) <= c) - || (count - 2) <= c ) { + count = sprintf(buf, "%" PRId64 " ", num); + if ((num > 0 && (count - 1) <= c) + || (count - 2) <= c) { /* we have 0. value, print the value with the leading zeros * (one for 0. and also keep the correct with of num according * to fraction-digits value) * for (num<0) - extra character for '-' sign */ - count = sprintf(buf, "%0*"PRId64" ", (num > 0) ? (c + 1) : (c + 2), num); + count = sprintf(buf, "%0*" PRId64 " ", (num > 0) ? (c + 1) : (c + 2), num); } - for (i = c, j = 1; i > 0 ; i--) { + for (i = c, j = 1; i > 0; i--) { if (j && i > 1 && buf[count - 2] == '0') { /* we have trailing zero to skip */ buf[count - 1] = '\0'; @@ -1127,7 +1127,7 @@ make_canonical(struct ly_ctx *ctx, int type, const char **value, void *data1, vo case LY_TYPE_INT32: case LY_TYPE_INT64: num = *((int64_t *)data1); - sprintf(buf, "%"PRId64, num); + sprintf(buf, "%" PRId64, num); break; case LY_TYPE_UINT8: @@ -1135,7 +1135,7 @@ make_canonical(struct ly_ctx *ctx, int type, const char **value, void *data1, vo case LY_TYPE_UINT32: case LY_TYPE_UINT64: unum = *((uint64_t *)data1); - sprintf(buf, "%"PRIu64, unum); + sprintf(buf, "%" PRIu64, unum); break; default: @@ -1274,8 +1274,8 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x if (ptr[uind] == '\n') { unum--; } else if ((ptr[uind] < '/' && ptr[uind] != '+') || - (ptr[uind] > '9' && ptr[uind] < 'A') || - (ptr[uind] > 'Z' && ptr[uind] < 'a') || ptr[uind] > 'z') { + (ptr[uind] > '9' && ptr[uind] < 'A') || + (ptr[uind] > 'Z' && ptr[uind] < 'a') || ptr[uind] > 'z') { if (ptr[uind] == '=') { /* padding */ if (uind == u - 2 && ptr[uind + 1] == '=') { @@ -1763,7 +1763,7 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x case LY_TYPE_INT8: if (parse_int(value, __INT64_C(-128), __INT64_C(127), dflt ? 0 : 10, &num, contextnode) - || (!trusted && validate_length_range(1, 0, num, 0, 0, type, value, contextnode))) { + || (!trusted && validate_length_range(1, 0, num, 0, 0, type, value, contextnode))) { goto error; } @@ -1780,7 +1780,7 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x case LY_TYPE_INT16: if (parse_int(value, __INT64_C(-32768), __INT64_C(32767), dflt ? 0 : 10, &num, contextnode) - || (!trusted && validate_length_range(1, 0, num, 0, 0, type, value, contextnode))) { + || (!trusted && validate_length_range(1, 0, num, 0, 0, type, value, contextnode))) { goto error; } @@ -1797,7 +1797,7 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x case LY_TYPE_INT32: if (parse_int(value, __INT64_C(-2147483648), __INT64_C(2147483647), dflt ? 0 : 10, &num, contextnode) - || (!trusted && validate_length_range(1, 0, num, 0, 0, type, value, contextnode))) { + || (!trusted && validate_length_range(1, 0, num, 0, 0, type, value, contextnode))) { goto error; } @@ -1815,7 +1815,7 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x case LY_TYPE_INT64: if (parse_int(value, __INT64_C(-9223372036854775807) - __INT64_C(1), __INT64_C(9223372036854775807), dflt ? 0 : 10, &num, contextnode) - || (!trusted && validate_length_range(1, 0, num, 0, 0, type, value, contextnode))) { + || (!trusted && validate_length_range(1, 0, num, 0, 0, type, value, contextnode))) { goto error; } @@ -1832,7 +1832,7 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x case LY_TYPE_UINT8: if (parse_uint(value, __UINT64_C(255), dflt ? 0 : 10, &unum, contextnode) - || (!trusted && validate_length_range(0, unum, 0, 0, 0, type, value, contextnode))) { + || (!trusted && validate_length_range(0, unum, 0, 0, 0, type, value, contextnode))) { goto error; } @@ -1849,7 +1849,7 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x case LY_TYPE_UINT16: if (parse_uint(value, __UINT64_C(65535), dflt ? 0 : 10, &unum, contextnode) - || (!trusted && validate_length_range(0, unum, 0, 0, 0, type, value, contextnode))) { + || (!trusted && validate_length_range(0, unum, 0, 0, 0, type, value, contextnode))) { goto error; } @@ -1866,7 +1866,7 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x case LY_TYPE_UINT32: if (parse_uint(value, __UINT64_C(4294967295), dflt ? 0 : 10, &unum, contextnode) - || (!trusted && validate_length_range(0, unum, 0, 0, 0, type, value, contextnode))) { + || (!trusted && validate_length_range(0, unum, 0, 0, 0, type, value, contextnode))) { goto error; } @@ -1883,7 +1883,7 @@ lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *x case LY_TYPE_UINT64: if (parse_uint(value, __UINT64_C(18446744073709551615), dflt ? 0 : 10, &unum, contextnode) - || (!trusted && validate_length_range(0, unum, 0, 0, 0, type, value, contextnode))) { + || (!trusted && validate_length_range(0, unum, 0, 0, 0, type, value, contextnode))) { goto error; } @@ -2092,7 +2092,7 @@ lyp_fill_attr(struct ly_ctx *ctx, struct lyd_node *parent, const char *module_ns dattr->parent = parent; dattr->next = NULL; dattr->annotation = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : - (struct lys_ext_instance_complex *)mod->ext[pos]; + (struct lys_ext_instance_complex *)mod->ext[pos]; dattr->name = lydict_insert(ctx, attr_name, 0); dattr->value_str = lydict_insert(ctx, attr_value, 0); @@ -2126,7 +2126,7 @@ lyp_check_edit_attr(struct ly_ctx *ctx, struct lyd_attr *attr, struct lyd_node * LY_TREE_FOR(attr, attr) { last = NULL; if (!strcmp(attr->annotation->arg_value, "operation") && - !strcmp(attr->annotation->module->name, "ietf-netconf")) { + !strcmp(attr->annotation->module->name, "ietf-netconf")) { if (bits & 0x10) { LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "operation attributes", parent->schema->name); return -1; @@ -2138,7 +2138,7 @@ lyp_check_edit_attr(struct ly_ctx *ctx, struct lyd_attr *attr, struct lyd_node * bits |= 0x20; } } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */ - !strcmp(attr->annotation->arg_value, "insert")) { + !strcmp(attr->annotation->arg_value, "insert")) { /* 'insert' attribute present */ if (!(parent->schema->flags & LYS_USERORDERED)) { /* ... but it is not expected */ @@ -2157,7 +2157,7 @@ lyp_check_edit_attr(struct ly_ctx *ctx, struct lyd_attr *attr, struct lyd_node * } last = attr; } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */ - !strcmp(attr->annotation->arg_value, "value")) { + !strcmp(attr->annotation->arg_value, "value")) { if (bits & 0x04) { LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "value attributes", parent->schema->name); return -1; @@ -2168,7 +2168,7 @@ lyp_check_edit_attr(struct ly_ctx *ctx, struct lyd_attr *attr, struct lyd_node * bits |= 0x04; last = attr; } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */ - !strcmp(attr->annotation->arg_value, "key")) { + !strcmp(attr->annotation->arg_value, "key")) { if (bits & 0x08) { LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "key attributes", parent->schema->name); return -1; @@ -2319,7 +2319,7 @@ lyp_check_identifier(struct ly_ctx *ctx, const char *id, enum LY_IDENT type, str } for (i = 1; id[i]; i++) { if (!(id[i] >= 'A' && id[i] <= 'Z') && !(id[i] >= 'a' && id[i] <= 'z') - && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') { + && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') { LOGVAL(ctx, LYE_INID, LY_VLOG_NONE, NULL, id, "invalid character"); return EXIT_FAILURE; } @@ -2349,14 +2349,14 @@ lyp_check_identifier(struct ly_ctx *ctx, const char *id, enum LY_IDENT type, str /* check collision with the built-in types */ if (!strcmp(id, "binary") || !strcmp(id, "bits") || - !strcmp(id, "boolean") || !strcmp(id, "decimal64") || - !strcmp(id, "empty") || !strcmp(id, "enumeration") || - !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") || - !strcmp(id, "int8") || !strcmp(id, "int16") || - !strcmp(id, "int32") || !strcmp(id, "int64") || - !strcmp(id, "leafref") || !strcmp(id, "string") || - !strcmp(id, "uint8") || !strcmp(id, "uint16") || - !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) { + !strcmp(id, "boolean") || !strcmp(id, "decimal64") || + !strcmp(id, "empty") || !strcmp(id, "enumeration") || + !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") || + !strcmp(id, "int8") || !strcmp(id, "int16") || + !strcmp(id, "int32") || !strcmp(id, "int64") || + !strcmp(id, "leafref") || !strcmp(id, "string") || + !strcmp(id, "uint8") || !strcmp(id, "uint16") || + !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) { LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, id, "typedef"); LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Typedef name duplicates a built-in type."); return EXIT_FAILURE; @@ -2522,7 +2522,7 @@ lyp_check_mandatory_(const struct lys_node *root) const struct lys_node *iter = NULL; while ((iter = lys_getnext(iter, root, NULL, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHUSES | LYS_GETNEXT_INTOUSES - | LYS_GETNEXT_INTONPCONT | LYS_GETNEXT_NOSTATECHECK))) { + | LYS_GETNEXT_INTONPCONT | LYS_GETNEXT_NOSTATECHECK))) { if (iter->nodetype == LYS_USES) { if (!((struct lys_node_uses *)iter)->grp) { /* not yet resolved uses */ @@ -2994,8 +2994,8 @@ lyp_check_import(struct lys_module *module, const char *value, struct lys_import if (dup) { /* check the revisions */ if ((dup != imp->module) || - (dup->rev_size != imp->module->rev_size && (!dup->rev_size || imp->module->rev_size)) || - (dup->rev_size && strcmp(dup->rev[0].date, imp->module->rev[0].date))) { + (dup->rev_size != imp->module->rev_size && (!dup->rev_size || imp->module->rev_size)) || + (dup->rev_size && strcmp(dup->rev[0].date, imp->module->rev[0].date))) { /* - modules are not the same * - one of modules has no revision (except they both has no revision) * - revisions of the modules are not the same */ @@ -3278,7 +3278,7 @@ lyp_mand_check_ext(struct lys_ext_instance_complex *ext, const char *ext_name) * LY_STMT_MODIFIER, LY_STMT_STATUS, LY_STMT_MANDATORY, LY_STMT_CONFIG - checked, but mandatory requirement * does not make sense since there is also a default value specified */ - switch(ext->substmt[i].stmt) { + switch (ext->substmt[i].stmt) { case LY_STMT_ORDEREDBY: /* always ok */ break; @@ -3451,7 +3451,7 @@ lyp_deviate_apply_ext(struct lys_deviate *dev, struct lys_node *target, LYEXT_SU * - the same type of the extension which was inherited in case of adding * note - delete deviation is covered in lyp_deviate_del_ext */ if (target->ext[n]->def != extdef || - (dev->mod == LY_DEVIATE_ADD && !(target->ext[n]->flags & LYEXT_OPT_INHERIT))) { + (dev->mod == LY_DEVIATE_ADD && !(target->ext[n]->flags & LYEXT_OPT_INHERIT))) { /* keep this extension */ continue; } @@ -3597,7 +3597,7 @@ lyp_ctx_check_module(struct lys_module *module) module->name, ctx->models.list[i]->rev[0].date); return -1; } else if ((!module->rev_size && !ctx->models.list[i]->rev_size) - || !strcmp(ctx->models.list[i]->rev[0].date, last_rev)) { + || !strcmp(ctx->models.list[i]->rev[0].date, last_rev)) { LOGVRB("Module \"%s@%s\" already in context.", module->name, last_rev ? last_rev : ""); @@ -3695,9 +3695,9 @@ pututf8(struct ly_ctx *ctx, char *dst, int32_t value) if (value < 0x80) { /* one byte character */ if (value < 0x20 && - value != 0x09 && - value != 0x0a && - value != 0x0d) { + value != 0x09 && + value != 0x0a && + value != 0x0d) { goto error; } @@ -3711,7 +3711,7 @@ pututf8(struct ly_ctx *ctx, char *dst, int32_t value) } else if (value < 0xfffe) { /* three bytes character */ if (((value & 0xf800) == 0xd800) || - (value >= 0xfdd0 && value <= 0xfdef)) { + (value >= 0xfdd0 && value <= 0xfdef)) { /* exclude surrogate blocks %xD800-DFFF */ /* exclude noncharacters %xFDD0-FDEF */ goto error; @@ -3754,9 +3754,9 @@ copyutf8(struct ly_ctx *ctx, char *dst, const char *src) if (!(src[0] & 0x80)) { /* one byte character */ if (src[0] < 0x20 && - src[0] != 0x09 && - src[0] != 0x0a && - src[0] != 0x0d) { + src[0] != 0x09 && + src[0] != 0x0a && + src[0] != 0x0d) { LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src); LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x", src[0]); return 0; @@ -3773,8 +3773,8 @@ copyutf8(struct ly_ctx *ctx, char *dst, const char *src) /* three bytes character */ value = ((uint32_t)(src[0] & 0xf) << 12) | ((uint32_t)(src[1] & 0x3f) << 6) | (src[2] & 0x3f); if (((value & 0xf800) == 0xd800) || - (value >= 0xfdd0 && value <= 0xfdef) || - (value & 0xffe) == 0xffe) { + (value >= 0xfdd0 && value <= 0xfdef) || + (value & 0xffe) == 0xffe) { /* exclude surrogate blocks %xD800-DFFF */ /* exclude noncharacters %xFDD0-FDEF */ /* exclude noncharacters %xFFFE-FFFF */ @@ -3830,15 +3830,15 @@ lyp_get_module(const struct lys_module *module, const char *prefix, int pref_len /* module own prefix, submodule own prefix, (sub)module own name */ if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len]) - || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len])) - && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) { + || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len])) + && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) { return main_module; } /* standard import */ for (i = 0; i < module->imp_size; ++i) { if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len])) - && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) { + && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) { return module->imp[i].module; } } @@ -3918,7 +3918,7 @@ lyp_get_yang_data_template(const struct lys_module *module, const char *yang_dat const struct lys_node *ret = NULL; const struct lys_submodule *submodule; - for(i = 0; i < module->ext_size; ++i) { + for (i = 0; i < module->ext_size; ++i) { if (!strcmp(module->ext[i]->def->name, "yang-data") && !strncmp(module->ext[i]->arg_value, yang_data_name, yang_data_name_len) && !module->ext[i]->arg_value[yang_data_name_len]) { ret = (struct lys_node *)module->ext[i]; @@ -3926,9 +3926,9 @@ lyp_get_yang_data_template(const struct lys_module *module, const char *yang_dat } } - for(j = 0; !ret && j < module->inc_size; ++j) { + for (j = 0; !ret && j < module->inc_size; ++j) { submodule = module->inc[j].submodule; - for(i = 0; i < submodule->ext_size; ++i) { + for (i = 0; i < submodule->ext_size; ++i) { if (!strcmp(submodule->ext[i]->def->name, "yang-data") && !strncmp(submodule->ext[i]->arg_value, yang_data_name, yang_data_name_len) && !submodule->ext[i]->arg_value[yang_data_name_len]) { ret = (struct lys_node *)submodule->ext[i]; diff --git a/test/bug-hunting/cve/CVE-2019-19888/jfif.c b/test/bug-hunting/cve/CVE-2019-19888/jfif.c index d3daa1cea..48c9211ed 100644 --- a/test/bug-hunting/cve/CVE-2019-19888/jfif.c +++ b/test/bug-hunting/cve/CVE-2019-19888/jfif.c @@ -18,8 +18,8 @@ // ÄÚ²¿ÀàÐͶ¨Òå typedef struct { // width & height - int width; - int height; + int width; + int height; // quantization table int *pqtab[16]; @@ -41,7 +41,7 @@ typedef struct { int htab_idx_dc; } comp_info[4]; - int datalen; + int datalen; BYTE *databuf; } JFIF; @@ -94,12 +94,12 @@ static void jfif_dump(JFIF *jfif) printf("comp_num : %d\n", jfif->comp_num); for (i=0; icomp_num; i++) { printf("id:%d samp_factor_v:%d samp_factor_h:%d qtab_idx:%d htab_idx_ac:%d htab_idx_dc:%d\n", - jfif->comp_info[i].id, - jfif->comp_info[i].samp_factor_v, - jfif->comp_info[i].samp_factor_h, - jfif->comp_info[i].qtab_idx, - jfif->comp_info[i].htab_idx_ac, - jfif->comp_info[i].htab_idx_dc); + jfif->comp_info[i].id, + jfif->comp_info[i].samp_factor_v, + jfif->comp_info[i].samp_factor_h, + jfif->comp_info[i].qtab_idx, + jfif->comp_info[i].htab_idx_ac, + jfif->comp_info[i].htab_idx_dc); } printf("\n"); @@ -133,7 +133,7 @@ static void category_encode(int *code, int *size) if (*code < 0) *code = (1 << *size) - absc - 1; } -static int category_decode(int code, int size) +static int category_decode(int code, int size) { return code >= (1 << (size - 1)) ? code : code - (1 << size) + 1; } @@ -143,15 +143,15 @@ void* jfif_load(char *file) { JFIF *jfif = NULL; FILE *fp = NULL; - int header = 0; - int type = 0; - WORD size = 0; + int header = 0; + int type = 0; + WORD size = 0; BYTE *buf = NULL; BYTE *end = NULL; BYTE *dqt, *dht; - int ret =-1; - long offset = 0; - int i; + int ret =-1; + long offset = 0; + int i; jfif = calloc(1, sizeof(JFIF)); buf = calloc(1, 0x10000); @@ -230,10 +230,10 @@ void* jfif_load(char *file) if (len > 256) len = 256; if (fac) { if (!jfif->phcac[idx]) jfif->phcac[idx] = calloc(1, sizeof(HUFCODEC)); - if ( jfif->phcac[idx]) memcpy(jfif->phcac[idx]->huftab, &dht[1], 16 + len); + if (jfif->phcac[idx]) memcpy(jfif->phcac[idx]->huftab, &dht[1], 16 + len); } else { if (!jfif->phcdc[idx]) jfif->phcdc[idx] = calloc(1, sizeof(HUFCODEC)); - if ( jfif->phcdc[idx]) memcpy(jfif->phcdc[idx]->huftab, &dht[1], 16 + len); + if (jfif->phcdc[idx]) memcpy(jfif->phcdc[idx]->huftab, &dht[1], 16 + len); } dht += 17 + len; size-= 17 + len; @@ -253,7 +253,7 @@ read_data: done: if (buf) free (buf); - if (fp ) fclose(fp ); + if (fp) fclose(fp ); if (ret == -1) { jfif_free(jfif); jfif = NULL; @@ -265,9 +265,9 @@ int jfif_save(void *ctxt, char *file) { JFIF *jfif = (JFIF*)ctxt; FILE *fp = NULL; - int len = 0; - int i, j; - int ret = -1; + int len = 0; + int i, j; + int ret = -1; fp = fopen(file, "wb"); if (!fp) goto done; @@ -284,7 +284,7 @@ int jfif_save(void *ctxt, char *file) fputc(0xdb, fp); fputc(len >> 8, fp); fputc(len >> 0, fp); - fputc(i , fp); + fputc(i, fp); for (j=0; j<64; j++) { fputc(jfif->pqtab[i][ZIGZAG[j]], fp); } @@ -296,7 +296,7 @@ int jfif_save(void *ctxt, char *file) fputc(0xc0, fp); fputc(len >> 8, fp); fputc(len >> 0, fp); - fputc(8 , fp); // precision 8bit + fputc(8, fp); // precision 8bit fputc(jfif->height >> 8, fp); // height fputc(jfif->height >> 0, fp); // height fputc(jfif->width >> 8, fp); // width @@ -363,7 +363,7 @@ done: void jfif_free(void *ctxt) { JFIF *jfif = (JFIF*)ctxt; - int i; + int i; if (!jfif) return; for (i=0; i<16; i++) { if (jfif->pqtab[i]) free(jfif->pqtab[i]); @@ -379,18 +379,18 @@ int jfif_decode(void *ctxt, BMP *pb) JFIF *jfif = (JFIF*)ctxt; void *bs = NULL; int *ftab[16]= {0}; - int dc[4] = {0}; - int mcuw, mcuh, mcuc, mcur, mcui, jw, jh; - int i, j, c, h, v, x, y; - int sfh_max = 0; - int sfv_max = 0; - int yuv_stride[3] = {0}; - int yuv_height[3] = {0}; + int dc[4] = {0}; + int mcuw, mcuh, mcuc, mcur, mcui, jw, jh; + int i, j, c, h, v, x, y; + int sfh_max = 0; + int sfv_max = 0; + int yuv_stride[3] = {0}; + int yuv_height[3] = {0}; int *yuv_datbuf[3] = {0}; int *idst, *isrc; int *ysrc, *usrc, *vsrc; BYTE *bdst; - int ret = -1; + int ret = -1; if (!ctxt || !pb) { printf("invalid input params !\n"); @@ -424,7 +424,7 @@ int jfif_decode(void *ctxt, BMP *pb) } mcuw = sfh_max * 8; mcuh = sfv_max * 8; - jw = ALIGN(jfif->width , mcuw); + jw = ALIGN(jfif->width, mcuw); jh = ALIGN(jfif->height, mcuh); mcuc = jw / mcuw; mcur = jh / mcuh; @@ -469,14 +469,14 @@ int jfif_decode(void *ctxt, BMP *pb) for (h=0; hcomp_info[c].samp_factor_h; h++) { HUFCODEC *hcac = jfif->phcac[jfif->comp_info[c].htab_idx_ac]; HUFCODEC *hcdc = jfif->phcdc[jfif->comp_info[c].htab_idx_dc]; - int fidx = jfif->comp_info[c].qtab_idx; + int fidx = jfif->comp_info[c].qtab_idx; int size, znum, code; int du[64] = {0}; //+ decode dc size = huffman_decode_step(hcdc) & 0xf; if (size) { - code = bitstr_get_bits(bs , size); + code = bitstr_get_bits(bs, size); code = category_decode(code, size); } else { @@ -487,13 +487,13 @@ int jfif_decode(void *ctxt, BMP *pb) //- decode dc //+ decode ac - for (i=1; i<64; ) { + for (i=1; i<64;) { code = huffman_decode_step(hcac); if (code <= 0) break; size = (code >> 0) & 0xf; znum = (code >> 4) & 0xf; i += znum; - code = bitstr_get_bits(bs , size); + code = bitstr_get_bits(bs, size); code = category_decode(code, size); if (i < 64) du[i++] = code; } @@ -583,9 +583,9 @@ static void jfif_encode_du(JFIF *jfif, int type, int du[64], int *dc) HUFCODEC *hfcdc = jfif->phcdc[type]; int *pqtab = jfif->pqtab[type]; void *bs = hfcac->output; - int diff, code, size; - RLEITEM rlelist[63]; - int i, j, n, eob; + int diff, code, size; + RLEITEM rlelist[63]; + int i, j, n, eob; // fdct fdct2d8x8(du, NULL); @@ -643,15 +643,15 @@ void* jfif_encode(BMP *pb) { JFIF *jfif = NULL; void *bs = NULL; - int jw, jh; + int jw, jh; int *yuv_datbuf[3] = {0}; int *ydst, *udst, *vdst; int *isrc, *idst; BYTE *bsrc; - int du[64]= {0}; - int dc[4 ]= {0}; - int i, j, m, n; - int failed = 1; + int du[64]= {0}; + int dc[4]= {0}; + int i, j, m, n; + int failed = 1; // check input params if (!pb) { @@ -677,10 +677,10 @@ void* jfif_encode(BMP *pb) jfif->phcdc[1] = calloc(1, sizeof(HUFCODEC)); jfif->datalen = jfif->width * jfif->height * 2; jfif->databuf = malloc(jfif->datalen); - if ( !jfif->pqtab[0] || !jfif->pqtab[1] - || !jfif->phcac[0] || !jfif->phcac[1] - || !jfif->phcdc[0] || !jfif->phcdc[1] - || !jfif->databuf ) { + if (!jfif->pqtab[0] || !jfif->pqtab[1] + || !jfif->phcac[0] || !jfif->phcac[1] + || !jfif->phcdc[0] || !jfif->phcdc[1] + || !jfif->databuf) { goto done; } @@ -727,7 +727,7 @@ void* jfif_encode(BMP *pb) jfif->comp_info[2].htab_idx_dc = 1; // init jw & jw, init yuv data buffer - jw = ALIGN(pb->width , 16); + jw = ALIGN(pb->width, 16); jh = ALIGN(pb->height, 16); yuv_datbuf[0] = calloc(1, jw * jh / 1 * sizeof(int)); yuv_datbuf[1] = calloc(1, jw * jh / 4 * sizeof(int)); diff --git a/test/bug-hunting/cve/CVE-2019-7156/ole.c b/test/bug-hunting/cve/CVE-2019-7156/ole.c index a760b3079..04467d1b5 100644 --- a/test/bug-hunting/cve/CVE-2019-7156/ole.c +++ b/test/bug-hunting/cve/CVE-2019-7156/ole.c @@ -4,12 +4,12 @@ * @date Wed Jun 11 12:33:01 2003 * Version: $Id: ole.c,v 1.2 2006/02/25 15:28:14 vitus Exp $ * Copyright: Victor B Wagner, 1996-2003 Alex Ott, 2003 - * + * * @brief Parsing structure of MS Office compound document - * + * * This file is part of catdoc project * and distributed under GNU Public License - * + * */ #ifdef HAVE_CONFIG_H #include @@ -27,563 +27,563 @@ const static unsigned char ole_sign[]={0xD0,0xCF,0x11,0xE0,0xA1,0xB1,0x1A,0xE1,0}; -/** +/** * Initializes ole structure - * + * * @param f (FILE *) compound document file, positioned at bufSize - * byte. Might be pipe or socket + * byte. Might be pipe or socket * @param buffer (void *) bytes already read from f * @param bufSize number of bytes already read from f should be less - * than 512 - * - * @return + * than 512 + * + * @return */ FILE* ole_init(FILE *f, void *buffer, size_t bufSize, struct ole_params_t *ole_params) { - unsigned char oleBuf[BBD_BLOCK_SIZE]; - unsigned char *tmpBuf; - FILE *newfile; - int ret=0, i; - long int sbdMaxLen, sbdCurrent, propMaxLen, propCurrent, mblock, msat_size; - oleEntry *tEntry; + unsigned char oleBuf[BBD_BLOCK_SIZE]; + unsigned char *tmpBuf; + FILE *newfile; + int ret=0, i; + long int sbdMaxLen, sbdCurrent, propMaxLen, propCurrent, mblock, msat_size; + oleEntry *tEntry; long int sectorSize; long int shortSectorSize; long int bbdNumBlocks; - /* deleting old data (if it was allocated) */ - ole_finish(ole_params); - - if (fseek(f,0,SEEK_SET) == -1) { - if ( errno == ESPIPE ) { - /* We got non-seekable file, create temp file */ - if((newfile=tmpfile()) == NULL) { - return NULL; - } - if (bufSize > 0) { - ret=fwrite(buffer, 1, bufSize, newfile); - if(ret != bufSize) { - return NULL; - } - } - - while(!feof(f)){ - ret=fread(oleBuf,1,BBD_BLOCK_SIZE,f); - fwrite(oleBuf, 1, ret, newfile); - } - fseek(newfile,0,SEEK_SET); - } else { - return NULL; - } - } else { - newfile=f; - } - fseek(newfile,0,SEEK_END); - ole_params->fileLength=ftell(newfile); + /* deleting old data (if it was allocated) */ + ole_finish(ole_params); - fseek(newfile,0,SEEK_SET); - ret=fread(oleBuf,1,BBD_BLOCK_SIZE,newfile); - if ( ret != BBD_BLOCK_SIZE ) { - return NULL; - } - if (strncmp(oleBuf,ole_sign,8) != 0) { - return NULL; - } + if (fseek(f,0,SEEK_SET) == -1) { + if (errno == ESPIPE) { + /* We got non-seekable file, create temp file */ + if ((newfile=tmpfile()) == NULL) { + return NULL; + } + if (bufSize > 0) { + ret=fwrite(buffer, 1, bufSize, newfile); + if (ret != bufSize) { + return NULL; + } + } + + while (!feof(f)) { + ret=fread(oleBuf,1,BBD_BLOCK_SIZE,f); + fwrite(oleBuf, 1, ret, newfile); + } + fseek(newfile,0,SEEK_SET); + } else { + return NULL; + } + } else { + newfile=f; + } + fseek(newfile,0,SEEK_END); + ole_params->fileLength=ftell(newfile); + + fseek(newfile,0,SEEK_SET); + ret=fread(oleBuf,1,BBD_BLOCK_SIZE,newfile); + if (ret != BBD_BLOCK_SIZE) { + return NULL; + } + if (strncmp(oleBuf,ole_sign,8) != 0) { + return NULL; + } ole_params->sectorSize = 1<sectorSize == 0) { return NULL; } sectorSize = ole_params->sectorSize; ole_params->shortSectorSize = 1<shortSectorSize; - if (shortSectorSize > sectorSize) { + shortSectorSize= ole_params->shortSectorSize; + if (shortSectorSize > sectorSize) { return NULL; } /* Read BBD into memory */ - ole_params->bbdNumBlocks = getulong(oleBuf,0x2c); + ole_params->bbdNumBlocks = getulong(oleBuf,0x2c); bbdNumBlocks = ole_params->bbdNumBlocks; - if((ole_params->BBD=malloc(bbdNumBlocks*sectorSize)) == NULL ) { - return NULL; - } - - if((tmpBuf=malloc(MSAT_ORIG_SIZE)) == NULL ) { - return NULL; - } - memcpy(tmpBuf,oleBuf+0x4c,MSAT_ORIG_SIZE); - mblock=getlong(oleBuf,0x44); - msat_size=getlong(oleBuf,0x48); + if ((ole_params->BBD=malloc(bbdNumBlocks*sectorSize)) == NULL) { + return NULL; + } -/* fprintf(stderr, "msat_size=%ld\n", msat_size); */ + if ((tmpBuf=malloc(MSAT_ORIG_SIZE)) == NULL) { + return NULL; + } + memcpy(tmpBuf,oleBuf+0x4c,MSAT_ORIG_SIZE); + mblock=getlong(oleBuf,0x44); + msat_size=getlong(oleBuf,0x48); - i=0; - while((mblock >= 0) && (i < msat_size)) { - unsigned char *newbuf; -/* fprintf(stderr, "i=%d mblock=%ld\n", i, mblock); */ - if ((newbuf=realloc(tmpBuf, sectorSize*(i+1)+MSAT_ORIG_SIZE)) != NULL) { - tmpBuf=newbuf; - } else { - free(tmpBuf); - ole_finish(ole_params); - return NULL; - } - - fseek(newfile, 512+mblock*sectorSize, SEEK_SET); - if(fread(tmpBuf+MSAT_ORIG_SIZE+(sectorSize-4)*i, - 1, sectorSize, newfile) != sectorSize) { - ole_finish(ole_params); - return NULL; - } +/* fprintf(stderr, "msat_size=%ld\n", msat_size); */ - i++; - mblock=getlong(tmpBuf, MSAT_ORIG_SIZE+(sectorSize-4)*i); - } - -/* fprintf(stderr, "bbdNumBlocks=%ld\n", bbdNumBlocks); */ - for(i=0; i< bbdNumBlocks; i++) { - long int bbdSector=getlong(tmpBuf,4*i); - - if (bbdSector >= ole_params->fileLength/sectorSize || bbdSector < 0) { + i=0; + while ((mblock >= 0) && (i < msat_size)) { + unsigned char *newbuf; +/* fprintf(stderr, "i=%d mblock=%ld\n", i, mblock); */ + if ((newbuf=realloc(tmpBuf, sectorSize*(i+1)+MSAT_ORIG_SIZE)) != NULL) { + tmpBuf=newbuf; + } else { + free(tmpBuf); + ole_finish(ole_params); + return NULL; + } + + fseek(newfile, 512+mblock*sectorSize, SEEK_SET); + if (fread(tmpBuf+MSAT_ORIG_SIZE+(sectorSize-4)*i, + 1, sectorSize, newfile) != sectorSize) { + ole_finish(ole_params); + return NULL; + } + + i++; + mblock=getlong(tmpBuf, MSAT_ORIG_SIZE+(sectorSize-4)*i); + } + +/* fprintf(stderr, "bbdNumBlocks=%ld\n", bbdNumBlocks); */ + for (i=0; i< bbdNumBlocks; i++) { + long int bbdSector=getlong(tmpBuf,4*i); + + if (bbdSector >= ole_params->fileLength/sectorSize || bbdSector < 0) { errno = EINVAL; - ole_finish(ole_params); - return NULL; - } - fseek(newfile, 512+bbdSector*sectorSize, SEEK_SET); - if ( fread(ole_params->BBD+i*sectorSize, 1, sectorSize, newfile) != sectorSize ) { - free(tmpBuf); - ole_finish(ole_params); - return NULL; - } - } - free(tmpBuf); - + ole_finish(ole_params); + return NULL; + } + fseek(newfile, 512+bbdSector*sectorSize, SEEK_SET); + if (fread(ole_params->BBD+i*sectorSize, 1, sectorSize, newfile) != sectorSize) { + free(tmpBuf); + ole_finish(ole_params); + return NULL; + } + } + free(tmpBuf); + /* Read SBD into memory */ - ole_params->sbdLen=0; - sbdMaxLen=10; - sbdCurrent = ole_params->sbdStart = getlong(oleBuf,0x3c); - if (ole_params->sbdStart > 0) { - if((ole_params->SBD=malloc(sectorSize*sbdMaxLen)) == NULL ) { - ole_finish(ole_params); - return NULL; - } - while(1) { - fseek(newfile, 512+sbdCurrent*sectorSize, SEEK_SET); - fread(ole_params->SBD+ole_params->sbdLen*sectorSize, 1, sectorSize, newfile); - ole_params->sbdLen++; - if (ole_params->sbdLen >= sbdMaxLen) { - unsigned char *newSBD; - - sbdMaxLen+=5; - if ((newSBD=realloc(ole_params->SBD, sectorSize*sbdMaxLen)) != NULL) { - ole_params->SBD=newSBD; - } else { - ole_finish(ole_params); - return NULL; - } - } + ole_params->sbdLen=0; + sbdMaxLen=10; + sbdCurrent = ole_params->sbdStart = getlong(oleBuf,0x3c); + if (ole_params->sbdStart > 0) { + if ((ole_params->SBD=malloc(sectorSize*sbdMaxLen)) == NULL) { + ole_finish(ole_params); + return NULL; + } + while (1) { + fseek(newfile, 512+sbdCurrent*sectorSize, SEEK_SET); + fread(ole_params->SBD+ole_params->sbdLen*sectorSize, 1, sectorSize, newfile); + ole_params->sbdLen++; + if (ole_params->sbdLen >= sbdMaxLen) { + unsigned char *newSBD; + + sbdMaxLen+=5; + if ((newSBD=realloc(ole_params->SBD, sectorSize*sbdMaxLen)) != NULL) { + ole_params->SBD=newSBD; + } else { + ole_finish(ole_params); + return NULL; + } + } if (sbdCurrent < 0 || sbdCurrent * 4 >= bbdNumBlocks * sectorSize) { break; } - sbdCurrent = getlong(ole_params->BBD, sbdCurrent*4); - if(sbdCurrent < 0 || - sbdCurrent >= ole_params->fileLength/sectorSize) - break; + sbdCurrent = getlong(ole_params->BBD, sbdCurrent*4); + if (sbdCurrent < 0 || + sbdCurrent >= ole_params->fileLength/sectorSize) + break; } - ole_params->sbdNumber = (ole_params->sbdLen*sectorSize)/shortSectorSize; - } else { - ole_params->SBD=NULL; - } + ole_params->sbdNumber = (ole_params->sbdLen*sectorSize)/shortSectorSize; + } else { + ole_params->SBD=NULL; + } /* Read property catalog into memory */ - ole_params->propLen = 0; - propMaxLen = 5; - propCurrent = ole_params->propStart = getlong(oleBuf,0x30); - if (ole_params->propStart >= 0) { - if((ole_params->properties=malloc(propMaxLen*sectorSize)) == NULL ) { - ole_finish(ole_params); - return NULL; - } - while(1) { -/* fprintf(stderr, "propCurrent=%ld\n",propCurrent); */ - fseek(newfile, 512+propCurrent*sectorSize, SEEK_SET); - fread(ole_params->properties+ole_params->propLen*sectorSize, - 1, sectorSize, newfile); - (ole_params->propLen)++; - if (ole_params->propLen >= propMaxLen) { - unsigned char *newProp; - - propMaxLen+=5; - if ((newProp=realloc(ole_params->properties, propMaxLen*sectorSize)) != NULL) - ole_params->properties=newProp; - else { - ole_finish(ole_params); - return NULL; - } - } - - propCurrent = getlong(ole_params->BBD, propCurrent*4); - if(propCurrent < 0 || - propCurrent >= ole_params->fileLength/sectorSize ) { - break; - } - } + ole_params->propLen = 0; + propMaxLen = 5; + propCurrent = ole_params->propStart = getlong(oleBuf,0x30); + if (ole_params->propStart >= 0) { + if ((ole_params->properties=malloc(propMaxLen*sectorSize)) == NULL) { + ole_finish(ole_params); + return NULL; + } + while (1) { +/* fprintf(stderr, "propCurrent=%ld\n",propCurrent); */ + fseek(newfile, 512+propCurrent*sectorSize, SEEK_SET); + fread(ole_params->properties+ole_params->propLen*sectorSize, + 1, sectorSize, newfile); + (ole_params->propLen)++; + if (ole_params->propLen >= propMaxLen) { + unsigned char *newProp; + + propMaxLen+=5; + if ((newProp=realloc(ole_params->properties, propMaxLen*sectorSize)) != NULL) + ole_params->properties=newProp; + else { + ole_finish(ole_params); + return NULL; + } + } + + propCurrent = getlong(ole_params->BBD, propCurrent*4); + if (propCurrent < 0 || + propCurrent >= ole_params->fileLength/sectorSize) { + break; + } + } + + ole_params->propNumber = (ole_params->propLen*sectorSize)/PROP_BLOCK_SIZE; + ole_params->propCurNumber = 0; + } else { + ole_finish(ole_params); + ole_params->properties = NULL; + return NULL; + } + - ole_params->propNumber = (ole_params->propLen*sectorSize)/PROP_BLOCK_SIZE; - ole_params->propCurNumber = 0; - } else { - ole_finish(ole_params); - ole_params->properties = NULL; - return NULL; - } - - /* Find Root Entry */ - while((tEntry=(oleEntry*)ole_readdir(newfile, ole_params)) != NULL) { - if (tEntry->type == oleRootDir ) { - ole_params->rootEntry=tEntry; - break; - } - ole_close((FILE*)tEntry); - } - ole_params->propCurNumber = 0; - fseek(newfile, 0, SEEK_SET); - if (!ole_params->rootEntry) { + while ((tEntry=(oleEntry*)ole_readdir(newfile, ole_params)) != NULL) { + if (tEntry->type == oleRootDir) { + ole_params->rootEntry=tEntry; + break; + } + ole_close((FILE*)tEntry); + } + ole_params->propCurNumber = 0; + fseek(newfile, 0, SEEK_SET); + if (!ole_params->rootEntry) { errno = EINVAL; - ole_finish(ole_params); - return NULL; - } - return newfile; -} - -/** - * - * - * @param oleBuf - * - * @return - */ -int rightOleType(unsigned char *oleBuf) { - return (oleBuf[0x42] == 1 || oleBuf[0x42] == 2 || - oleBuf[0x42] == 3 || oleBuf[0x42] == 5 ); -} - -/** - * - * - * @param oleBuf - * - * @return - */ -oleType getOleType(unsigned char *oleBuf) { - return (oleType)((unsigned char)oleBuf[0x42]); -} - -/** - * Reads next directory entry from file - * - * @param name buffer for name converted to us-ascii should be at least 33 chars long - * @param size size of file - * - * @return 0 if everything is ok -1 on error - */ -FILE *ole_readdir(FILE *f, struct ole_params_t *ole_params) { - int i, nLen; - unsigned char *oleBuf; - oleEntry *e=NULL; - long int chainMaxLen, chainCurrent; - - if ( ole_params->properties == NULL || ole_params->propCurNumber >= ole_params->propNumber || f == NULL ) - return NULL; - oleBuf=ole_params->properties + ole_params->propCurNumber*PROP_BLOCK_SIZE; - if( !rightOleType(oleBuf)) - return NULL; - if ((e = (oleEntry*)malloc(sizeof(oleEntry))) == NULL) { - return NULL; - } - e->dirPos=oleBuf; - e->type=getOleType(oleBuf); - e->file=f; - e->startBlock=getlong(oleBuf,0x74); - e->blocks=NULL; - - nLen=getshort(oleBuf,0x40); - for (i=0 ; i < nLen/2 && i < OLENAMELENGHT; i++) - e->name[i]=(char)oleBuf[i*2]; - e->name[i]='\0'; - (ole_params->propCurNumber)++; - e->length=getulong(oleBuf,0x78); -/* Read sector chain for object */ - chainMaxLen = 25; - e->numOfBlocks = 0; - chainCurrent = e->startBlock; - e->isBigBlock = (e->length >= 0x1000) || !strcmp(e->name, "Root Entry"); -/* fprintf(stderr, "e->name=%s e->length=%ld\n", e->name, e->length); */ -/* fprintf(stderr, "e->startBlock=%ld BBD=%p\n", e->startBlock, BBD); */ - if (e->startBlock >= 0 && - e->length >= 0 && - (e->startBlock <= - ole_params->fileLength/(e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize))) { - if((e->blocks=malloc(chainMaxLen*sizeof(long int))) == NULL ) { - return NULL; - } - while(1) { -/* fprintf(stderr, "chainCurrent=%ld\n", chainCurrent); */ - e->blocks[e->numOfBlocks++] = chainCurrent; - if (e->numOfBlocks >= chainMaxLen) { - long int *newChain; - chainMaxLen+=25; - if ((newChain=realloc(e->blocks, - chainMaxLen*sizeof(long int))) != NULL) - e->blocks=newChain; - else { - free(e->blocks); - e->blocks=NULL; - return NULL; - } - } - if ( e->isBigBlock ) { - chainCurrent = getlong(ole_params->BBD, chainCurrent*4); - } else if ( ole_params->SBD != NULL ) { - chainCurrent = getlong(ole_params->SBD, chainCurrent*4); - } else { - chainCurrent=-1; - } - if(chainCurrent <= 0 || - chainCurrent >= ( e->isBigBlock ? - ((ole_params->bbdNumBlocks*ole_params->sectorSize)/4) - : ((ole_params->sbdNumber*ole_params->shortSectorSize)/4) ) || - (e->numOfBlocks > - e->length/(e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize))) { -/* fprintf(stderr, "chain End=%ld\n", chainCurrent); */ - break; - } - } - } - - if(e->length > (e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize)*e->numOfBlocks) - e->length = (e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize)*e->numOfBlocks; -/* fprintf(stderr, "READDIR: e->name=%s e->numOfBlocks=%ld length=%ld\n", */ -/* e->name, e->numOfBlocks, e->length); */ - - return (FILE*)e; -} - -/** - * Open stream, which correspond to directory entry last read by - * ole_readdir - * - * - * @return opaque pointer to pass to ole_read, casted to (FILE *) - */ -int ole_open(FILE *stream) { - oleEntry *e=(oleEntry *)stream; - if ( e->type != oleStream) - return -2; - - e->ole_offset=0; - e->file_offset= ftell(e->file); - return 0; -} - -/** - * - * - * @param e - * @param blk - * - * @return - */ -long int calcFileBlockOffset(oleEntry *e, long int blk, struct ole_params_t *ole_params) { - long int res; - if ( e->isBigBlock ) { - res=512+e->blocks[blk]*ole_params->sectorSize; - } else { - long int sbdPerSector=(ole_params->sectorSize)/(ole_params->shortSectorSize); - long int sbdSecNum=e->blocks[blk]/sbdPerSector; - long int sbdSecMod=e->blocks[blk]%sbdPerSector; - - res=512 + ole_params->rootEntry->blocks[sbdSecNum]*ole_params->sectorSize + sbdSecMod*ole_params->shortSectorSize; - } - return res; -} - - -/** - * Reads block from open ole stream interface-compatible with fread - * - * @param ptr pointer to buffer for read to - * @param size size of block - * @param nmemb size in blocks - * @param stream pointer to FILE* structure - * - * @return number of readed blocks - */ -size_t ole_read(void *ptr, size_t size, size_t nmemb, FILE *stream, struct ole_params_t *ole_params) { - oleEntry *e = (oleEntry*)stream; - long int llen = size*nmemb, rread=0, i; - long int blockNumber, modBlock, toReadBlocks, toReadBytes, bytesInBlock; - long int ssize; /**< Size of block */ - long int newoffset; - unsigned char *cptr = ptr; - if( e->ole_offset+llen > e->length ) - llen= e->length - e->ole_offset; - - ssize = (e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize); - blockNumber=e->ole_offset/ssize; -/* fprintf(stderr, "blockNumber=%ld e->numOfBlocks=%ld llen=%ld\n", */ -/* blockNumber, e->numOfBlocks, llen); */ - if ( blockNumber >= e->numOfBlocks || llen <=0 ) - return 0; - - modBlock=e->ole_offset%ssize; - bytesInBlock = ssize - modBlock; - if(bytesInBlock < llen) { - toReadBlocks = (llen-bytesInBlock)/ssize; - toReadBytes = (llen-bytesInBlock)%ssize; - } else { - toReadBlocks = toReadBytes = 0; - } -/* fprintf(stderr, "llen=%ld toReadBlocks=%ld toReadBytes=%ld bytesInBlock=%ld blockNumber=%ld modBlock=%ld\n", */ -/* llen, toReadBlocks, toReadBytes, bytesInBlock, blockNumber, modBlock); */ - newoffset = calcFileBlockOffset(e,blockNumber, ole_params)+modBlock; - if (e->file_offset != newoffset) { - fseek(e->file, e->file_offset=newoffset, SEEK_SET); - } - rread=fread(ptr, 1, min(llen,bytesInBlock), e->file); - e->file_offset += rread; - for(i=0; ifile_offset); - fseek(e->file, e->file_offset=newoffset , SEEK_SET); - readbytes=fread(cptr+rread, 1, min(llen-rread, ssize), e->file); - rread +=readbytes; - e->file_offset +=readbytes; - } - if(toReadBytes > 0) { - int readbytes; - blockNumber++; - newoffset = calcFileBlockOffset(e,blockNumber, ole_params); - fseek(e->file, e->file_offset=newoffset, SEEK_SET); - readbytes=fread(cptr+rread, 1, toReadBytes,e ->file); - rread +=readbytes; - e->file_offset +=readbytes; - } -/* fprintf(stderr, "ole_offset=%ld rread=%ld llen=%ld\n", - e->ole_offset, rread, llen);*/ - e->ole_offset+=rread; - return rread; -} - -/** - * - * - * @param stream - * - * @return - */ -int ole_eof(FILE *stream) { - oleEntry *e=(oleEntry*)stream; -/* fprintf(stderr, "EOF: e->ole_offset=%ld e->length=%ld\n", - e->ole_offset, e->length);*/ - return (e->ole_offset >= e->length); -} - -/** - * - * - */ -void ole_finish(struct ole_params_t *ole_params) { - if ( ole_params->BBD != NULL ) free(ole_params->BBD); - if ( ole_params->SBD != NULL ) free(ole_params->SBD); - if ( ole_params->properties != NULL ) free(ole_params->properties); - if ( ole_params->rootEntry != NULL ) ole_close((FILE*)(ole_params->rootEntry)); - ole_params->properties = ole_params->SBD = ole_params->BBD = NULL; - ole_params->rootEntry = NULL; -} - -/** - * - * - * @param stream - * - * @return - */ -int ole_close(FILE *stream) { - oleEntry *e=(oleEntry*)stream; - if(e == NULL) - return -1; - if (e->blocks != NULL) - free(e->blocks); - free(e); - return 0; + ole_finish(ole_params); + return NULL; + } + return newfile; } /** - * - * - * @param stream pointer to OLE stream structure - * @param offset - * @param whence - * - * @return + * + * + * @param oleBuf + * + * @return */ -int ole_seek(FILE *stream, long offset, int whence, struct ole_params_t *ole_params) { - oleEntry *e=(oleEntry*)stream; - long int new_ole_offset=0, new_file_offset; - int ssize, modBlock, blockNumber; - - switch(whence) { - case SEEK_SET: - new_ole_offset=offset; - break; - - case SEEK_CUR: - new_ole_offset=e->ole_offset+offset; - break; - - case SEEK_END: - new_ole_offset=e->length+offset; - break; - - default: - errno=EINVAL; - return -1; - } - if(new_ole_offset<0) - new_ole_offset=0; - if(new_ole_offset >= e->length) - new_ole_offset=e->length; - - ssize = (e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize); - blockNumber=new_ole_offset/ssize; - if ( blockNumber >= e->numOfBlocks ) - return -1; - - modBlock=new_ole_offset%ssize; - new_file_offset = calcFileBlockOffset(e,blockNumber, ole_params)+modBlock; - fseek(e->file, e->file_offset=new_file_offset, SEEK_SET); - e->ole_offset=new_ole_offset; - - return 0; +int rightOleType(unsigned char *oleBuf) { + return (oleBuf[0x42] == 1 || oleBuf[0x42] == 2 || + oleBuf[0x42] == 3 || oleBuf[0x42] == 5); } -/** +/** + * + * + * @param oleBuf + * + * @return + */ +oleType getOleType(unsigned char *oleBuf) { + return (oleType)((unsigned char)oleBuf[0x42]); +} + +/** + * Reads next directory entry from file + * + * @param name buffer for name converted to us-ascii should be at least 33 chars long + * @param size size of file + * + * @return 0 if everything is ok -1 on error + */ +FILE *ole_readdir(FILE *f, struct ole_params_t *ole_params) { + int i, nLen; + unsigned char *oleBuf; + oleEntry *e=NULL; + long int chainMaxLen, chainCurrent; + + if (ole_params->properties == NULL || ole_params->propCurNumber >= ole_params->propNumber || f == NULL) + return NULL; + oleBuf=ole_params->properties + ole_params->propCurNumber*PROP_BLOCK_SIZE; + if (!rightOleType(oleBuf)) + return NULL; + if ((e = (oleEntry*)malloc(sizeof(oleEntry))) == NULL) { + return NULL; + } + e->dirPos=oleBuf; + e->type=getOleType(oleBuf); + e->file=f; + e->startBlock=getlong(oleBuf,0x74); + e->blocks=NULL; + + nLen=getshort(oleBuf,0x40); + for (i=0; i < nLen/2 && i < OLENAMELENGHT; i++) + e->name[i]=(char)oleBuf[i*2]; + e->name[i]='\0'; + (ole_params->propCurNumber)++; + e->length=getulong(oleBuf,0x78); +/* Read sector chain for object */ + chainMaxLen = 25; + e->numOfBlocks = 0; + chainCurrent = e->startBlock; + e->isBigBlock = (e->length >= 0x1000) || !strcmp(e->name, "Root Entry"); +/* fprintf(stderr, "e->name=%s e->length=%ld\n", e->name, e->length); */ +/* fprintf(stderr, "e->startBlock=%ld BBD=%p\n", e->startBlock, BBD); */ + if (e->startBlock >= 0 && + e->length >= 0 && + (e->startBlock <= + ole_params->fileLength/(e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize))) { + if ((e->blocks=malloc(chainMaxLen*sizeof(long int))) == NULL) { + return NULL; + } + while (1) { +/* fprintf(stderr, "chainCurrent=%ld\n", chainCurrent); */ + e->blocks[e->numOfBlocks++] = chainCurrent; + if (e->numOfBlocks >= chainMaxLen) { + long int *newChain; + chainMaxLen+=25; + if ((newChain=realloc(e->blocks, + chainMaxLen*sizeof(long int))) != NULL) + e->blocks=newChain; + else { + free(e->blocks); + e->blocks=NULL; + return NULL; + } + } + if (e->isBigBlock) { + chainCurrent = getlong(ole_params->BBD, chainCurrent*4); + } else if (ole_params->SBD != NULL) { + chainCurrent = getlong(ole_params->SBD, chainCurrent*4); + } else { + chainCurrent=-1; + } + if (chainCurrent <= 0 || + chainCurrent >= (e->isBigBlock ? + ((ole_params->bbdNumBlocks*ole_params->sectorSize)/4) + : ((ole_params->sbdNumber*ole_params->shortSectorSize)/4)) || + (e->numOfBlocks > + e->length/(e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize))) { +/* fprintf(stderr, "chain End=%ld\n", chainCurrent); */ + break; + } + } + } + + if (e->length > (e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize)*e->numOfBlocks) + e->length = (e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize)*e->numOfBlocks; +/* fprintf(stderr, "READDIR: e->name=%s e->numOfBlocks=%ld length=%ld\n", */ +/* e->name, e->numOfBlocks, e->length); */ + + return (FILE*)e; +} + +/** + * Open stream, which correspond to directory entry last read by + * ole_readdir + * + * + * @return opaque pointer to pass to ole_read, casted to (FILE *) + */ +int ole_open(FILE *stream) { + oleEntry *e=(oleEntry *)stream; + if (e->type != oleStream) + return -2; + + e->ole_offset=0; + e->file_offset= ftell(e->file); + return 0; +} + +/** + * + * + * @param e + * @param blk + * + * @return + */ +long int calcFileBlockOffset(oleEntry *e, long int blk, struct ole_params_t *ole_params) { + long int res; + if (e->isBigBlock) { + res=512+e->blocks[blk]*ole_params->sectorSize; + } else { + long int sbdPerSector=(ole_params->sectorSize)/(ole_params->shortSectorSize); + long int sbdSecNum=e->blocks[blk]/sbdPerSector; + long int sbdSecMod=e->blocks[blk]%sbdPerSector; + + res=512 + ole_params->rootEntry->blocks[sbdSecNum]*ole_params->sectorSize + sbdSecMod*ole_params->shortSectorSize; + } + return res; +} + + +/** + * Reads block from open ole stream interface-compatible with fread + * + * @param ptr pointer to buffer for read to + * @param size size of block + * @param nmemb size in blocks + * @param stream pointer to FILE* structure + * + * @return number of readed blocks + */ +size_t ole_read(void *ptr, size_t size, size_t nmemb, FILE *stream, struct ole_params_t *ole_params) { + oleEntry *e = (oleEntry*)stream; + long int llen = size*nmemb, rread=0, i; + long int blockNumber, modBlock, toReadBlocks, toReadBytes, bytesInBlock; + long int ssize; /**< Size of block */ + long int newoffset; + unsigned char *cptr = ptr; + if (e->ole_offset+llen > e->length) + llen= e->length - e->ole_offset; + + ssize = (e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize); + blockNumber=e->ole_offset/ssize; +/* fprintf(stderr, "blockNumber=%ld e->numOfBlocks=%ld llen=%ld\n", */ +/* blockNumber, e->numOfBlocks, llen); */ + if (blockNumber >= e->numOfBlocks || llen <=0) + return 0; + + modBlock=e->ole_offset%ssize; + bytesInBlock = ssize - modBlock; + if (bytesInBlock < llen) { + toReadBlocks = (llen-bytesInBlock)/ssize; + toReadBytes = (llen-bytesInBlock)%ssize; + } else { + toReadBlocks = toReadBytes = 0; + } +/* fprintf(stderr, "llen=%ld toReadBlocks=%ld toReadBytes=%ld bytesInBlock=%ld blockNumber=%ld modBlock=%ld\n", */ +/* llen, toReadBlocks, toReadBytes, bytesInBlock, blockNumber, modBlock); */ + newoffset = calcFileBlockOffset(e,blockNumber, ole_params)+modBlock; + if (e->file_offset != newoffset) { + fseek(e->file, e->file_offset=newoffset, SEEK_SET); + } + rread=fread(ptr, 1, min(llen,bytesInBlock), e->file); + e->file_offset += rread; + for (i=0; ifile_offset); + fseek(e->file, e->file_offset=newoffset, SEEK_SET); + readbytes=fread(cptr+rread, 1, min(llen-rread, ssize), e->file); + rread +=readbytes; + e->file_offset +=readbytes; + } + if (toReadBytes > 0) { + int readbytes; + blockNumber++; + newoffset = calcFileBlockOffset(e,blockNumber, ole_params); + fseek(e->file, e->file_offset=newoffset, SEEK_SET); + readbytes=fread(cptr+rread, 1, toReadBytes,e->file); + rread +=readbytes; + e->file_offset +=readbytes; + } +/* fprintf(stderr, "ole_offset=%ld rread=%ld llen=%ld\n", + e->ole_offset, rread, llen);*/ + e->ole_offset+=rread; + return rread; +} + +/** + * + * + * @param stream + * + * @return + */ +int ole_eof(FILE *stream) { + oleEntry *e=(oleEntry*)stream; +/* fprintf(stderr, "EOF: e->ole_offset=%ld e->length=%ld\n", + e->ole_offset, e->length);*/ + return (e->ole_offset >= e->length); +} + +/** + * + * + */ +void ole_finish(struct ole_params_t *ole_params) { + if (ole_params->BBD != NULL) free(ole_params->BBD); + if (ole_params->SBD != NULL) free(ole_params->SBD); + if (ole_params->properties != NULL) free(ole_params->properties); + if (ole_params->rootEntry != NULL) ole_close((FILE*)(ole_params->rootEntry)); + ole_params->properties = ole_params->SBD = ole_params->BBD = NULL; + ole_params->rootEntry = NULL; +} + +/** + * + * + * @param stream + * + * @return + */ +int ole_close(FILE *stream) { + oleEntry *e=(oleEntry*)stream; + if (e == NULL) + return -1; + if (e->blocks != NULL) + free(e->blocks); + free(e); + return 0; +} + +/** + * + * + * @param stream pointer to OLE stream structure + * @param offset + * @param whence + * + * @return + */ +int ole_seek(FILE *stream, long offset, int whence, struct ole_params_t *ole_params) { + oleEntry *e=(oleEntry*)stream; + long int new_ole_offset=0, new_file_offset; + int ssize, modBlock, blockNumber; + + switch (whence) { + case SEEK_SET: + new_ole_offset=offset; + break; + + case SEEK_CUR: + new_ole_offset=e->ole_offset+offset; + break; + + case SEEK_END: + new_ole_offset=e->length+offset; + break; + + default: + errno=EINVAL; + return -1; + } + if (new_ole_offset<0) + new_ole_offset=0; + if (new_ole_offset >= e->length) + new_ole_offset=e->length; + + ssize = (e->isBigBlock ? ole_params->sectorSize : ole_params->shortSectorSize); + blockNumber=new_ole_offset/ssize; + if (blockNumber >= e->numOfBlocks) + return -1; + + modBlock=new_ole_offset%ssize; + new_file_offset = calcFileBlockOffset(e,blockNumber, ole_params)+modBlock; + fseek(e->file, e->file_offset=new_file_offset, SEEK_SET); + e->ole_offset=new_ole_offset; + + return 0; +} + +/** * Tell position inside OLE stream - * + * * @param stream pointer to OLE stream - * + * * @return current position inside OLE stream */ long ole_tell(FILE *stream) { - oleEntry *e=(oleEntry*)stream; - return e->ole_offset; + oleEntry *e=(oleEntry*)stream; + return e->ole_offset; } void set_ole_func(struct io_funcs_t *io_funcs) { - io_funcs->catdoc_read=ole_read; - io_funcs->catdoc_eof=ole_eof; - io_funcs->catdoc_seek=ole_seek; - io_funcs->catdoc_tell=ole_tell; + io_funcs->catdoc_read=ole_read; + io_funcs->catdoc_eof=ole_eof; + io_funcs->catdoc_seek=ole_seek; + io_funcs->catdoc_tell=ole_tell; } @@ -598,8 +598,8 @@ int my_fseek(FILE *stream, long offset, int whence, struct ole_params_t *ole_par } void set_std_func(struct io_funcs_t *io_funcs) { - io_funcs->catdoc_read=my_fread; - io_funcs->catdoc_eof=feof; - io_funcs->catdoc_seek=my_fseek; - io_funcs->catdoc_tell=ftell; + io_funcs->catdoc_read=my_fread; + io_funcs->catdoc_eof=feof; + io_funcs->catdoc_seek=my_fseek; + io_funcs->catdoc_tell=ftell; } diff --git a/test/cfg/boost.cpp b/test/cfg/boost.cpp index d9f996f06..f106c66a6 100644 --- a/test/cfg/boost.cpp +++ b/test/cfg/boost.cpp @@ -15,16 +15,13 @@ BOOST_FORCEINLINE void boost_forceinline_test() -{ -} +{} BOOST_NOINLINE void boost_noinline_test() -{ -} +{} BOOST_NORETURN void boost_noreturn_test() -{ -} +{} void print_hello() { @@ -33,10 +30,8 @@ void print_hello() void valid_code(boost::function &pf_print_hello) { - if (BOOST_LIKELY(1)) { - } - if (BOOST_UNLIKELY(0)) { - } + if (BOOST_LIKELY(1)) {} + if (BOOST_UNLIKELY(0)) {} int int1 = 5; boost::endian::endian_reverse_inplace(int1); diff --git a/test/cfg/gtk.c b/test/cfg/gtk.c index d759e68a2..d75f2495a 100644 --- a/test/cfg/gtk.c +++ b/test/cfg/gtk.c @@ -18,13 +18,9 @@ void validCode(int argInt, GHashTableIter * hash_table_iter, GHashTable * hash_t g_assert_cmpstr("test", ==, "test"); // if G_UNLIKELY is not defined this results in a syntax error - if G_UNLIKELY(argInt == 1) { - } else if (G_UNLIKELY(argInt == 2)) { - } + if G_UNLIKELY(argInt == 1) {} else if (G_UNLIKELY(argInt == 2)) {} - if G_LIKELY(argInt == 0) { - } else if (G_LIKELY(argInt == -1)) { - } + if G_LIKELY(argInt == 0) {} else if (G_LIKELY(argInt == -1)) {} printf("%s", _("test")); printf("%s", Q_("a|test")); diff --git a/test/cfg/posix.c b/test/cfg/posix.c index bae5685f1..ca3240d32 100644 --- a/test/cfg/posix.c +++ b/test/cfg/posix.c @@ -345,7 +345,7 @@ void noleak(int x, int y, int z) int fd = open("path", O_RDONLY); FILE *f = fdopen(fd, "rt"); fclose(f); - */ + */ } diff --git a/test/cfg/qt.cpp b/test/cfg/qt.cpp index 59b5dde9f..889001920 100644 --- a/test/cfg/qt.cpp +++ b/test/cfg/qt.cpp @@ -341,7 +341,7 @@ void QStack3() } // Verify that Qt macros do not result in syntax errors, false positives or other issues. -class MacroTest1: public QObject { +class MacroTest1 : public QObject { Q_OBJECT Q_PLUGIN_METADATA(IID "com.foo.bar" FILE "test.json") @@ -373,8 +373,7 @@ void MacroTest2_test() void validCode(int * pIntPtr, QString & qstrArg) { - if (QFile::exists("test")) { - } + if (QFile::exists("test")) {} if (pIntPtr != Q_NULLPTR) { *pIntPtr = 5; @@ -384,8 +383,7 @@ void validCode(int * pIntPtr, QString & qstrArg) forever { } } else if (pIntPtr && *pIntPtr == 2) { - Q_FOREVER { - } + Q_FOREVER {} } if (Q_LIKELY(pIntPtr)) {} @@ -399,13 +397,11 @@ void validCode(int * pIntPtr, QString & qstrArg) //#9650 QString qstr1(qstrArg); - if (qstr1.length() == 1) { - } else { + if (qstr1.length() == 1) {} else { qstr1.chop(1); if (qstr1.length() == 1) {} } - if (qstr1.length() == 1) { - } else { + if (qstr1.length() == 1) {} else { qstr1.remove(1); if (qstr1.length() == 1) {} } diff --git a/test/cfg/std.c b/test/cfg/std.c index 211ac393b..7856cedf5 100644 --- a/test/cfg/std.c +++ b/test/cfg/std.c @@ -2698,7 +2698,7 @@ void uninitvar_memset(void) void uninitvar_wmemset(void) { wchar_t *cs; - wchar_t c; + wchar_t c; size_t n; // cppcheck-suppress uninitvar (void)wmemset(cs,c,n); @@ -2861,7 +2861,7 @@ void uninitvar_bsearch(void) size_t num; size_t size; // cppcheck-suppress uninitvar - (void)bsearch(key,base,num,size,(int(*)(const void*,const void*)) strcmp); + (void)bsearch(key,base,num,size,(int (*)(const void*,const void*))strcmp); } void uninitvar_qsort(void) @@ -2870,7 +2870,7 @@ void uninitvar_qsort(void) size_t n; size_t size; // cppcheck-suppress uninitvar - (void)qsort(base,n,size, (int(*)(const void*,const void*)) strcmp); + (void)qsort(base,n,size, (int (*)(const void*,const void*))strcmp); } void uninitvar_putc(void) @@ -3273,7 +3273,7 @@ void uninitvar_strcpy_s(char * strDest, ssize_t s, char *source) { char *strUninit1; char *strUninit2; - ssize_t size; + ssize_t size; // cppcheck-suppress uninitvar (void)strcpy_s(strUninit1, 1, "a"); @@ -4501,7 +4501,7 @@ void invalidPrintfArgType_printf(void) // #7016 uint8_t n = 7; // TODO cppcheck-suppress invalidPrintfArgType_uint - printf("%"PRIi16"\n", n); + printf("%" PRIi16 "\n", n); } diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index 163c6957c..5d9f4ee43 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -2068,7 +2068,7 @@ void uninitvar_memset(void) void uninitvar_wmemset(void) { wchar_t *cs; - wchar_t c; + wchar_t c; size_t n; // cppcheck-suppress uninitvar (void)std::wmemset(cs,c,n); @@ -2212,20 +2212,20 @@ void uninivar_bsearch(void) size_t num; size_t size; // cppcheck-suppress uninitvar - (void)std::bsearch(key,base,num,size,(int(*)(const void*,const void*)) strcmp); + (void)std::bsearch(key,base,num,size,(int (*)(const void*,const void*))strcmp); } void minsize_bsearch(const void* key, const void* base, size_t num, size_t size, int (*compar)(const void*,const void*)) { - int Base [3] = {42, 43, 44}; + int Base[3] = {42, 43, 44}; - (void)std::bsearch(key,Base,2,size,(int(*)(const void*,const void*)) strcmp); - (void)std::bsearch(key,Base,3,size,(int(*)(const void*,const void*)) strcmp); - (void)std::bsearch(key,Base,4,size,(int(*)(const void*,const void*)) strcmp); + (void)std::bsearch(key,Base,2,size,(int (*)(const void*,const void*))strcmp); + (void)std::bsearch(key,Base,3,size,(int (*)(const void*,const void*))strcmp); + (void)std::bsearch(key,Base,4,size,(int (*)(const void*,const void*))strcmp); - (void)std::bsearch(key,base,2,size,(int(*)(const void*,const void*)) strcmp); + (void)std::bsearch(key,base,2,size,(int (*)(const void*,const void*))strcmp); } void uninitvar_qsort(void) @@ -2234,7 +2234,7 @@ void uninitvar_qsort(void) size_t n; size_t size; // cppcheck-suppress uninitvar - (void)std::qsort(base,n,size, (int(*)(const void*,const void*)) strcmp); + (void)std::qsort(base,n,size, (int (*)(const void*,const void*))strcmp); } void uninitvar_putc(void) @@ -3477,7 +3477,7 @@ void nullPointer_wmemcmp(wchar_t *p) #include #include -#define pred [](int i){return i==0;} +#define pred [] (int i) {return i==0;} void stdalgorithm(const std::list &ints1, const std::list &ints2) diff --git a/test/cfg/windows.cpp b/test/cfg/windows.cpp index 239770546..6428fa274 100644 --- a/test/cfg/windows.cpp +++ b/test/cfg/windows.cpp @@ -842,32 +842,31 @@ void oppositeInnerCondition_SUCCEEDED_FAILED(HRESULT hr) { if (SUCCEEDED(hr)) { // TODO ticket #8596 cppcheck-suppress oppositeInnerCondition - if (FAILED(hr)) { - } + if (FAILED(hr)) {} } } /*HANDLE WINAPI CreateThread( - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ SIZE_T dwStackSize, - _In_ LPTHREAD_START_ROUTINE lpStartAddress, - _In_opt_ LPVOID lpParameter, - _In_ DWORD dwCreationFlags, - _Out_opt_ LPDWORD lpThreadId -);*/ -HANDLE test_CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, - SIZE_T dwStackSize, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ SIZE_T dwStackSize, + _In_ LPTHREAD_START_ROUTINE lpStartAddress, + _In_opt_ LPVOID lpParameter, + _In_ DWORD dwCreationFlags, + _Out_opt_ LPDWORD lpThreadId + );*/ +HANDLE test_CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId) + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId) { // Create uninitialized variables - LPSECURITY_ATTRIBUTES uninit_lpThreadAttributes; - SIZE_T uninit_dwStackSize; + LPSECURITY_ATTRIBUTES uninit_lpThreadAttributes; + SIZE_T uninit_dwStackSize; LPTHREAD_START_ROUTINE uninit_lpStartAddress; - LPVOID uninit_lpParameter; - DWORD uninit_dwCreationFlags; + LPVOID uninit_lpParameter; + DWORD uninit_dwCreationFlags; // cppcheck-suppress leakReturnValNotUsed // cppcheck-suppress uninitvar @@ -996,15 +995,15 @@ void GetShortPathName_validCode(TCHAR* lpszPath) TCHAR* buffer = new TCHAR[length]; length = GetShortPathName(lpszPath, buffer, length); if (length == 0) { - delete [] buffer; + delete[] buffer; _tprintf(TEXT("error")); return; } _tprintf(TEXT("long name = %s short name = %s"), lpszPath, buffer); - delete [] buffer; + delete[] buffer; } -class MyClass :public CObject { +class MyClass : public CObject { DECLARE_DYNAMIC(MyClass) DECLARE_DYNCREATE(MyClass) DECLARE_SERIAL(MyClass) diff --git a/test/cli/proj-inline-suppress/3.cpp b/test/cli/proj-inline-suppress/3.cpp index 7ecd1c0e8..246ffbfe1 100644 --- a/test/cli/proj-inline-suppress/3.cpp +++ b/test/cli/proj-inline-suppress/3.cpp @@ -1,6 +1,6 @@ // From forum: https://sourceforge.net/p/cppcheck/discussion/general/thread/e67653efdb/ void foo() { // cppcheck-suppress zerodiv - int x = 10000 / 0; + int x = 10000 / 0; } diff --git a/test/cli/proj-suppress-syntaxError/1.c b/test/cli/proj-suppress-syntaxError/1.c index ebc333b99..c4521b0d6 100644 --- a/test/cli/proj-suppress-syntaxError/1.c +++ b/test/cli/proj-suppress-syntaxError/1.c @@ -3,8 +3,6 @@ void validCode(int argInt) { // if G_UNLIKELY is not defined this results in a syntax error - if G_UNLIKELY(argInt == 1) { - } else if (G_UNLIKELY(argInt == 2)) { - } + if G_UNLIKELY(argInt == 1) {} else if (G_UNLIKELY(argInt == 2)) {} } diff --git a/test/options.cpp b/test/options.cpp index 2e4a2f228..27e2faa47 100644 --- a/test/options.cpp +++ b/test/options.cpp @@ -17,7 +17,7 @@ #include "options.h" options::options(int argc, const char* const argv[]) - :mWhichTests(argv + 1, argv + argc) + : mWhichTests(argv + 1, argv + argc) ,mQuiet(mWhichTests.count("-q") != 0) ,mHelp(mWhichTests.count("-h") != 0 || mWhichTests.count("--help")) ,mExe(argv[0]) diff --git a/test/redirect.h b/test/redirect.h index e68fbdfd3..a97f9c735 100644 --- a/test/redirect.h +++ b/test/redirect.h @@ -24,10 +24,10 @@ extern std::ostringstream errout; extern std::ostringstream output; /** - * @brief Utility class for capturing cout and cerr to ostringstream buffers - * for later use. Uses RAII to stop redirection when the object goes out of - * scope. - */ + * @brief Utility class for capturing cout and cerr to ostringstream buffers + * for later use. Uses RAII to stop redirection when the object goes out of + * scope. + */ class RedirectOutputError { public: /** Set up redirection, flushing anything in the pipes. */ @@ -58,7 +58,7 @@ public: } /** Normally called after getOutput() to prevent same text to be returned - twice. */ + twice. */ void clearOutput() { _out.str(""); } @@ -69,7 +69,7 @@ public: } /** Normally called after getErrout() to prevent same text to be returned - twice. */ + twice. */ void clearErrout() { _err.str(""); } @@ -81,7 +81,7 @@ private: std::streambuf *_oldCerr; }; -#define REDIRECT RedirectOutputError redir; do {} while(false) +#define REDIRECT RedirectOutputError redir; do {} while (false) #define GET_REDIRECT_OUTPUT redir.getOutput() #define CLEAR_REDIRECT_OUTPUT redir.clearOutput() #define GET_REDIRECT_ERROUT redir.getErrout() diff --git a/test/synthetic/controlflow.c b/test/synthetic/controlflow.c index 845a42ab2..c92106df0 100644 --- a/test/synthetic/controlflow.c +++ b/test/synthetic/controlflow.c @@ -6,68 +6,68 @@ int buf[2]; void in_if(int a) { - if (a==100) - buf[a] = 0; // BUG + if (a==100) + buf[a] = 0; // BUG } void before_if(int a) { - buf[a] = 0; // WARNING - if (a==100) {} + buf[a] = 0; // WARNING + if (a==100) {} } void after_if(int a) { - if (a==100) {} - buf[a] = 0; // WARNING + if (a==100) {} + buf[a] = 0; // WARNING } void in_for(void) { - int x; - for (x = 0; x<100; x++) { - buf[x] = 0; // BUG - } + int x; + for (x = 0; x<100; x++) { + buf[x] = 0; // BUG + } } void after_for(void) { - int x; - for (x = 0; x<100; x++) {} - buf[x] = 0; // BUG + int x; + for (x = 0; x<100; x++) {} + buf[x] = 0; // BUG } void in_switch(int x) { - switch (x) { - case 100: - buf[x] = 0; // BUG - break; - } + switch (x) { + case 100: + buf[x] = 0; // BUG + break; + } } void before_switch(int x) { - buf[x] = 0; // WARNING - switch (x) { - case 100: - break; - } + buf[x] = 0; // WARNING + switch (x) { + case 100: + break; + } } void after_switch(int x) { - switch (x) { - case 100: - break; - } - buf[x] = 0; // WARNING + switch (x) { + case 100: + break; + } + buf[x] = 0; // WARNING } void in_while(void) { - int x = 0; - while (x<100) { - buf[x] = 0; // BUG - x++; - } + int x = 0; + while (x<100) { + buf[x] = 0; // BUG + x++; + } } void after_while(void) { - int x = 0; - while (x<100) - x++; - buf[x] = 0; // BUG + int x = 0; + while (x<100) + x++; + buf[x] = 0; // BUG } diff --git a/test/synthetic/data.c b/test/synthetic/data.c index 87d49f1e3..9d2a5d578 100644 --- a/test/synthetic/data.c +++ b/test/synthetic/data.c @@ -3,66 +3,66 @@ int TestData[10]; int g; void global() { - g = 1000; - TestData[g] = 0; // BUG + g = 1000; + TestData[g] = 0; // BUG } int garr[10]; void global_array() { - garr[3] = 1000; - TestData[garr[3]] = 0; // BUG + garr[3] = 1000; + TestData[garr[3]] = 0; // BUG } int *gp; void global_pointer() { - *gp = 1000; - TestData[*gp] = 0; // BUG + *gp = 1000; + TestData[*gp] = 0; // BUG } void local() { - int x; - x = 1000; - TestData[x] = 0; // BUG + int x; + x = 1000; + TestData[x] = 0; // BUG } void local_array() { - int arr[10]; - arr[3] = 1000; - TestData[arr[3]] = 0; // BUG + int arr[10]; + arr[3] = 1000; + TestData[arr[3]] = 0; // BUG } void local_alias_1() { - int x; - int *p = &x; - *p = 1000; - TestData[*p] = 0; // BUG + int x; + int *p = &x; + *p = 1000; + TestData[*p] = 0; // BUG } void local_alias_2() { - int x; - int *p = &x; - x = 1000; - TestData[*p] = 0; // BUG + int x; + int *p = &x; + x = 1000; + TestData[*p] = 0; // BUG } struct ABC { - int a; - int b[10]; - int c; + int a; + int b[10]; + int c; }; void struct_member_init() { - struct ABC abc = {1000,{0},3}; - TestData[abc.a] = 0; // BUG + struct ABC abc = {1000,{0},3}; + TestData[abc.a] = 0; // BUG } void struct_member_assign(struct ABC *abc) { - abc->a = 1000; - TestData[abc->a] = 0; // BUG + abc->a = 1000; + TestData[abc->a] = 0; // BUG } void struct_arraymember(struct ABC *abc) { - abc->b[3] = 1000; - TestData[abc->b[3]] = 0; // BUG + abc->b[3] = 1000; + TestData[abc->b[3]] = 0; // BUG } diff --git a/test/synthetic/functions.c b/test/synthetic/functions.c index e94082a46..bc6639cb9 100644 --- a/test/synthetic/functions.c +++ b/test/synthetic/functions.c @@ -3,20 +3,22 @@ int TestData[100]; void par_not_dependant(int par) { - TestData[par] = 0; // BUG + TestData[par] = 0; // BUG } void par_dependant(int x, int y) { - if (x < 10) - TestData[y] = 0; // BUG + if (x < 10) + TestData[y] = 0; // BUG } void call(int x) { - par_not_dependant(1000); - par_dependant(0, 1000); + par_not_dependant(1000); + par_dependant(0, 1000); } -int getLargeIndex() { return 1000; } +int getLargeIndex() { + return 1000; +} void return_value() { - TestData[getLargeIndex()] = 0; // BUG + TestData[getLargeIndex()] = 0; // BUG } diff --git a/test/synthetic/ub.c b/test/synthetic/ub.c index f0ac31ffe..1ded7b524 100644 --- a/test/synthetic/ub.c +++ b/test/synthetic/ub.c @@ -1,17 +1,49 @@ -void alias() { int x; int *ip=&x; float *fp = (float *)ip; } -int buffer_overflow() { int x[10]={0}; return x[100]; } -int dead_pointer(int a) { int *p=&a; if (a) { int x=0; p = &x; } return *p; } -int division_by_zero() { return 100 / 0; } -int float_to_int() { double d=1E100; return (int)d; } -void negative_size(int sz) { if (sz < 0) { int buf[sz]; } } +void alias() { + int x; int *ip=&x; float *fp = (float *)ip; +} +int buffer_overflow() { + int x[10]={0}; return x[100]; +} +int dead_pointer(int a) { + int *p=&a; if (a) { int x=0; p = &x; } return *p; +} +int division_by_zero() { + return 100 / 0; +} +int float_to_int() { + double d=1E100; return (int)d; +} +void negative_size(int sz) { + if (sz < 0) { int buf[sz]; } +} int no_return() {} -int null_pointer() { int *p = 0; return *p; } -int *pointer_arithmetic() { static int buf[10]; return buf + 100; } -unsigned char pointer_to_u8() { static int buf[10]; return (int*)buf; } -int pointer_subtraction() { char a[10]; char b[10]; return b-a; } -int pointer_comparison() { char a[10]; char b[10]; return b> 1; return intmax * 2; } -void string_literal() { *((char *)"hello") = 0; } -int uninit() { int x; return x + 2; } +int null_pointer() { + int *p = 0; return *p; +} +int *pointer_arithmetic() { + static int buf[10]; return buf + 100; +} +unsigned char pointer_to_u8() { + static int buf[10]; return (int*)buf; +} +int pointer_subtraction() { + char a[10]; char b[10]; return b-a; +} +int pointer_comparison() { + char a[10]; char b[10]; return b> 1; return intmax * 2; +} +void string_literal() { + *((char *)"hello") = 0; +} +int uninit() { + int x; return x + 2; +} diff --git a/test/test64bit.cpp b/test/test64bit.cpp index d9451cc86..d67c8ce3a 100644 --- a/test/test64bit.cpp +++ b/test/test64bit.cpp @@ -25,8 +25,7 @@ class Test64BitPortability : public TestFixture { public: - Test64BitPortability() : TestFixture("Test64BitPortability") { - } + Test64BitPortability() : TestFixture("Test64BitPortability") {} private: Settings settings; diff --git a/test/testastutils.cpp b/test/testastutils.cpp index 41831050f..5bb57fb2f 100644 --- a/test/testastutils.cpp +++ b/test/testastutils.cpp @@ -28,8 +28,7 @@ class TestAstUtils : public TestFixture { public: - TestAstUtils() : TestFixture("TestAstUtils") { - } + TestAstUtils() : TestFixture("TestAstUtils") {} private: diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 6b70f08df..57253dd60 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -25,8 +25,7 @@ class TestAutoVariables : public TestFixture { public: - TestAutoVariables() : TestFixture("TestAutoVariables") { - } + TestAutoVariables() : TestFixture("TestAutoVariables") {} private: Settings settings; diff --git a/test/testbool.cpp b/test/testbool.cpp index d9f0323f1..c93054593 100644 --- a/test/testbool.cpp +++ b/test/testbool.cpp @@ -25,8 +25,7 @@ class TestBool : public TestFixture { public: - TestBool() : TestFixture("TestBool") { - } + TestBool() : TestFixture("TestBool") {} private: Settings settings; @@ -152,7 +151,7 @@ private: " const int *rmat = n < 4 ? " /* OK */ " ctx->q_intra_matrix :" " ctx->q_chroma_intra_matrix;\n" - "}", /*experimental=*/false, "test.c"); + "}", /*experimental=*/ false, "test.c"); ASSERT_EQUALS("[test.c:3]: (error) Boolean value assigned to pointer.\n", errout.str()); // ticket #6588 (c++ mode) @@ -171,7 +170,7 @@ private: " char* m1 = compare(a, b) < 0\n" " ? (compare(b, c) < 0 ? b : (compare(a, c) < 0 ? c : a))\n" " : (compare(a, c) < 0 ? a : (compare(b, c) < 0 ? c : b));\n" - "}", /*experimental=*/false, "test.c"); + "}", /*experimental=*/ false, "test.c"); ASSERT_EQUALS("", errout.str()); // #7381 @@ -296,7 +295,7 @@ private: " if ((5 && x) < 0)\n" " a++;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer.\n", errout.str()); check("void f(int x) {\n" @@ -309,7 +308,7 @@ private: " if ((5 && x) > 1)\n" " a++;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer.\n", errout.str()); @@ -323,7 +322,7 @@ private: " if (0 > (5 && x))\n" " a++;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer.\n", errout.str()); check("void f(int x) {\n" @@ -336,7 +335,7 @@ private: " if (1 < (5 && x))\n" " a++;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer.\n", errout.str()); check("void f(bool x ) {\n" diff --git a/test/testboost.cpp b/test/testboost.cpp index 63eff597e..271338935 100644 --- a/test/testboost.cpp +++ b/test/testboost.cpp @@ -25,8 +25,7 @@ class TestBoost : public TestFixture { public: - TestBoost() : TestFixture("TestBoost") { - } + TestBoost() : TestFixture("TestBoost") {} private: Settings settings; diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 974547bd5..841f3cb9d 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -33,8 +33,7 @@ class TestBufferOverrun : public TestFixture { public: - TestBufferOverrun() : TestFixture("TestBufferOverrun") { - } + TestBufferOverrun() : TestFixture("TestBufferOverrun") {} private: Settings settings0; @@ -3431,7 +3430,7 @@ private: ASSERT_EQUALS(15, CheckBufferOverrun::countSprintfLength("str%s%d%d", multipleParams)); ASSERT_EQUALS(26, CheckBufferOverrun::countSprintfLength("str%-6s%08ld%08ld", multipleParams)); } - */ + */ // extracttests.disable diff --git a/test/testcharvar.cpp b/test/testcharvar.cpp index 558ec2a2e..4f4a4fe5c 100644 --- a/test/testcharvar.cpp +++ b/test/testcharvar.cpp @@ -26,8 +26,7 @@ class TestCharVar : public TestFixture { public: - TestCharVar() : TestFixture("TestCharVar") { - } + TestCharVar() : TestFixture("TestCharVar") {} private: Settings settings; diff --git a/test/testclangimport.cpp b/test/testclangimport.cpp index f5e5fcbd4..0d501efc3 100644 --- a/test/testclangimport.cpp +++ b/test/testclangimport.cpp @@ -21,11 +21,10 @@ #include "testsuite.h" -class TestClangImport: public TestFixture { +class TestClangImport : public TestFixture { public: TestClangImport() - :TestFixture("TestClangImport") { - } + : TestFixture("TestClangImport") {} private: diff --git a/test/testclass.cpp b/test/testclass.cpp index cb8625917..f53cfcb3e 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -27,8 +27,7 @@ class TestClass : public TestFixture { public: - TestClass() : TestFixture("TestClass") { - } + TestClass() : TestFixture("TestClass") {} private: Settings settings0; @@ -41,13 +40,13 @@ private: // Load std.cfg configuration { const char xmldata[] = "\n" - "\n" - " \n" - " malloc\n" - " free\n" - " \n" - " \n" - ""; + "\n" + " \n" + " malloc\n" + " free\n" + " \n" + " \n" + ""; tinyxml2::XMLDocument doc; doc.Parse(xmldata, sizeof(xmldata)); settings0.library.load(doc); @@ -6809,7 +6808,7 @@ private: } - void checkSelfInitialization(const char code []) { + void checkSelfInitialization(const char code[]) { // Clear the error log errout.str(""); diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 1d7c8e918..546c9dd0e 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -34,8 +34,7 @@ class TestCmdlineParser : public TestFixture { public: TestCmdlineParser() : TestFixture("TestCmdlineParser") - , defParser(&settings) { - } + , defParser(&settings) {} private: Settings settings; @@ -975,7 +974,7 @@ private: ASSERT_EQUALS("src/", parser.getIgnoredPaths()[0]); ASSERT_EQUALS("module/", parser.getIgnoredPaths()[1]); } - */ + */ void ignorepaths4() { REDIRECT; const char * const argv[] = {"cppcheck", "-i", "src", "-i", "module", "file.cpp"}; @@ -994,7 +993,7 @@ private: ASSERT_EQUALS(1, parser.getIgnoredPaths().size()); ASSERT_EQUALS("foo.cpp", parser.getIgnoredPaths()[0]); } - */ + */ void ignorefilepaths2() { REDIRECT; const char * const argv[] = {"cppcheck", "-isrc/foo.cpp", "file.cpp"}; diff --git a/test/testcondition.cpp b/test/testcondition.cpp index c38341f96..3e7c25b96 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -30,8 +30,7 @@ class TestCondition : public TestFixture { public: - TestCondition() : TestFixture("TestCondition") { - } + TestCondition() : TestFixture("TestCondition") {} private: Settings settings0; @@ -49,9 +48,9 @@ private: settings0.severity.enable(Severity::warning); const char cfg[] = "\n" - "\n" - " \n" - ""; + "\n" + " \n" + ""; tinyxml2::XMLDocument xmldoc; xmldoc.Parse(cfg, sizeof(cfg)); settings1.severity.enable(Severity::style); @@ -905,7 +904,7 @@ private: " if ((x != 1) || (x != 3) && (y == 1))\n" " a++;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'x!=3' is always true\n", errout.str()); check("void f(int x) {\n" @@ -1073,21 +1072,21 @@ private: " if (x >= 3 || x <= 3)\n" " a++;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x <= 3.\n", errout.str()); check("void f(int x) {\n" " if (x >= 3 || x < 3)\n" " a++;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x >= 3 || x < 3.\n", errout.str()); check("void f(int x) {\n" " if (x > 3 || x <= 3)\n" " a++;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (warning) Logical disjunction always evaluates to true: x > 3 || x <= 3.\n", errout.str()); check("void f(int x) {\n" diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 60164b491..b67635b5f 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -25,8 +25,7 @@ class TestConstructors : public TestFixture { public: - TestConstructors() : TestFixture("TestConstructors") { - } + TestConstructors() : TestFixture("TestConstructors") {} private: Settings settings; @@ -600,7 +599,7 @@ private: "public:\n" " A(wxWindow *parent,\n" " wxWindowID id = 1,\n" - " const wxString &title = wxT(""),\n" + " const wxString &title = wxT(" "),\n" " const wxPoint& pos = wxDefaultPosition,\n" " const wxSize& size = wxDefaultSize,\n" " long style = wxDIALOG_NO_PARENT | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX);\n" diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index 13d6d1b64..86a9e75ad 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -29,8 +29,7 @@ class TestCppcheck : public TestFixture { public: - TestCppcheck() : TestFixture("TestCppcheck") { - } + TestCppcheck() : TestFixture("TestCppcheck") {} private: diff --git a/test/testerrorlogger.cpp b/test/testerrorlogger.cpp index 7e59a08a9..847f99ee9 100644 --- a/test/testerrorlogger.cpp +++ b/test/testerrorlogger.cpp @@ -29,8 +29,7 @@ class TestErrorLogger : public TestFixture { public: - TestErrorLogger() : TestFixture("TestErrorLogger"), fooCpp5("foo.cpp", 5, 1), barCpp8("bar.cpp", 8, 1) { - } + TestErrorLogger() : TestFixture("TestErrorLogger"), fooCpp5("foo.cpp", 5, 1), barCpp8("bar.cpp", 8, 1) {} private: const ErrorMessage::FileLocation fooCpp5; diff --git a/test/testexceptionsafety.cpp b/test/testexceptionsafety.cpp index 263bace8f..3a28021cc 100644 --- a/test/testexceptionsafety.cpp +++ b/test/testexceptionsafety.cpp @@ -25,8 +25,7 @@ class TestExceptionSafety : public TestFixture { public: - TestExceptionSafety() : TestFixture("TestExceptionSafety") { - } + TestExceptionSafety() : TestFixture("TestExceptionSafety") {} private: Settings settings; diff --git a/test/testexprengine.cpp b/test/testexprengine.cpp index 387b69259..b3cd8e55d 100644 --- a/test/testexprengine.cpp +++ b/test/testexprengine.cpp @@ -29,8 +29,7 @@ class TestExprEngine : public TestFixture { public: - TestExprEngine() : TestFixture("TestExprEngine") { - } + TestExprEngine() : TestFixture("TestExprEngine") {} private: void run() OVERRIDE { diff --git a/test/testfilelister.cpp b/test/testfilelister.cpp index e19e62c67..e1348c9fb 100644 --- a/test/testfilelister.cpp +++ b/test/testfilelister.cpp @@ -25,11 +25,10 @@ #include #include -class TestFileLister: public TestFixture { +class TestFileLister : public TestFixture { public: TestFileLister() - :TestFixture("TestFileLister") { - } + : TestFixture("TestFileLister") {} private: void run() OVERRIDE { diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index 9b37f8786..8ee5db901 100644 --- a/test/testfunctions.cpp +++ b/test/testfunctions.cpp @@ -28,8 +28,7 @@ class TestFunctions : public TestFixture { public: - TestFunctions() : TestFixture("TestFunctions") { - } + TestFunctions() : TestFixture("TestFunctions") {} private: Settings settings; diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index d7e3c4809..0be286b19 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -27,8 +27,7 @@ class TestGarbage : public TestFixture { public: - TestGarbage() : TestFixture("TestGarbage") { - } + TestGarbage() : TestFixture("TestGarbage") {} private: Settings settings; @@ -267,8 +266,7 @@ private: // run alternate check first. It should only ensure stability - so we catch exceptions here. try { checkCodeInternal(code, alternatefilename); - } catch (const InternalError&) { - } + } catch (const InternalError&) {} return checkCodeInternal(code, filename); } @@ -950,9 +948,9 @@ private: } void garbageCode121() { // #2585 - ASSERT_THROW(checkCode("abcdef?""?<" - "123456?""?>" - "+?""?="), InternalError); + ASSERT_THROW(checkCode("abcdef?" "?<" + "123456?" "?>" + "+?" "?="), InternalError); } void garbageCode122() { // #6303 @@ -1580,7 +1578,7 @@ private: // #8752 void garbageCode199() { - checkCode("d f(){e n00e0[]n00e0&""0+f=0}"); + checkCode("d f(){e n00e0[]n00e0&" "0+f=0}"); } // #8757 diff --git a/test/testimportproject.cpp b/test/testimportproject.cpp index e7593af08..07f626e57 100644 --- a/test/testimportproject.cpp +++ b/test/testimportproject.cpp @@ -33,8 +33,7 @@ public: class TestImportProject : public TestFixture { public: - TestImportProject() : TestFixture("TestImportProject") { - } + TestImportProject() : TestFixture("TestImportProject") {} private: diff --git a/test/testincompletestatement.cpp b/test/testincompletestatement.cpp index d36f296d0..a99900b57 100644 --- a/test/testincompletestatement.cpp +++ b/test/testincompletestatement.cpp @@ -27,8 +27,7 @@ class TestIncompleteStatement : public TestFixture { public: - TestIncompleteStatement() : TestFixture("TestIncompleteStatement") { - } + TestIncompleteStatement() : TestFixture("TestIncompleteStatement") {} private: Settings settings; diff --git a/test/testinternal.cpp b/test/testinternal.cpp index 4aa6079f1..5200334fc 100644 --- a/test/testinternal.cpp +++ b/test/testinternal.cpp @@ -25,8 +25,7 @@ class TestInternal : public TestFixture { public: - TestInternal() : TestFixture("TestInternal") { - } + TestInternal() : TestFixture("TestInternal") {} private: Settings settings; diff --git a/test/testio.cpp b/test/testio.cpp index b225aa8ca..d94e3009a 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -26,8 +26,7 @@ class TestIO : public TestFixture { public: - TestIO() : TestFixture("TestIO") { - } + TestIO() : TestFixture("TestIO") {} private: Settings settings; @@ -775,22 +774,22 @@ private: } -#define TEST_SCANF_CODE(format, type)\ +#define TEST_SCANF_CODE(format, type) \ "void f(){" type " x; scanf(\"" format "\", &x);}" -#define TEST_SCANF_ERR(format, formatStr, type)\ +#define TEST_SCANF_ERR(format, formatStr, type) \ "[test.cpp:1]: (warning) " format " in format string (no. 1) requires '" formatStr " *' but the argument type is '" type " *'.\n" -#define TEST_SCANF_ERR_AKA(format, formatStr, type, akaType)\ +#define TEST_SCANF_ERR_AKA(format, formatStr, type, akaType) \ "[test.cpp:1]: (portability) " format " in format string (no. 1) requires '" formatStr " *' but the argument type is '" type " * {aka " akaType " *}'.\n" -#define TEST_PRINTF_CODE(format, type)\ +#define TEST_PRINTF_CODE(format, type) \ "void f(" type " x){printf(\"" format "\", x);}" -#define TEST_PRINTF_ERR(format, requiredType, actualType)\ +#define TEST_PRINTF_ERR(format, requiredType, actualType) \ "[test.cpp:1]: (warning) " format " in format string (no. 1) requires '" requiredType "' but the argument type is '" actualType "'.\n" -#define TEST_PRINTF_ERR_AKA(format, requiredType, actualType, akaType)\ +#define TEST_PRINTF_ERR_AKA(format, requiredType, actualType, akaType) \ "[test.cpp:1]: (portability) " format " in format string (no. 1) requires '" requiredType "' but the argument type is '" actualType " {aka " akaType "}'.\n" void testFormatStrNoWarn(const char *filename, unsigned int linenr, const char* code) { diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 5f48b740c..5be1e1f74 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -29,8 +29,7 @@ class TestLeakAutoVar : public TestFixture { public: - TestLeakAutoVar() : TestFixture("TestLeakAutoVar") { - } + TestLeakAutoVar() : TestFixture("TestLeakAutoVar") {} private: Settings settings; @@ -53,9 +52,9 @@ private: settings.library.smartPointers["std::unique_ptr"].unique = true; const char xmldata[] = "\n" - "\n" - " \n" - ""; + "\n" + " \n" + ""; tinyxml2::XMLDocument doc; doc.Parse(xmldata, sizeof(xmldata)); settings.library.load(doc); @@ -1124,7 +1123,7 @@ private: " } while(!done);\n" " return;" "}" - ); + ); ASSERT_EQUALS("", errout.str()); } @@ -1152,7 +1151,7 @@ private: check("void do_wordexp(FILE *f) {\n" " free(getword(f));\n" " fclose(f);\n" - "}", /*cpp=*/false); + "}", /*cpp=*/ false); ASSERT_EQUALS("", errout.str()); } @@ -2207,7 +2206,7 @@ private: " mList.push_back(std::shared_ptr(pt));\n" "}\n", true - ); + ); ASSERT_EQUALS("", errout.str()); } @@ -2242,8 +2241,7 @@ REGISTER_TEST(TestLeakAutoVar) class TestLeakAutoVarRecursiveCountLimit : public TestFixture { public: - TestLeakAutoVarRecursiveCountLimit() : TestFixture("TestLeakAutoVarRecursiveCountLimit") { - } + TestLeakAutoVarRecursiveCountLimit() : TestFixture("TestLeakAutoVarRecursiveCountLimit") {} private: Settings settings; @@ -2302,10 +2300,9 @@ private: REGISTER_TEST(TestLeakAutoVarRecursiveCountLimit) -class TestLeakAutoVarStrcpy: public TestFixture { +class TestLeakAutoVarStrcpy : public TestFixture { public: - TestLeakAutoVarStrcpy() : TestFixture("TestLeakAutoVarStrcpy") { - } + TestLeakAutoVarStrcpy() : TestFixture("TestLeakAutoVarStrcpy") {} private: Settings settings; @@ -2355,8 +2352,7 @@ REGISTER_TEST(TestLeakAutoVarStrcpy) class TestLeakAutoVarWindows : public TestFixture { public: - TestLeakAutoVarWindows() : TestFixture("TestLeakAutoVarWindows") { - } + TestLeakAutoVarWindows() : TestFixture("TestLeakAutoVarWindows") {} private: Settings settings; diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index feb73df39..add484834 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -33,7 +33,7 @@ class TestLibrary : public TestFixture { public: - TestLibrary() : TestFixture("TestLibrary") { } + TestLibrary() : TestFixture("TestLibrary") {} private: Settings settings; @@ -842,32 +842,32 @@ private: void version() const { { - const char xmldata [] = "\n" - "\n" - ""; + const char xmldata[] = "\n" + "\n" + ""; Library library; const Library::Error err = readLibrary(library, xmldata); ASSERT_EQUALS(true, err.errorcode == Library::ErrorCode::OK); } { - const char xmldata [] = "\n" - "\n" - ""; + const char xmldata[] = "\n" + "\n" + ""; Library library; const Library::Error err = readLibrary(library, xmldata); ASSERT_EQUALS(true, err.errorcode == Library::ErrorCode::OK); } { - const char xmldata [] = "\n" - "\n" - ""; + const char xmldata[] = "\n" + "\n" + ""; Library library; const Library::Error err = readLibrary(library, xmldata); ASSERT_EQUALS(true, err.errorcode == Library::ErrorCode::UNSUPPORTED_FORMAT); } } - void loadLibError(const char xmldata [], Library::ErrorCode errorcode, const char* file, unsigned line) const { + void loadLibError(const char xmldata[], Library::ErrorCode errorcode, const char* file, unsigned line) const { Library library; assertEquals(file, line, true, errorcode == readLibrary(library, xmldata).errorcode); } diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 34cc02679..de7e91612 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -27,8 +27,7 @@ struct InternalError; class TestMathLib : public TestFixture { public: - TestMathLib() : TestFixture("TestMathLib") { - } + TestMathLib() : TestFixture("TestMathLib") {} private: diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index e0123230b..fabb168c1 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -29,8 +29,7 @@ class TestMemleak : private TestFixture { public: - TestMemleak() : TestFixture("TestMemleak") { - } + TestMemleak() : TestFixture("TestMemleak") {} private: Settings settings; @@ -116,8 +115,7 @@ REGISTER_TEST(TestMemleak) class TestMemleakInFunction : public TestFixture { public: - TestMemleakInFunction() : TestFixture("TestMemleakInFunction") { - } + TestMemleakInFunction() : TestFixture("TestMemleakInFunction") {} private: Settings settings0; @@ -460,8 +458,7 @@ REGISTER_TEST(TestMemleakInFunction) class TestMemleakInClass : public TestFixture { public: - TestMemleakInClass() : TestFixture("TestMemleakInClass") { - } + TestMemleakInClass() : TestFixture("TestMemleakInClass") {} private: Settings settings; @@ -1637,8 +1634,7 @@ REGISTER_TEST(TestMemleakInClass) class TestMemleakStructMember : public TestFixture { public: - TestMemleakStructMember() : TestFixture("TestMemleakStructMember") { - } + TestMemleakStructMember() : TestFixture("TestMemleakStructMember") {} private: Settings settings; @@ -2119,8 +2115,7 @@ REGISTER_TEST(TestMemleakStructMember) class TestMemleakNoVar : public TestFixture { public: - TestMemleakNoVar() : TestFixture("TestMemleakNoVar") { - } + TestMemleakNoVar() : TestFixture("TestMemleakNoVar") {} private: Settings settings; diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 5b69a84fd..7451b5ad0 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -34,8 +34,7 @@ class TestNullPointer : public TestFixture { public: - TestNullPointer() : TestFixture("TestNullPointer") { - } + TestNullPointer() : TestFixture("TestNullPointer") {} private: Settings settings; @@ -1500,7 +1499,7 @@ private: void nullpointer34() { check("void g() {\n" - " throw "";\n" + " throw " ";\n" "}\n" "bool f(int * x) {\n" " if (x) *x += 1;\n" diff --git a/test/testoptions.cpp b/test/testoptions.cpp index 0e6001b4c..524cbe4f5 100644 --- a/test/testoptions.cpp +++ b/test/testoptions.cpp @@ -18,11 +18,10 @@ #include "testsuite.h" -class TestOptions: public TestFixture { +class TestOptions : public TestFixture { public: TestOptions() - :TestFixture("TestOptions") { - } + : TestFixture("TestOptions") {} private: diff --git a/test/testother.cpp b/test/testother.cpp index 9d84632bf..7bbf89f9e 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -33,8 +33,7 @@ class TestOther : public TestFixture { public: - TestOther() : TestFixture("TestOther") { - } + TestOther() : TestFixture("TestOther") {} private: Settings _settings; @@ -2168,7 +2167,7 @@ private: " x.dostuff();\n" " const U& y = dynamic_cast(x)\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared with const\n", errout.str()); check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" @@ -4860,7 +4859,7 @@ private: false, // runSimpleChecks false, // verbose nullptr // settings - ); + ); ASSERT_EQUALS("", errout.str()); // make sure there are not "same expression" fp when there are different ({}) expressions @@ -9289,15 +9288,15 @@ private: } void knownArgumentTernaryOperator() { // #10374 - check("void f(bool a, bool b) {\n" - " const T* P = nullptr; \n" - " long N = 0; \n" - " const bool c = foo(); \n" - " bar(P, N); \n" - " if (c ? a : b)\n" - " baz(P, N); \n" - "}"); - ASSERT_EQUALS("", errout.str()); + check("void f(bool a, bool b) {\n" + " const T* P = nullptr; \n" + " long N = 0; \n" + " const bool c = foo(); \n" + " bar(P, N); \n" + " if (c ? a : b)\n" + " baz(P, N); \n" + "}"); + ASSERT_EQUALS("", errout.str()); } void checkComparePointers() { diff --git a/test/testpath.cpp b/test/testpath.cpp index ddebb2963..c2c09ac9d 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -24,8 +24,7 @@ class TestPath : public TestFixture { public: - TestPath() : TestFixture("TestPath") { - } + TestPath() : TestFixture("TestPath") {} private: diff --git a/test/testpathmatch.cpp b/test/testpathmatch.cpp index 8a1d1fe31..7197e76a2 100644 --- a/test/testpathmatch.cpp +++ b/test/testpathmatch.cpp @@ -30,8 +30,7 @@ public: , emptyMatcher(std::vector()) , srcMatcher(std::vector(1, "src/")) , fooCppMatcher(std::vector(1, "foo.cpp")) - , srcFooCppMatcher(std::vector(1, "src/foo.cpp")) { - } + , srcFooCppMatcher(std::vector(1, "src/foo.cpp")) {} private: const PathMatch emptyMatcher; diff --git a/test/testplatform.cpp b/test/testplatform.cpp index 2d5f307ff..9ffb77287 100644 --- a/test/testplatform.cpp +++ b/test/testplatform.cpp @@ -25,7 +25,7 @@ class TestPlatform : public TestFixture { public: - TestPlatform() : TestFixture("TestPlatform") { } + TestPlatform() : TestFixture("TestPlatform") {} private: void run() OVERRIDE { diff --git a/test/testpostfixoperator.cpp b/test/testpostfixoperator.cpp index 1b2dcd1af..5533f4f25 100644 --- a/test/testpostfixoperator.cpp +++ b/test/testpostfixoperator.cpp @@ -25,8 +25,7 @@ class TestPostfixOperator : public TestFixture { public: - TestPostfixOperator() : TestFixture("TestPostfixOperator") { - } + TestPostfixOperator() : TestFixture("TestPostfixOperator") {} private: Settings settings; diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 2f09f6ce5..3f1c058f6 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -266,8 +266,7 @@ private: actual[config] = cfgcode; } catch (const simplecpp::Output &) { actual[config] = ""; - } catch (...) { - } + } catch (...) {} } } @@ -1286,7 +1285,7 @@ private: // invalid code ASSERT_EQUALS("\nprintf ( \"hello\" ) ;", actual); } - */ + */ void va_args_3() const { const char filedata[] = "#define FRED(...) { fred(__VA_ARGS__); }\n" "FRED(123)\n"; diff --git a/test/testrunner.cpp b/test/testrunner.cpp index 3766f8293..fbdf3ee54 100644 --- a/test/testrunner.cpp +++ b/test/testrunner.cpp @@ -33,24 +33,25 @@ int main(int argc, char *argv[]) #ifdef NDEBUG try { #endif - Preprocessor::macroChar = '$'; // While macroChar is char(1) per default outside test suite, we require it to be a human-readable character here. + Preprocessor::macroChar = '$'; // While macroChar is char(1) per default outside test suite, we require it to be a human-readable character here. - options args(argc, argv); + options args(argc, argv); - if (args.help()) { - TestFixture::printHelp(); - return EXIT_SUCCESS; - } - const std::size_t failedTestsCount = TestFixture::runTests(args); - return (failedTestsCount == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -#ifdef NDEBUG - } catch (const InternalError& e) { - std::cout << e.errorMessage << std::endl; - } catch (const std::exception& error) { - std::cout << error.what() << std::endl; - } catch (...) { - std::cout << "Unknown exception" << std::endl; + if (args.help()) { + TestFixture::printHelp(); + return EXIT_SUCCESS; } - return EXIT_FAILURE; + const std::size_t failedTestsCount = TestFixture::runTests(args); + return (failedTestsCount == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +#ifdef NDEBUG +} +catch (const InternalError& e) { + std::cout << e.errorMessage << std::endl; +} catch (const std::exception& error) { + std::cout << error.what() << std::endl; +} catch (...) { + std::cout << "Unknown exception" << std::endl; +} +return EXIT_FAILURE; #endif } diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index c88bb8a6e..e11d3a3b6 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -32,8 +32,7 @@ struct InternalError; class TestSimplifyTemplate : public TestFixture { public: - TestSimplifyTemplate() : TestFixture("TestSimplifyTemplate") { - } + TestSimplifyTemplate() : TestFixture("TestSimplifyTemplate") {} private: Settings settings; @@ -1395,9 +1394,9 @@ private: void template57() { // #7891 const char code[] = "template struct Test { Test(T); };\n" "Test test( 0 );"; - const char exp [] = "struct Test ; " - "Test test ( 0 ) ; " - "struct Test { Test ( unsigned long ) ; } ;"; + const char exp[] = "struct Test ; " + "Test test ( 0 ) ; " + "struct Test { Test ( unsigned long ) ; } ;"; ASSERT_EQUALS(exp, tok(code)); } @@ -1531,25 +1530,25 @@ private: " t_func<1>();\n" "}\n" "};"; - const char exp [] = "bool foo ( ) ; " - "struct A { " - "void t_func<0> ( ) ; " - "void t_func<1> ( ) ; " - "void t_caller ( ) " - "{ " - "t_func<0> ( ) ; " - "t_func<1> ( ) ; " - "} " - "} ; " - "void A :: t_func<0> ( ) " - "{ " - "if ( 0 != 0 || foo ( ) ) { ; } " - "} " - "void A :: t_func<1> ( ) " - "{ " - "if ( 1 != 0 || foo ( ) ) { ; } " - "} " - "bool foo ( ) { return true ; }"; + const char exp[] = "bool foo ( ) ; " + "struct A { " + "void t_func<0> ( ) ; " + "void t_func<1> ( ) ; " + "void t_caller ( ) " + "{ " + "t_func<0> ( ) ; " + "t_func<1> ( ) ; " + "} " + "} ; " + "void A :: t_func<0> ( ) " + "{ " + "if ( 0 != 0 || foo ( ) ) { ; } " + "} " + "void A :: t_func<1> ( ) " + "{ " + "if ( 1 != 0 || foo ( ) ) { ; } " + "} " + "bool foo ( ) { return true ; }"; ASSERT_EQUALS(exp, tok(code)); } @@ -1569,17 +1568,17 @@ private: " AssociationDAGlobalGraphObserver grObs;\n" " return 1;\n" "}"; - const char exp [] = "namespace bpp " - "{ " - "class AssociationDAGraphImplObserver ; " - "} " - "using namespace bpp ; " - "int main ( ) { " - "bpp :: AssociationDAGraphImplObserver grObs ; " - "return 1 ; " - "} class bpp :: AssociationDAGraphImplObserver : " - "public AssociationGraphImplObserver < std :: string , unsigned int , DAGlobalGraph > " - "{ } ;"; + const char exp[] = "namespace bpp " + "{ " + "class AssociationDAGraphImplObserver ; " + "} " + "using namespace bpp ; " + "int main ( ) { " + "bpp :: AssociationDAGraphImplObserver grObs ; " + "return 1 ; " + "} class bpp :: AssociationDAGraphImplObserver : " + "public AssociationGraphImplObserver < std :: string , unsigned int , DAGlobalGraph > " + "{ } ;"; ASSERT_EQUALS(exp, tok(code)); } @@ -1589,12 +1588,12 @@ private: "};\n" "template const int ** Fred::foo() { return nullptr; }\n" "Fred fred;"; - const char exp [] = "struct Fred ; " - "Fred fred ; " - "struct Fred { " - "const int * * foo ( ) ; " - "} ; " - "const int * * Fred :: foo ( ) { return nullptr ; }"; + const char exp[] = "struct Fred ; " + "Fred fred ; " + "struct Fred { " + "const int * * foo ( ) ; " + "} ; " + "const int * * Fred :: foo ( ) { return nullptr ; }"; ASSERT_EQUALS(exp, tok(code)); } @@ -1637,12 +1636,12 @@ private: " T value;\n" "};\n" "Fred fred;"; - const char exp [] = "union Fred ; " - "Fred fred ; " - "union Fred { " - "char dummy [ sizeof ( int ) ] ; " - "int value ; " - "} ;"; + const char exp[] = "union Fred ; " + "Fred fred ; " + "union Fred { " + "char dummy [ sizeof ( int ) ] ; " + "int value ; " + "} ;"; ASSERT_EQUALS(exp, tok(code)); } @@ -1652,12 +1651,12 @@ private: " template T lookup() { return test; }\n" " int Fun() { return lookup(); }\n" "};"; - const char exp [] = "class Test { " - "int test ; " - "int lookup ( ) ; " - "int Fun ( ) { return lookup ( ) ; } " - "} ; " - "int Test :: lookup ( ) { return test ; }"; + const char exp[] = "class Test { " + "int test ; " + "int lookup ( ) ; " + "int Fun ( ) { return lookup ( ) ; } " + "} ; " + "int Test :: lookup ( ) { return test ; }"; ASSERT_EQUALS(exp, tok(code)); } @@ -1670,22 +1669,22 @@ private: "class Bar : private Bar {\n" " void foo() { }\n" "};"; - const char exp [] = "template < typename T , typename V , int KeySize = 0 > class Bar ; " - "class Bar ; " - "class Bar { " - "} ; " - "template < typename K , typename V , int KeySize = 0 > " - "class Bar : private Bar { " - "void foo ( ) { } " - "} ;"; - const char act [] = "template < typename T , typename V , int KeySize = 0 > class Bar ; " - "class Bar { " - "} ; " - "class Bar ; " - "template < typename K , typename V , int KeySize = 0 > " - "class Bar : private Bar { " - "void foo ( ) { } " - "} ;"; + const char exp[] = "template < typename T , typename V , int KeySize = 0 > class Bar ; " + "class Bar ; " + "class Bar { " + "} ; " + "template < typename K , typename V , int KeySize = 0 > " + "class Bar : private Bar { " + "void foo ( ) { } " + "} ;"; + const char act[] = "template < typename T , typename V , int KeySize = 0 > class Bar ; " + "class Bar { " + "} ; " + "class Bar ; " + "template < typename K , typename V , int KeySize = 0 > " + "class Bar : private Bar { " + "void foo ( ) { } " + "} ;"; TODO_ASSERT_EQUALS(exp, act, tok(code)); } @@ -1702,11 +1701,11 @@ private: "}\n" "\n" "Reference< class XPropertyList > dostuff();"; - const char exp [] = "int f1 ( int * pInterface , int x ) { return 0 ; } " - "class Reference ; " - "Reference dostuff ( ) ; " - "class Reference { template < class XPropertyList > int i ( ) ; int * pInterface ; } ; " - "int Reference :: i ( ) { return f1 ( pInterface , XPropertyList :: static_type ( ) ) ; }"; + const char exp[] = "int f1 ( int * pInterface , int x ) { return 0 ; } " + "class Reference ; " + "Reference dostuff ( ) ; " + "class Reference { template < class XPropertyList > int i ( ) ; int * pInterface ; } ; " + "int Reference :: i ( ) { return f1 ( pInterface , XPropertyList :: static_type ( ) ) ; }"; ASSERT_EQUALS(exp, tok(code)); } @@ -1715,10 +1714,10 @@ private: "const Tokenizer *tokenizer() const;\n" "template \n" "Tokenizer::Tokenizer() { }"; - const char exp [] = "template < typename N , typename P > class Tokenizer ; " - "const Tokenizer < Node , Path > * tokenizer ( ) const ; " - "template < typename N , typename P > " - "Tokenizer < N , P > :: Tokenizer ( ) { }"; + const char exp[] = "template < typename N , typename P > class Tokenizer ; " + "const Tokenizer < Node , Path > * tokenizer ( ) const ; " + "template < typename N , typename P > " + "Tokenizer < N , P > :: Tokenizer ( ) { }"; ASSERT_EQUALS(exp, tok(code)); } @@ -2328,35 +2327,35 @@ private: void template97() { const char code[] ="namespace NS1 {\n" - " namespace NS2 {\n" - " namespace NS3 {\n" - " namespace NS4 {\n" - " template\n" - " class Fred {\n" - " T * t;\n" - " public:\n" - " Fred() : t(nullptr) {}\n" - " };\n" - " }\n" - " using namespace NS4;\n" - " Fred fred_bool;\n" - " NS4::Fred fred_char;\n" - " }\n" - " using namespace NS3;\n" - " NS4::Fred fred_short;\n" - " using namespace NS3::NS4;\n" - " Fred fred_int;\n" - " NS3::NS4::Fred fred_long;\n" - " NS2::NS3::NS4::Fred fred_float;\n" - " NS1::NS2::NS3::NS4::Fred fred_double;\n" - " }\n" - " using namespace NS2;\n" - " NS3::NS4::Fred fred_float1;\n" - " NS2::NS3::NS4::Fred fred_double1;\n" - "}\n" - "using namespace NS1::NS2::NS3::NS4;\n" - "Fred fred_bool1;\n" - "NS1::NS2::NS3::NS4::Fred fred_int1;"; + " namespace NS2 {\n" + " namespace NS3 {\n" + " namespace NS4 {\n" + " template\n" + " class Fred {\n" + " T * t;\n" + " public:\n" + " Fred() : t(nullptr) {}\n" + " };\n" + " }\n" + " using namespace NS4;\n" + " Fred fred_bool;\n" + " NS4::Fred fred_char;\n" + " }\n" + " using namespace NS3;\n" + " NS4::Fred fred_short;\n" + " using namespace NS3::NS4;\n" + " Fred fred_int;\n" + " NS3::NS4::Fred fred_long;\n" + " NS2::NS3::NS4::Fred fred_float;\n" + " NS1::NS2::NS3::NS4::Fred fred_double;\n" + " }\n" + " using namespace NS2;\n" + " NS3::NS4::Fred fred_float1;\n" + " NS2::NS3::NS4::Fred fred_double1;\n" + "}\n" + "using namespace NS1::NS2::NS3::NS4;\n" + "Fred fred_bool1;\n" + "NS1::NS2::NS3::NS4::Fred fred_int1;"; const char exp[] = "namespace NS1 { " "namespace NS2 { " "namespace NS3 { " @@ -2836,10 +2835,10 @@ private: "template struct e;\n" "template using f = typename e>::g>::h;"; const char exp[] = "template < typename a , a > struct b { } ; " - "template < typename > struct c ; " - "template < typename > struct d : b < bool , std :: is_polymorphic < int > { } > { } ; " - "template < bool > struct e ; " - "template < typename a > using f = typename e < c < d < a > > :: g > :: h ;"; + "template < typename > struct c ; " + "template < typename > struct d : b < bool , std :: is_polymorphic < int > { } > { } ; " + "template < bool > struct e ; " + "template < typename a > using f = typename e < c < d < a > > :: g > :: h ;"; ASSERT_EQUALS(exp, tok(code)); } { @@ -2848,9 +2847,9 @@ private: "template struct d : b{}> {};\n" "template using e = typename c{}, d>::f;\n"; const char exp[] = "template < typename a , a > struct b ; " - "template < bool , typename > struct c ; " - "template < typename a > struct d : b < bool , std :: is_empty < a > { } > { } ; " - "template < typename a > using e = typename c < std :: is_final < a > { } , d < a > > :: f ;"; + "template < bool , typename > struct c ; " + "template < typename a > struct d : b < bool , std :: is_empty < a > { } > { } ; " + "template < typename a > using e = typename c < std :: is_final < a > { } , d < a > > :: f ;"; ASSERT_EQUALS(exp, tok(code)); } } @@ -4581,10 +4580,10 @@ private: const char code[] = "template class DefaultMemory {}; " "template > class thv_table_c {}; " "thv_table_c id_table_m;"; - const char exp [] = "template < class T , class U > class DefaultMemory { } ; " - "class thv_table_c> ; " - "thv_table_c> id_table_m ; " - "class thv_table_c> { } ;"; + const char exp[] = "template < class T , class U > class DefaultMemory { } ; " + "class thv_table_c> ; " + "thv_table_c> id_table_m ; " + "class thv_table_c> { } ;"; ASSERT_EQUALS(exp, tok(code)); } { @@ -5228,7 +5227,7 @@ private: tokenizer.splitTemplateRightAngleBrackets(false); const Token *_tok = tokenizer.tokens(); - for (unsigned i = 0 ; i < offset ; ++i) + for (unsigned i = 0; i < offset; ++i) _tok = _tok->next(); return tokenizer.mTemplateSimplifier->getTemplateNamePosition(_tok); } @@ -5298,7 +5297,7 @@ private: tokenizer.splitTemplateRightAngleBrackets(false); const Token *_tok = tokenizer.tokens(); - for (unsigned i = 0 ; i < offset ; ++i) + for (unsigned i = 0; i < offset; ++i) _tok = _tok->next(); const Token *tok1 = TemplateSimplifier::findTemplateDeclarationEnd(_tok); diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index a1747fd4b..3c0047816 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -28,8 +28,7 @@ class TestSimplifyTokens : public TestFixture { public: - TestSimplifyTokens() : TestFixture("TestSimplifyTokens") { - } + TestSimplifyTokens() : TestFixture("TestSimplifyTokens") {} private: @@ -493,13 +492,13 @@ private: void test1() { // "&p[1]" => "p+1" /* - ASSERT_EQUALS("; x = p + n ;", tok("; x = & p [ n ] ;")); - ASSERT_EQUALS("; x = ( p + n ) [ m ] ;", tok("; x = & p [ n ] [ m ] ;")); - ASSERT_EQUALS("; x = y & p [ n ] ;", tok("; x = y & p [ n ] ;")); - ASSERT_EQUALS("; x = 10 & p [ n ] ;", tok("; x = 10 & p [ n ] ;")); - ASSERT_EQUALS("; x = y [ 10 ] & p [ n ] ;", tok("; x = y [ 10 ] & p [ n ] ;")); - ASSERT_EQUALS("; x = ( a + m ) & p [ n ] ;", tok("; x = ( a + m ) & p [ n ] ;")); - */ + ASSERT_EQUALS("; x = p + n ;", tok("; x = & p [ n ] ;")); + ASSERT_EQUALS("; x = ( p + n ) [ m ] ;", tok("; x = & p [ n ] [ m ] ;")); + ASSERT_EQUALS("; x = y & p [ n ] ;", tok("; x = y & p [ n ] ;")); + ASSERT_EQUALS("; x = 10 & p [ n ] ;", tok("; x = 10 & p [ n ] ;")); + ASSERT_EQUALS("; x = y [ 10 ] & p [ n ] ;", tok("; x = y [ 10 ] & p [ n ] ;")); + ASSERT_EQUALS("; x = ( a + m ) & p [ n ] ;", tok("; x = ( a + m ) & p [ n ] ;")); + */ // "*(p+1)" => "p[1]" ASSERT_EQUALS("; x = p [ 1 ] ;", tok("; x = * ( p + 1 ) ;")); ASSERT_EQUALS("; x = p [ 0xA ] ;", tok("; x = * ( p + 0xA ) ;")); @@ -539,9 +538,9 @@ private: void simplifyMathFunctions_erfc() { // verify erfc(), erfcf(), erfcl() - simplifcation const char code_erfc[] ="void f(int x) {\n" - " std::cout << erfc(x);\n" // do not simplify - " std::cout << erfc(0L);\n" // simplify to 1 - "}"; + " std::cout << erfc(x);\n" // do not simplify + " std::cout << erfc(0L);\n" // simplify to 1 + "}"; const char expected_erfc[] = "void f ( int x ) {\n" "std :: cout << erfc ( x ) ;\n" "std :: cout << 1 ;\n" @@ -549,9 +548,9 @@ private: ASSERT_EQUALS(expected_erfc, tokWithNewlines(code_erfc)); const char code_erfcf[] ="void f(float x) {\n" - " std::cout << erfcf(x);\n" // do not simplify - " std::cout << erfcf(0.0f);\n" // simplify to 1 - "}"; + " std::cout << erfcf(x);\n" // do not simplify + " std::cout << erfcf(0.0f);\n" // simplify to 1 + "}"; const char expected_erfcf[] = "void f ( float x ) {\n" "std :: cout << erfcf ( x ) ;\n" "std :: cout << 1 ;\n" @@ -559,9 +558,9 @@ private: ASSERT_EQUALS(expected_erfcf, tokWithNewlines(code_erfcf)); const char code_erfcl[] ="void f(long double x) {\n" - " std::cout << erfcl(x);\n" // do not simplify - " std::cout << erfcl(0.0f);\n" // simplify to 1 - "}"; + " std::cout << erfcl(x);\n" // do not simplify + " std::cout << erfcl(0.0f);\n" // simplify to 1 + "}"; const char expected_erfcl[] = "void f ( double x ) {\n" "std :: cout << erfcl ( x ) ;\n" "std :: cout << 1 ;\n" @@ -572,9 +571,9 @@ private: void simplifyMathFunctions_cos() { // verify cos(), cosf(), cosl() - simplifcation const char code_cos[] ="void f(int x) {\n" - " std::cout << cos(x);\n" // do not simplify - " std::cout << cos(0L);\n" // simplify to 1 - "}"; + " std::cout << cos(x);\n" // do not simplify + " std::cout << cos(0L);\n" // simplify to 1 + "}"; const char expected_cos[] = "void f ( int x ) {\n" "std :: cout << cos ( x ) ;\n" "std :: cout << 1 ;\n" @@ -582,9 +581,9 @@ private: ASSERT_EQUALS(expected_cos, tokWithNewlines(code_cos)); const char code_cosf[] ="void f(float x) {\n" - " std::cout << cosf(x);\n" // do not simplify - " std::cout << cosf(0.0f);\n" // simplify to 1 - "}"; + " std::cout << cosf(x);\n" // do not simplify + " std::cout << cosf(0.0f);\n" // simplify to 1 + "}"; const char expected_cosf[] = "void f ( float x ) {\n" "std :: cout << cosf ( x ) ;\n" "std :: cout << 1 ;\n" @@ -592,9 +591,9 @@ private: ASSERT_EQUALS(expected_cosf, tokWithNewlines(code_cosf)); const char code_cosl[] ="void f(long double x) {\n" - " std::cout << cosl(x);\n" // do not simplify - " std::cout << cosl(0.0f);\n" // simplify to 1 - "}"; + " std::cout << cosl(x);\n" // do not simplify + " std::cout << cosl(0.0f);\n" // simplify to 1 + "}"; const char expected_cosl[] = "void f ( double x ) {\n" "std :: cout << cosl ( x ) ;\n" "std :: cout << 1 ;\n" @@ -605,9 +604,9 @@ private: void simplifyMathFunctions_cosh() { // verify cosh(), coshf(), coshl() - simplifcation const char code_cosh[] ="void f(int x) {\n" - " std::cout << cosh(x);\n" // do not simplify - " std::cout << cosh(0L);\n" // simplify to 1 - "}"; + " std::cout << cosh(x);\n" // do not simplify + " std::cout << cosh(0L);\n" // simplify to 1 + "}"; const char expected_cosh[] = "void f ( int x ) {\n" "std :: cout << cosh ( x ) ;\n" "std :: cout << 1 ;\n" @@ -615,9 +614,9 @@ private: ASSERT_EQUALS(expected_cosh, tokWithNewlines(code_cosh)); const char code_coshf[] ="void f(float x) {\n" - " std::cout << coshf(x);\n" // do not simplify - " std::cout << coshf(0.0f);\n" // simplify to 1 - "}"; + " std::cout << coshf(x);\n" // do not simplify + " std::cout << coshf(0.0f);\n" // simplify to 1 + "}"; const char expected_coshf[] = "void f ( float x ) {\n" "std :: cout << coshf ( x ) ;\n" "std :: cout << 1 ;\n" @@ -625,9 +624,9 @@ private: ASSERT_EQUALS(expected_coshf, tokWithNewlines(code_coshf)); const char code_coshl[] ="void f(long double x) {\n" - " std::cout << coshl(x);\n" // do not simplify - " std::cout << coshl(0.0f);\n" // simplify to 1 - "}"; + " std::cout << coshl(x);\n" // do not simplify + " std::cout << coshl(0.0f);\n" // simplify to 1 + "}"; const char expected_coshl[] = "void f ( double x ) {\n" "std :: cout << coshl ( x ) ;\n" "std :: cout << 1 ;\n" @@ -638,9 +637,9 @@ private: void simplifyMathFunctions_acos() { // verify acos(), acosf(), acosl() - simplifcation const char code_acos[] ="void f(int x) {\n" - " std::cout << acos(x);\n" // do not simplify - " std::cout << acos(1L);\n" // simplify to 0 - "}"; + " std::cout << acos(x);\n" // do not simplify + " std::cout << acos(1L);\n" // simplify to 0 + "}"; const char expected_acos[] = "void f ( int x ) {\n" "std :: cout << acos ( x ) ;\n" "std :: cout << 0 ;\n" @@ -648,9 +647,9 @@ private: ASSERT_EQUALS(expected_acos, tokWithNewlines(code_acos)); const char code_acosf[] ="void f(float x) {\n" - " std::cout << acosf(x);\n" // do not simplify - " std::cout << acosf(1.0f);\n" // simplify to 0 - "}"; + " std::cout << acosf(x);\n" // do not simplify + " std::cout << acosf(1.0f);\n" // simplify to 0 + "}"; const char expected_acosf[] = "void f ( float x ) {\n" "std :: cout << acosf ( x ) ;\n" "std :: cout << 0 ;\n" @@ -658,9 +657,9 @@ private: ASSERT_EQUALS(expected_acosf, tokWithNewlines(code_acosf)); const char code_acosl[] ="void f(long double x) {\n" - " std::cout << acosl(x);\n" // do not simplify - " std::cout << acosl(1.0f);\n" // simplify to 0 - "}"; + " std::cout << acosl(x);\n" // do not simplify + " std::cout << acosl(1.0f);\n" // simplify to 0 + "}"; const char expected_acosl[] = "void f ( double x ) {\n" "std :: cout << acosl ( x ) ;\n" "std :: cout << 0 ;\n" @@ -671,9 +670,9 @@ private: void simplifyMathFunctions_acosh() { // verify acosh(), acoshf(), acoshl() - simplifcation const char code_acosh[] ="void f(int x) {\n" - " std::cout << acosh(x);\n" // do not simplify - " std::cout << acosh(1L);\n" // simplify to 0 - "}"; + " std::cout << acosh(x);\n" // do not simplify + " std::cout << acosh(1L);\n" // simplify to 0 + "}"; const char expected_acosh[] = "void f ( int x ) {\n" "std :: cout << acosh ( x ) ;\n" "std :: cout << 0 ;\n" @@ -681,9 +680,9 @@ private: ASSERT_EQUALS(expected_acosh, tokWithNewlines(code_acosh)); const char code_acoshf[] ="void f(float x) {\n" - " std::cout << acoshf(x);\n" // do not simplify - " std::cout << acoshf(1.0f);\n" // simplify to 0 - "}"; + " std::cout << acoshf(x);\n" // do not simplify + " std::cout << acoshf(1.0f);\n" // simplify to 0 + "}"; const char expected_acoshf[] = "void f ( float x ) {\n" "std :: cout << acoshf ( x ) ;\n" "std :: cout << 0 ;\n" @@ -691,9 +690,9 @@ private: ASSERT_EQUALS(expected_acoshf, tokWithNewlines(code_acoshf)); const char code_acoshl[] ="void f(long double x) {\n" - " std::cout << acoshl(x);\n" // do not simplify - " std::cout << acoshl(1.0f);\n" // simplify to 0 - "}"; + " std::cout << acoshl(x);\n" // do not simplify + " std::cout << acoshl(1.0f);\n" // simplify to 0 + "}"; const char expected_acoshl[] = "void f ( double x ) {\n" "std :: cout << acoshl ( x ) ;\n" "std :: cout << 0 ;\n" @@ -704,11 +703,11 @@ private: void simplifyMathFunctions_sqrt() { // verify sqrt(), sqrtf(), sqrtl() - simplifcation const char code_sqrt[] ="void f(int x) {\n" - " std::cout << sqrt(x);\n" // do not simplify - " std::cout << sqrt(-1);\n" // do not simplify - " std::cout << sqrt(0L);\n" // simplify to 0 - " std::cout << sqrt(1L);\n" // simplify to 1 - "}"; + " std::cout << sqrt(x);\n" // do not simplify + " std::cout << sqrt(-1);\n" // do not simplify + " std::cout << sqrt(0L);\n" // simplify to 0 + " std::cout << sqrt(1L);\n" // simplify to 1 + "}"; const char expected_sqrt[] = "void f ( int x ) {\n" "std :: cout << sqrt ( x ) ;\n" "std :: cout << sqrt ( -1 ) ;\n" @@ -718,11 +717,11 @@ private: ASSERT_EQUALS(expected_sqrt, tokWithNewlines(code_sqrt)); const char code_sqrtf[] ="void f(float x) {\n" - " std::cout << sqrtf(x);\n" // do not simplify - " std::cout << sqrtf(-1.0f);\n" // do not simplify - " std::cout << sqrtf(0.0f);\n" // simplify to 0 - " std::cout << sqrtf(1.0);\n" // simplify to 1 - "}"; + " std::cout << sqrtf(x);\n" // do not simplify + " std::cout << sqrtf(-1.0f);\n" // do not simplify + " std::cout << sqrtf(0.0f);\n" // simplify to 0 + " std::cout << sqrtf(1.0);\n" // simplify to 1 + "}"; const char expected_sqrtf[] = "void f ( float x ) {\n" "std :: cout << sqrtf ( x ) ;\n" "std :: cout << sqrtf ( -1.0f ) ;\n" @@ -732,11 +731,11 @@ private: ASSERT_EQUALS(expected_sqrtf, tokWithNewlines(code_sqrtf)); const char code_sqrtl[] ="void f(long double x) {\n" - " std::cout << sqrtf(x);\n" // do not simplify - " std::cout << sqrtf(-1.0);\n" // do not simplify - " std::cout << sqrtf(0.0);\n" // simplify to 0 - " std::cout << sqrtf(1.0);\n" // simplify to 1 - "}"; + " std::cout << sqrtf(x);\n" // do not simplify + " std::cout << sqrtf(-1.0);\n" // do not simplify + " std::cout << sqrtf(0.0);\n" // simplify to 0 + " std::cout << sqrtf(1.0);\n" // simplify to 1 + "}"; const char expected_sqrtl[] = "void f ( double x ) {\n" "std :: cout << sqrtf ( x ) ;\n" "std :: cout << sqrtf ( -1.0 ) ;\n" @@ -749,11 +748,11 @@ private: void simplifyMathFunctions_cbrt() { // verify cbrt(), cbrtf(), cbrtl() - simplifcation const char code_cbrt[] ="void f(int x) {\n" - " std::cout << cbrt(x);\n" // do not simplify - " std::cout << cbrt(-1);\n" // do not simplify - " std::cout << cbrt(0L);\n" // simplify to 0 - " std::cout << cbrt(1L);\n" // simplify to 1 - "}"; + " std::cout << cbrt(x);\n" // do not simplify + " std::cout << cbrt(-1);\n" // do not simplify + " std::cout << cbrt(0L);\n" // simplify to 0 + " std::cout << cbrt(1L);\n" // simplify to 1 + "}"; const char expected_cbrt[] = "void f ( int x ) {\n" "std :: cout << cbrt ( x ) ;\n" "std :: cout << cbrt ( -1 ) ;\n" @@ -763,11 +762,11 @@ private: ASSERT_EQUALS(expected_cbrt, tokWithNewlines(code_cbrt)); const char code_cbrtf[] ="void f(float x) {\n" - " std::cout << cbrtf(x);\n" // do not simplify - " std::cout << cbrtf(-1.0f);\n" // do not simplify - " std::cout << cbrtf(0.0f);\n" // simplify to 0 - " std::cout << cbrtf(1.0);\n" // simplify to 1 - "}"; + " std::cout << cbrtf(x);\n" // do not simplify + " std::cout << cbrtf(-1.0f);\n" // do not simplify + " std::cout << cbrtf(0.0f);\n" // simplify to 0 + " std::cout << cbrtf(1.0);\n" // simplify to 1 + "}"; const char expected_cbrtf[] = "void f ( float x ) {\n" "std :: cout << cbrtf ( x ) ;\n" "std :: cout << cbrtf ( -1.0f ) ;\n" @@ -777,11 +776,11 @@ private: ASSERT_EQUALS(expected_cbrtf, tokWithNewlines(code_cbrtf)); const char code_cbrtl[] ="void f(long double x) {\n" - " std::cout << cbrtl(x);\n" // do not simplify - " std::cout << cbrtl(-1.0);\n" // do not simplify - " std::cout << cbrtl(0.0);\n" // simplify to 0 - " std::cout << cbrtl(1.0);\n" // simplify to 1 - "}"; + " std::cout << cbrtl(x);\n" // do not simplify + " std::cout << cbrtl(-1.0);\n" // do not simplify + " std::cout << cbrtl(0.0);\n" // simplify to 0 + " std::cout << cbrtl(1.0);\n" // simplify to 1 + "}"; const char expected_cbrtl[] = "void f ( double x ) {\n" "std :: cout << cbrtl ( x ) ;\n" "std :: cout << cbrtl ( -1.0 ) ;\n" @@ -794,11 +793,11 @@ private: void simplifyMathFunctions_exp2() { // verify exp2(), exp2f(), exp2l() - simplifcation const char code_exp2[] ="void f(int x) {\n" - " std::cout << exp2(x);\n" // do not simplify - " std::cout << exp2(-1);\n" // do not simplify - " std::cout << exp2(0L);\n" // simplify to 0 - " std::cout << exp2(1L);\n" // do not simplify - "}"; + " std::cout << exp2(x);\n" // do not simplify + " std::cout << exp2(-1);\n" // do not simplify + " std::cout << exp2(0L);\n" // simplify to 0 + " std::cout << exp2(1L);\n" // do not simplify + "}"; const char expected_exp2[] = "void f ( int x ) {\n" "std :: cout << exp2 ( x ) ;\n" "std :: cout << exp2 ( -1 ) ;\n" @@ -808,11 +807,11 @@ private: ASSERT_EQUALS(expected_exp2, tokWithNewlines(code_exp2)); const char code_exp2f[] ="void f(float x) {\n" - " std::cout << exp2f(x);\n" // do not simplify - " std::cout << exp2f(-1.0);\n" // do not simplify - " std::cout << exp2f(0.0);\n" // simplify to 1 - " std::cout << exp2f(1.0);\n" // do not simplify - "}"; + " std::cout << exp2f(x);\n" // do not simplify + " std::cout << exp2f(-1.0);\n" // do not simplify + " std::cout << exp2f(0.0);\n" // simplify to 1 + " std::cout << exp2f(1.0);\n" // do not simplify + "}"; const char expected_exp2f[] = "void f ( float x ) {\n" "std :: cout << exp2f ( x ) ;\n" "std :: cout << exp2f ( -1.0 ) ;\n" @@ -822,11 +821,11 @@ private: ASSERT_EQUALS(expected_exp2f, tokWithNewlines(code_exp2f)); const char code_exp2l[] ="void f(long double x) {\n" - " std::cout << exp2l(x);\n" // do not simplify - " std::cout << exp2l(-1.0);\n" // do not simplify - " std::cout << exp2l(0.0);\n" // simplify to 1 - " std::cout << exp2l(1.0);\n" // do not simplify - "}"; + " std::cout << exp2l(x);\n" // do not simplify + " std::cout << exp2l(-1.0);\n" // do not simplify + " std::cout << exp2l(0.0);\n" // simplify to 1 + " std::cout << exp2l(1.0);\n" // do not simplify + "}"; const char expected_exp2l[] = "void f ( double x ) {\n" "std :: cout << exp2l ( x ) ;\n" "std :: cout << exp2l ( -1.0 ) ;\n" @@ -839,11 +838,11 @@ private: void simplifyMathFunctions_exp() { // verify exp(), expf(), expl() - simplifcation const char code_exp[] ="void f(int x) {\n" - " std::cout << exp(x);\n" // do not simplify - " std::cout << exp(-1);\n" // do not simplify - " std::cout << exp(0L);\n" // simplify to 1 - " std::cout << exp(1L);\n" // do not simplify - "}"; + " std::cout << exp(x);\n" // do not simplify + " std::cout << exp(-1);\n" // do not simplify + " std::cout << exp(0L);\n" // simplify to 1 + " std::cout << exp(1L);\n" // do not simplify + "}"; const char expected_exp[] = "void f ( int x ) {\n" "std :: cout << exp ( x ) ;\n" "std :: cout << exp ( -1 ) ;\n" @@ -853,11 +852,11 @@ private: ASSERT_EQUALS(expected_exp, tokWithNewlines(code_exp)); const char code_expf[] ="void f(float x) {\n" - " std::cout << expf(x);\n" // do not simplify - " std::cout << expf(-1.0);\n" // do not simplify - " std::cout << expf(0.0);\n" // simplify to 1 - " std::cout << expf(1.0);\n" // do not simplify - "}"; + " std::cout << expf(x);\n" // do not simplify + " std::cout << expf(-1.0);\n" // do not simplify + " std::cout << expf(0.0);\n" // simplify to 1 + " std::cout << expf(1.0);\n" // do not simplify + "}"; const char expected_expf[] = "void f ( float x ) {\n" "std :: cout << expf ( x ) ;\n" "std :: cout << expf ( -1.0 ) ;\n" @@ -867,11 +866,11 @@ private: ASSERT_EQUALS(expected_expf, tokWithNewlines(code_expf)); const char code_expl[] ="void f(long double x) {\n" - " std::cout << expl(x);\n" // do not simplify - " std::cout << expl(-1.0);\n" // do not simplify - " std::cout << expl(0.0);\n" // simplify to 1 - " std::cout << expl(1.0);\n" // do not simplify - "}"; + " std::cout << expl(x);\n" // do not simplify + " std::cout << expl(-1.0);\n" // do not simplify + " std::cout << expl(0.0);\n" // simplify to 1 + " std::cout << expl(1.0);\n" // do not simplify + "}"; const char expected_expl[] = "void f ( double x ) {\n" "std :: cout << expl ( x ) ;\n" "std :: cout << expl ( -1.0 ) ;\n" @@ -884,10 +883,10 @@ private: void simplifyMathFunctions_erf() { // verify erf(), erff(), erfl() - simplifcation const char code_erf[] ="void f(int x) {\n" - " std::cout << erf(x);\n" // do not simplify - " std::cout << erf(10);\n" // do not simplify - " std::cout << erf(0L);\n" // simplify to 0 - "}"; + " std::cout << erf(x);\n" // do not simplify + " std::cout << erf(10);\n" // do not simplify + " std::cout << erf(0L);\n" // simplify to 0 + "}"; const char expected_erf[] = "void f ( int x ) {\n" "std :: cout << erf ( x ) ;\n" "std :: cout << erf ( 10 ) ;\n" @@ -896,10 +895,10 @@ private: ASSERT_EQUALS(expected_erf, tokWithNewlines(code_erf)); const char code_erff[] ="void f(float x) {\n" - " std::cout << erff(x);\n" // do not simplify - " std::cout << erff(10);\n" // do not simplify - " std::cout << erff(0.0f);\n" // simplify to 0 - "}"; + " std::cout << erff(x);\n" // do not simplify + " std::cout << erff(10);\n" // do not simplify + " std::cout << erff(0.0f);\n" // simplify to 0 + "}"; const char expected_erff[] = "void f ( float x ) {\n" "std :: cout << erff ( x ) ;\n" "std :: cout << erff ( 10 ) ;\n" @@ -908,10 +907,10 @@ private: ASSERT_EQUALS(expected_erff, tokWithNewlines(code_erff)); const char code_erfl[] ="void f(long double x) {\n" - " std::cout << erfl(x);\n" // do not simplify - " std::cout << erfl(10.0f);\n" // do not simplify - " std::cout << erfl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << erfl(x);\n" // do not simplify + " std::cout << erfl(10.0f);\n" // do not simplify + " std::cout << erfl(0.0f);\n" // simplify to 0 + "}"; const char expected_erfl[] = "void f ( double x ) {\n" "std :: cout << erfl ( x ) ;\n" "std :: cout << erfl ( 10.0f ) ;\n" @@ -923,10 +922,10 @@ private: void simplifyMathFunctions_atanh() { // verify atanh(), atanhf(), atanhl() - simplifcation const char code_atanh[] ="void f(int x) {\n" - " std::cout << atanh(x);\n" // do not simplify - " std::cout << atanh(10);\n" // do not simplify - " std::cout << atanh(0L);\n" // simplify to 0 - "}"; + " std::cout << atanh(x);\n" // do not simplify + " std::cout << atanh(10);\n" // do not simplify + " std::cout << atanh(0L);\n" // simplify to 0 + "}"; const char expected_atanh[] = "void f ( int x ) {\n" "std :: cout << atanh ( x ) ;\n" "std :: cout << atanh ( 10 ) ;\n" @@ -935,10 +934,10 @@ private: ASSERT_EQUALS(expected_atanh, tokWithNewlines(code_atanh)); const char code_atanhf[] ="void f(float x) {\n" - " std::cout << atanhf(x);\n" // do not simplify - " std::cout << atanhf(10);\n" // do not simplify - " std::cout << atanhf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << atanhf(x);\n" // do not simplify + " std::cout << atanhf(10);\n" // do not simplify + " std::cout << atanhf(0.0f);\n" // simplify to 0 + "}"; const char expected_atanhf[] = "void f ( float x ) {\n" "std :: cout << atanhf ( x ) ;\n" "std :: cout << atanhf ( 10 ) ;\n" @@ -947,11 +946,11 @@ private: ASSERT_EQUALS(expected_atanhf, tokWithNewlines(code_atanhf)); const char code_atanhl[] ="void f(long double x) {\n" - " std::cout << atanhl(x);\n" // do not simplify - " std::cout << atanhl(10.0f);\n" // do not simplify - " std::cout << atanhl(0.0d);\n" // do not simplify - invalid number! - " std::cout << atanhl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << atanhl(x);\n" // do not simplify + " std::cout << atanhl(10.0f);\n" // do not simplify + " std::cout << atanhl(0.0d);\n" // do not simplify - invalid number! + " std::cout << atanhl(0.0f);\n" // simplify to 0 + "}"; const char expected_atanhl[] = "void f ( double x ) {\n" "std :: cout << atanhl ( x ) ;\n" "std :: cout << atanhl ( 10.0f ) ;\n" @@ -964,10 +963,10 @@ private: void simplifyMathFunctions_atan() { // verify atan(), atanf(), atanl() - simplifcation const char code_atan[] ="void f(int x) {\n" - " std::cout << atan(x);\n" // do not simplify - " std::cout << atan(10);\n" // do not simplify - " std::cout << atan(0L);\n" // simplify to 0 - "}"; + " std::cout << atan(x);\n" // do not simplify + " std::cout << atan(10);\n" // do not simplify + " std::cout << atan(0L);\n" // simplify to 0 + "}"; const char expected_atan[] = "void f ( int x ) {\n" "std :: cout << atan ( x ) ;\n" "std :: cout << atan ( 10 ) ;\n" @@ -976,10 +975,10 @@ private: ASSERT_EQUALS(expected_atan, tokWithNewlines(code_atan)); const char code_atanf[] ="void f(float x) {\n" - " std::cout << atanf(x);\n" // do not simplify - " std::cout << atanf(10);\n" // do not simplify - " std::cout << atanf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << atanf(x);\n" // do not simplify + " std::cout << atanf(10);\n" // do not simplify + " std::cout << atanf(0.0f);\n" // simplify to 0 + "}"; const char expected_atanf[] = "void f ( float x ) {\n" "std :: cout << atanf ( x ) ;\n" "std :: cout << atanf ( 10 ) ;\n" @@ -988,10 +987,10 @@ private: ASSERT_EQUALS(expected_atanf, tokWithNewlines(code_atanf)); const char code_atanl[] ="void f(long double x) {\n" - " std::cout << atanl(x);\n" // do not simplify - " std::cout << atanl(10.0f);\n" // do not simplify - " std::cout << atanl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << atanl(x);\n" // do not simplify + " std::cout << atanl(10.0f);\n" // do not simplify + " std::cout << atanl(0.0f);\n" // simplify to 0 + "}"; const char expected_atanl[] = "void f ( double x ) {\n" "std :: cout << atanl ( x ) ;\n" "std :: cout << atanl ( 10.0f ) ;\n" @@ -1003,10 +1002,10 @@ private: void simplifyMathFunctions_tanh() { // verify tanh(), tanhf(), tanhl() - simplifcation const char code_tanh[] ="void f(int x) {\n" - " std::cout << tanh(x);\n" // do not simplify - " std::cout << tanh(10);\n" // do not simplify - " std::cout << tanh(0L);\n" // simplify to 0 - "}"; + " std::cout << tanh(x);\n" // do not simplify + " std::cout << tanh(10);\n" // do not simplify + " std::cout << tanh(0L);\n" // simplify to 0 + "}"; const char expected_tanh[] = "void f ( int x ) {\n" "std :: cout << tanh ( x ) ;\n" "std :: cout << tanh ( 10 ) ;\n" @@ -1015,10 +1014,10 @@ private: ASSERT_EQUALS(expected_tanh, tokWithNewlines(code_tanh)); const char code_tanhf[] ="void f(float x) {\n" - " std::cout << tanhf(x);\n" // do not simplify - " std::cout << tanhf(10);\n" // do not simplify - " std::cout << tanhf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << tanhf(x);\n" // do not simplify + " std::cout << tanhf(10);\n" // do not simplify + " std::cout << tanhf(0.0f);\n" // simplify to 0 + "}"; const char expected_tanhf[] = "void f ( float x ) {\n" "std :: cout << tanhf ( x ) ;\n" "std :: cout << tanhf ( 10 ) ;\n" @@ -1027,10 +1026,10 @@ private: ASSERT_EQUALS(expected_tanhf, tokWithNewlines(code_tanhf)); const char code_tanhl[] ="void f(long double x) {\n" - " std::cout << tanhl(x);\n" // do not simplify - " std::cout << tanhl(10.0f);\n" // do not simplify - " std::cout << tanhl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << tanhl(x);\n" // do not simplify + " std::cout << tanhl(10.0f);\n" // do not simplify + " std::cout << tanhl(0.0f);\n" // simplify to 0 + "}"; const char expected_tanhl[] = "void f ( double x ) {\n" "std :: cout << tanhl ( x ) ;\n" "std :: cout << tanhl ( 10.0f ) ;\n" @@ -1042,10 +1041,10 @@ private: void simplifyMathFunctions_tan() { // verify tan(), tanf(), tanl() - simplifcation const char code_tan[] ="void f(int x) {\n" - " std::cout << tan(x);\n" // do not simplify - " std::cout << tan(10);\n" // do not simplify - " std::cout << tan(0L);\n" // simplify to 0 - "}"; + " std::cout << tan(x);\n" // do not simplify + " std::cout << tan(10);\n" // do not simplify + " std::cout << tan(0L);\n" // simplify to 0 + "}"; const char expected_tan[] = "void f ( int x ) {\n" "std :: cout << tan ( x ) ;\n" "std :: cout << tan ( 10 ) ;\n" @@ -1054,10 +1053,10 @@ private: ASSERT_EQUALS(expected_tan, tokWithNewlines(code_tan)); const char code_tanf[] ="void f(float x) {\n" - " std::cout << tanf(x);\n" // do not simplify - " std::cout << tanf(10);\n" // do not simplify - " std::cout << tanf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << tanf(x);\n" // do not simplify + " std::cout << tanf(10);\n" // do not simplify + " std::cout << tanf(0.0f);\n" // simplify to 0 + "}"; const char expected_tanf[] = "void f ( float x ) {\n" "std :: cout << tanf ( x ) ;\n" "std :: cout << tanf ( 10 ) ;\n" @@ -1066,10 +1065,10 @@ private: ASSERT_EQUALS(expected_tanf, tokWithNewlines(code_tanf)); const char code_tanl[] ="void f(long double x) {\n" - " std::cout << tanl(x);\n" // do not simplify - " std::cout << tanl(10.0f);\n" // do not simplify - " std::cout << tanl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << tanl(x);\n" // do not simplify + " std::cout << tanl(10.0f);\n" // do not simplify + " std::cout << tanl(0.0f);\n" // simplify to 0 + "}"; const char expected_tanl[] = "void f ( double x ) {\n" "std :: cout << tanl ( x ) ;\n" "std :: cout << tanl ( 10.0f ) ;\n" @@ -1081,10 +1080,10 @@ private: void simplifyMathFunctions_expm1() { // verify expm1(), expm1f(), expm1l() - simplifcation const char code_expm1[] ="void f(int x) {\n" - " std::cout << expm1(x);\n" // do not simplify - " std::cout << expm1(10);\n" // do not simplify - " std::cout << expm1(0L);\n" // simplify to 0 - "}"; + " std::cout << expm1(x);\n" // do not simplify + " std::cout << expm1(10);\n" // do not simplify + " std::cout << expm1(0L);\n" // simplify to 0 + "}"; const char expected_expm1[] = "void f ( int x ) {\n" "std :: cout << expm1 ( x ) ;\n" "std :: cout << expm1 ( 10 ) ;\n" @@ -1093,10 +1092,10 @@ private: ASSERT_EQUALS(expected_expm1, tokWithNewlines(code_expm1)); const char code_expm1f[] ="void f(float x) {\n" - " std::cout << expm1f(x);\n" // do not simplify - " std::cout << expm1f(10);\n" // do not simplify - " std::cout << expm1f(0.0f);\n" // simplify to 0 - "}"; + " std::cout << expm1f(x);\n" // do not simplify + " std::cout << expm1f(10);\n" // do not simplify + " std::cout << expm1f(0.0f);\n" // simplify to 0 + "}"; const char expected_expm1f[] = "void f ( float x ) {\n" "std :: cout << expm1f ( x ) ;\n" "std :: cout << expm1f ( 10 ) ;\n" @@ -1105,10 +1104,10 @@ private: ASSERT_EQUALS(expected_expm1f, tokWithNewlines(code_expm1f)); const char code_expm1l[] ="void f(long double x) {\n" - " std::cout << expm1l(x);\n" // do not simplify - " std::cout << expm1l(10.0f);\n" // do not simplify - " std::cout << expm1l(0.0f);\n" // simplify to 0 - "}"; + " std::cout << expm1l(x);\n" // do not simplify + " std::cout << expm1l(10.0f);\n" // do not simplify + " std::cout << expm1l(0.0f);\n" // simplify to 0 + "}"; const char expected_expm1l[] = "void f ( double x ) {\n" "std :: cout << expm1l ( x ) ;\n" "std :: cout << expm1l ( 10.0f ) ;\n" @@ -1120,10 +1119,10 @@ private: void simplifyMathFunctions_asinh() { // verify asinh(), asinhf(), asinhl() - simplifcation const char code_asinh[] ="void f(int x) {\n" - " std::cout << asinh(x);\n" // do not simplify - " std::cout << asinh(10);\n" // do not simplify - " std::cout << asinh(0L);\n" // simplify to 0 - "}"; + " std::cout << asinh(x);\n" // do not simplify + " std::cout << asinh(10);\n" // do not simplify + " std::cout << asinh(0L);\n" // simplify to 0 + "}"; const char expected_asinh[] = "void f ( int x ) {\n" "std :: cout << asinh ( x ) ;\n" "std :: cout << asinh ( 10 ) ;\n" @@ -1132,10 +1131,10 @@ private: ASSERT_EQUALS(expected_asinh, tokWithNewlines(code_asinh)); const char code_asinhf[] ="void f(float x) {\n" - " std::cout << asinhf(x);\n" // do not simplify - " std::cout << asinhf(10);\n" // do not simplify - " std::cout << asinhf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << asinhf(x);\n" // do not simplify + " std::cout << asinhf(10);\n" // do not simplify + " std::cout << asinhf(0.0f);\n" // simplify to 0 + "}"; const char expected_asinhf[] = "void f ( float x ) {\n" "std :: cout << asinhf ( x ) ;\n" "std :: cout << asinhf ( 10 ) ;\n" @@ -1144,10 +1143,10 @@ private: ASSERT_EQUALS(expected_asinhf, tokWithNewlines(code_asinhf)); const char code_asinhl[] ="void f(long double x) {\n" - " std::cout << asinhl(x);\n" // do not simplify - " std::cout << asinhl(10.0f);\n" // do not simplify - " std::cout << asinhl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << asinhl(x);\n" // do not simplify + " std::cout << asinhl(10.0f);\n" // do not simplify + " std::cout << asinhl(0.0f);\n" // simplify to 0 + "}"; const char expected_asinhl[] = "void f ( double x ) {\n" "std :: cout << asinhl ( x ) ;\n" "std :: cout << asinhl ( 10.0f ) ;\n" @@ -1159,10 +1158,10 @@ private: void simplifyMathFunctions_asin() { // verify asin(), asinf(), asinl() - simplifcation const char code_asin[] ="void f(int x) {\n" - " std::cout << asin(x);\n" // do not simplify - " std::cout << asin(10);\n" // do not simplify - " std::cout << asin(0L);\n" // simplify to 0 - "}"; + " std::cout << asin(x);\n" // do not simplify + " std::cout << asin(10);\n" // do not simplify + " std::cout << asin(0L);\n" // simplify to 0 + "}"; const char expected_asin[] = "void f ( int x ) {\n" "std :: cout << asin ( x ) ;\n" "std :: cout << asin ( 10 ) ;\n" @@ -1171,10 +1170,10 @@ private: ASSERT_EQUALS(expected_asin, tokWithNewlines(code_asin)); const char code_asinf[] ="void f(float x) {\n" - " std::cout << asinf(x);\n" // do not simplify - " std::cout << asinf(10);\n" // do not simplify - " std::cout << asinf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << asinf(x);\n" // do not simplify + " std::cout << asinf(10);\n" // do not simplify + " std::cout << asinf(0.0f);\n" // simplify to 0 + "}"; const char expected_asinf[] = "void f ( float x ) {\n" "std :: cout << asinf ( x ) ;\n" "std :: cout << asinf ( 10 ) ;\n" @@ -1183,10 +1182,10 @@ private: ASSERT_EQUALS(expected_asinf, tokWithNewlines(code_asinf)); const char code_asinl[] ="void f(long double x) {\n" - " std::cout << asinl(x);\n" // do not simplify - " std::cout << asinl(10.0f);\n" // do not simplify - " std::cout << asinl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << asinl(x);\n" // do not simplify + " std::cout << asinl(10.0f);\n" // do not simplify + " std::cout << asinl(0.0f);\n" // simplify to 0 + "}"; const char expected_asinl[] = "void f ( double x ) {\n" "std :: cout << asinl ( x ) ;\n" "std :: cout << asinl ( 10.0f ) ;\n" @@ -1198,10 +1197,10 @@ private: void simplifyMathFunctions_sinh() { // verify sinh(), sinhf(), sinhl() - simplifcation const char code_sinh[] ="void f(int x) {\n" - " std::cout << sinh(x);\n" // do not simplify - " std::cout << sinh(10);\n" // do not simplify - " std::cout << sinh(0L);\n" // simplify to 0 - "}"; + " std::cout << sinh(x);\n" // do not simplify + " std::cout << sinh(10);\n" // do not simplify + " std::cout << sinh(0L);\n" // simplify to 0 + "}"; const char expected_sinh[] = "void f ( int x ) {\n" "std :: cout << sinh ( x ) ;\n" "std :: cout << sinh ( 10 ) ;\n" @@ -1210,10 +1209,10 @@ private: ASSERT_EQUALS(expected_sinh, tokWithNewlines(code_sinh)); const char code_sinhf[] ="void f(float x) {\n" - " std::cout << sinhf(x);\n" // do not simplify - " std::cout << sinhf(10);\n" // do not simplify - " std::cout << sinhf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << sinhf(x);\n" // do not simplify + " std::cout << sinhf(10);\n" // do not simplify + " std::cout << sinhf(0.0f);\n" // simplify to 0 + "}"; const char expected_sinhf[] = "void f ( float x ) {\n" "std :: cout << sinhf ( x ) ;\n" "std :: cout << sinhf ( 10 ) ;\n" @@ -1222,10 +1221,10 @@ private: ASSERT_EQUALS(expected_sinhf, tokWithNewlines(code_sinhf)); const char code_sinhl[] ="void f(long double x) {\n" - " std::cout << sinhl(x);\n" // do not simplify - " std::cout << sinhl(10.0f);\n" // do not simplify - " std::cout << sinhl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << sinhl(x);\n" // do not simplify + " std::cout << sinhl(10.0f);\n" // do not simplify + " std::cout << sinhl(0.0f);\n" // simplify to 0 + "}"; const char expected_sinhl[] = "void f ( double x ) {\n" "std :: cout << sinhl ( x ) ;\n" "std :: cout << sinhl ( 10.0f ) ;\n" @@ -1237,10 +1236,10 @@ private: void simplifyMathFunctions_sin() { // verify sin(), sinf(), sinl() - simplifcation const char code_sin[] ="void f(int x) {\n" - " std::cout << sin(x);\n" // do not simplify - " std::cout << sin(10);\n" // do not simplify - " std::cout << sin(0L);\n" // simplify to 0 - "}"; + " std::cout << sin(x);\n" // do not simplify + " std::cout << sin(10);\n" // do not simplify + " std::cout << sin(0L);\n" // simplify to 0 + "}"; const char expected_sin[] = "void f ( int x ) {\n" "std :: cout << sin ( x ) ;\n" "std :: cout << sin ( 10 ) ;\n" @@ -1249,10 +1248,10 @@ private: ASSERT_EQUALS(expected_sin, tokWithNewlines(code_sin)); const char code_sinf[] ="void f(float x) {\n" - " std::cout << sinf(x);\n" // do not simplify - " std::cout << sinf(10);\n" // do not simplify - " std::cout << sinf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << sinf(x);\n" // do not simplify + " std::cout << sinf(10);\n" // do not simplify + " std::cout << sinf(0.0f);\n" // simplify to 0 + "}"; const char expected_sinf[] = "void f ( float x ) {\n" "std :: cout << sinf ( x ) ;\n" "std :: cout << sinf ( 10 ) ;\n" @@ -1261,10 +1260,10 @@ private: ASSERT_EQUALS(expected_sinf, tokWithNewlines(code_sinf)); const char code_sinl[] ="void f(long double x) {\n" - " std::cout << sinl(x);\n" // do not simplify - " std::cout << sinl(10.0f);\n" // do not simplify - " std::cout << sinl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << sinl(x);\n" // do not simplify + " std::cout << sinl(10.0f);\n" // do not simplify + " std::cout << sinl(0.0f);\n" // simplify to 0 + "}"; const char expected_sinl[] = "void f ( double x ) {\n" "std :: cout << sinl ( x ) ;\n" "std :: cout << sinl ( 10.0f ) ;\n" @@ -1281,10 +1280,10 @@ private: void simplifyMathFunctions_ilogb() { // verify ilogb(), ilogbf(), ilogbl() - simplifcation const char code_ilogb[] ="void f(int x) {\n" - " std::cout << ilogb(x);\n" // do not simplify - " std::cout << ilogb(10);\n" // do not simplify - " std::cout << ilogb(1L);\n" // simplify to 0 - "}"; + " std::cout << ilogb(x);\n" // do not simplify + " std::cout << ilogb(10);\n" // do not simplify + " std::cout << ilogb(1L);\n" // simplify to 0 + "}"; const char expected_ilogb[] = "void f ( int x ) {\n" "std :: cout << ilogb ( x ) ;\n" "std :: cout << ilogb ( 10 ) ;\n" @@ -1293,10 +1292,10 @@ private: ASSERT_EQUALS(expected_ilogb, tokWithNewlines(code_ilogb)); const char code_ilogbf[] ="void f(float x) {\n" - " std::cout << ilogbf(x);\n" // do not simplify - " std::cout << ilogbf(10);\n" // do not simplify - " std::cout << ilogbf(1.0f);\n" // simplify to 0 - "}"; + " std::cout << ilogbf(x);\n" // do not simplify + " std::cout << ilogbf(10);\n" // do not simplify + " std::cout << ilogbf(1.0f);\n" // simplify to 0 + "}"; const char expected_ilogbf[] = "void f ( float x ) {\n" "std :: cout << ilogbf ( x ) ;\n" "std :: cout << ilogbf ( 10 ) ;\n" @@ -1305,10 +1304,10 @@ private: ASSERT_EQUALS(expected_ilogbf, tokWithNewlines(code_ilogbf)); const char code_ilogbl[] ="void f(long double x) {\n" - " std::cout << ilogbl(x);\n" // do not simplify - " std::cout << ilogbl(10.0f);\n" // do not simplify - " std::cout << ilogbl(1.0f);\n" // simplify to 0 - "}"; + " std::cout << ilogbl(x);\n" // do not simplify + " std::cout << ilogbl(10.0f);\n" // do not simplify + " std::cout << ilogbl(1.0f);\n" // simplify to 0 + "}"; const char expected_ilogbl[] = "void f ( double x ) {\n" "std :: cout << ilogbl ( x ) ;\n" "std :: cout << ilogbl ( 10.0f ) ;\n" @@ -1320,10 +1319,10 @@ private: void simplifyMathFunctions_logb() { // verify logb(), logbf(), logbl() - simplifcation const char code_logb[] ="void f(int x) {\n" - " std::cout << logb(x);\n" // do not simplify - " std::cout << logb(10);\n" // do not simplify - " std::cout << logb(1L);\n" // simplify to 0 - "}"; + " std::cout << logb(x);\n" // do not simplify + " std::cout << logb(10);\n" // do not simplify + " std::cout << logb(1L);\n" // simplify to 0 + "}"; const char expected_logb[] = "void f ( int x ) {\n" "std :: cout << logb ( x ) ;\n" "std :: cout << logb ( 10 ) ;\n" @@ -1332,10 +1331,10 @@ private: ASSERT_EQUALS(expected_logb, tokWithNewlines(code_logb)); const char code_logbf[] ="void f(float x) {\n" - " std::cout << logbf(x);\n" // do not simplify - " std::cout << logbf(10);\n" // do not simplify - " std::cout << logbf(1.0f);\n" // simplify to 0 - "}"; + " std::cout << logbf(x);\n" // do not simplify + " std::cout << logbf(10);\n" // do not simplify + " std::cout << logbf(1.0f);\n" // simplify to 0 + "}"; const char expected_logbf[] = "void f ( float x ) {\n" "std :: cout << logbf ( x ) ;\n" "std :: cout << logbf ( 10 ) ;\n" @@ -1344,10 +1343,10 @@ private: ASSERT_EQUALS(expected_logbf, tokWithNewlines(code_logbf)); const char code_logbl[] ="void f(long double x) {\n" - " std::cout << logbl(x);\n" // do not simplify - " std::cout << logbl(10.0f);\n" // do not simplify - " std::cout << logbl(1.0f);\n" // simplify to 0 - "}"; + " std::cout << logbl(x);\n" // do not simplify + " std::cout << logbl(10.0f);\n" // do not simplify + " std::cout << logbl(1.0f);\n" // simplify to 0 + "}"; const char expected_logbl[] = "void f ( double x ) {\n" "std :: cout << logbl ( x ) ;\n" "std :: cout << logbl ( 10.0f ) ;\n" @@ -1359,10 +1358,10 @@ private: void simplifyMathFunctions_log1p() { // verify log1p(), log1pf(), log1pl() - simplifcation const char code_log1p[] ="void f(int x) {\n" - " std::cout << log1p(x);\n" // do not simplify - " std::cout << log1p(10);\n" // do not simplify - " std::cout << log1p(0L);\n" // simplify to 0 - "}"; + " std::cout << log1p(x);\n" // do not simplify + " std::cout << log1p(10);\n" // do not simplify + " std::cout << log1p(0L);\n" // simplify to 0 + "}"; const char expected_log1p[] = "void f ( int x ) {\n" "std :: cout << log1p ( x ) ;\n" "std :: cout << log1p ( 10 ) ;\n" @@ -1371,10 +1370,10 @@ private: ASSERT_EQUALS(expected_log1p, tokWithNewlines(code_log1p)); const char code_log1pf[] ="void f(float x) {\n" - " std::cout << log1pf(x);\n" // do not simplify - " std::cout << log1pf(10);\n" // do not simplify - " std::cout << log1pf(0.0f);\n" // simplify to 0 - "}"; + " std::cout << log1pf(x);\n" // do not simplify + " std::cout << log1pf(10);\n" // do not simplify + " std::cout << log1pf(0.0f);\n" // simplify to 0 + "}"; const char expected_log1pf[] = "void f ( float x ) {\n" "std :: cout << log1pf ( x ) ;\n" "std :: cout << log1pf ( 10 ) ;\n" @@ -1383,10 +1382,10 @@ private: ASSERT_EQUALS(expected_log1pf, tokWithNewlines(code_log1pf)); const char code_log1pl[] ="void f(long double x) {\n" - " std::cout << log1pl(x);\n" // do not simplify - " std::cout << log1pl(10.0f);\n" // do not simplify - " std::cout << log1pl(0.0f);\n" // simplify to 0 - "}"; + " std::cout << log1pl(x);\n" // do not simplify + " std::cout << log1pl(10.0f);\n" // do not simplify + " std::cout << log1pl(0.0f);\n" // simplify to 0 + "}"; const char expected_log1pl[] = "void f ( double x ) {\n" "std :: cout << log1pl ( x ) ;\n" "std :: cout << log1pl ( 10.0f ) ;\n" @@ -1398,10 +1397,10 @@ private: void simplifyMathFunctions_log10() { // verify log10(), log10f(), log10l() - simplifcation const char code_log10[] ="void f(int x) {\n" - " std::cout << log10(x);\n" // do not simplify - " std::cout << log10(10);\n" // do not simplify - " std::cout << log10(1L);\n" // simplify to 0 - "}"; + " std::cout << log10(x);\n" // do not simplify + " std::cout << log10(10);\n" // do not simplify + " std::cout << log10(1L);\n" // simplify to 0 + "}"; const char expected_log10[] = "void f ( int x ) {\n" "std :: cout << log10 ( x ) ;\n" "std :: cout << log10 ( 10 ) ;\n" @@ -1410,10 +1409,10 @@ private: ASSERT_EQUALS(expected_log10, tokWithNewlines(code_log10)); const char code_log10f[] ="void f(float x) {\n" - " std::cout << log10f(x);\n" // do not simplify - " std::cout << log10f(10);\n" // do not simplify - " std::cout << log10f(1.0f);\n" // simplify to 0 - "}"; + " std::cout << log10f(x);\n" // do not simplify + " std::cout << log10f(10);\n" // do not simplify + " std::cout << log10f(1.0f);\n" // simplify to 0 + "}"; const char expected_log10f[] = "void f ( float x ) {\n" "std :: cout << log10f ( x ) ;\n" "std :: cout << log10f ( 10 ) ;\n" @@ -1422,10 +1421,10 @@ private: ASSERT_EQUALS(expected_log10f, tokWithNewlines(code_log10f)); const char code_log10l[] ="void f(long double x) {\n" - " std::cout << log10l(x);\n" // do not simplify - " std::cout << log10l(10.0f);\n" // do not simplify - " std::cout << log10l(1.0f);\n" // simplify to 0 - "}"; + " std::cout << log10l(x);\n" // do not simplify + " std::cout << log10l(10.0f);\n" // do not simplify + " std::cout << log10l(1.0f);\n" // simplify to 0 + "}"; const char expected_log10l[] = "void f ( double x ) {\n" "std :: cout << log10l ( x ) ;\n" "std :: cout << log10l ( 10.0f ) ;\n" @@ -1437,10 +1436,10 @@ private: void simplifyMathFunctions_log() { // verify log(), logf(), logl() - simplifcation const char code_log[] ="void f(int x) {\n" - " std::cout << log(x);\n" // do not simplify - " std::cout << log(10);\n" // do not simplify - " std::cout << log(1L);\n" // simplify to 0 - "}"; + " std::cout << log(x);\n" // do not simplify + " std::cout << log(10);\n" // do not simplify + " std::cout << log(1L);\n" // simplify to 0 + "}"; const char expected_log[] = "void f ( int x ) {\n" "std :: cout << log ( x ) ;\n" "std :: cout << log ( 10 ) ;\n" @@ -1449,10 +1448,10 @@ private: ASSERT_EQUALS(expected_log, tokWithNewlines(code_log)); const char code_logf[] ="void f(float x) {\n" - " std::cout << logf(x);\n" // do not simplify - " std::cout << logf(10);\n" // do not simplify - " std::cout << logf(1.0f);\n" // simplify to 0 - "}"; + " std::cout << logf(x);\n" // do not simplify + " std::cout << logf(10);\n" // do not simplify + " std::cout << logf(1.0f);\n" // simplify to 0 + "}"; const char expected_logf[] = "void f ( float x ) {\n" "std :: cout << logf ( x ) ;\n" "std :: cout << logf ( 10 ) ;\n" @@ -1461,10 +1460,10 @@ private: ASSERT_EQUALS(expected_logf, tokWithNewlines(code_logf)); const char code_logl[] ="void f(long double x) {\n" - " std::cout << logl(x);\n" // do not simplify - " std::cout << logl(10.0f);\n" // do not simplify - " std::cout << logl(1.0f);\n" // simplify to 0 - "}"; + " std::cout << logl(x);\n" // do not simplify + " std::cout << logl(10.0f);\n" // do not simplify + " std::cout << logl(1.0f);\n" // simplify to 0 + "}"; const char expected_logl[] = "void f ( double x ) {\n" "std :: cout << logl ( x ) ;\n" "std :: cout << logl ( 10.0f ) ;\n" @@ -1476,10 +1475,10 @@ private: void simplifyMathFunctions_log2() { // verify log2(), log2f(), log2l() - simplifcation const char code_log2[] ="void f(int x) {\n" - " std::cout << log2(x);\n" // do not simplify - " std::cout << log2(10);\n" // do not simplify - " std::cout << log2(1L);\n" // simplify to 0 - "}"; + " std::cout << log2(x);\n" // do not simplify + " std::cout << log2(10);\n" // do not simplify + " std::cout << log2(1L);\n" // simplify to 0 + "}"; const char expected_log2[] = "void f ( int x ) {\n" "std :: cout << log2 ( x ) ;\n" "std :: cout << log2 ( 10 ) ;\n" @@ -1488,10 +1487,10 @@ private: ASSERT_EQUALS(expected_log2, tokWithNewlines(code_log2)); const char code_log2f[] ="void f(float x) {\n" - " std::cout << log2f(x);\n" // do not simplify - " std::cout << log2f(10);\n" // do not simplify - " std::cout << log2f(1.0f);\n" // simplify to 0 - "}"; + " std::cout << log2f(x);\n" // do not simplify + " std::cout << log2f(10);\n" // do not simplify + " std::cout << log2f(1.0f);\n" // simplify to 0 + "}"; const char expected_log2f[] = "void f ( float x ) {\n" "std :: cout << log2f ( x ) ;\n" "std :: cout << log2f ( 10 ) ;\n" @@ -1500,10 +1499,10 @@ private: ASSERT_EQUALS(expected_log2f, tokWithNewlines(code_log2f)); const char code_log2l[] ="void f(long double x) {\n" - " std::cout << log2l(x);\n" // do not simplify - " std::cout << log2l(10.0f);\n" // do not simplify - " std::cout << log2l(1.0f);\n" // simplify to 0 - "}"; + " std::cout << log2l(x);\n" // do not simplify + " std::cout << log2l(10.0f);\n" // do not simplify + " std::cout << log2l(1.0f);\n" // simplify to 0 + "}"; const char expected_log2l[] = "void f ( double x ) {\n" "std :: cout << log2l ( x ) ;\n" "std :: cout << log2l ( 10.0f ) ;\n" @@ -1515,19 +1514,19 @@ private: void simplifyMathFunctions_pow() { // verify pow(),pow(),powl() - simplifcation const char code_pow[] ="void f() {\n" - " std::cout << pow(-1.0,1);\n" - " std::cout << pow(1.0,1);\n" - " std::cout << pow(0,1);\n" - " std::cout << pow(1,-6);\n" - " std::cout << powf(-1.0,1.0f);\n" - " std::cout << powf(1.0,1.0f);\n" - " std::cout << powf(0,1.0f);\n" - " std::cout << powf(1.0,-6.0f);\n" - " std::cout << powl(-1.0,1.0);\n" - " std::cout << powl(1.0,1.0);\n" - " std::cout << powl(0,1.0);\n" - " std::cout << powl(1.0,-6.0d);\n" - "}"; + " std::cout << pow(-1.0,1);\n" + " std::cout << pow(1.0,1);\n" + " std::cout << pow(0,1);\n" + " std::cout << pow(1,-6);\n" + " std::cout << powf(-1.0,1.0f);\n" + " std::cout << powf(1.0,1.0f);\n" + " std::cout << powf(0,1.0f);\n" + " std::cout << powf(1.0,-6.0f);\n" + " std::cout << powl(-1.0,1.0);\n" + " std::cout << powl(1.0,1.0);\n" + " std::cout << powl(0,1.0);\n" + " std::cout << powl(1.0,-6.0d);\n" + "}"; const char expected_pow[] = "void f ( ) {\n" "std :: cout << -1.0 ;\n" @@ -1567,16 +1566,16 @@ private: void simplifyMathFunctions_fmin() { // verify fmin,fminl,fminl simplifcation const char code_fmin[] ="void f() {\n" - " std::cout << fmin(-1.0,0);\n" - " std::cout << fmin(1.0,0);\n" - " std::cout << fmin(0,0);\n" - " std::cout << fminf(-1.0,0);\n" - " std::cout << fminf(1.0,0);\n" - " std::cout << fminf(0,0);\n" - " std::cout << fminl(-1.0,0);\n" - " std::cout << fminl(1.0,0);\n" - " std::cout << fminl(0,0);\n" - "}"; + " std::cout << fmin(-1.0,0);\n" + " std::cout << fmin(1.0,0);\n" + " std::cout << fmin(0,0);\n" + " std::cout << fminf(-1.0,0);\n" + " std::cout << fminf(1.0,0);\n" + " std::cout << fminf(0,0);\n" + " std::cout << fminl(-1.0,0);\n" + " std::cout << fminl(1.0,0);\n" + " std::cout << fminl(0,0);\n" + "}"; const char expected_fmin[] = "void f ( ) {\n" "std :: cout << -1.0 ;\n" @@ -1600,16 +1599,16 @@ private: void simplifyMathFunctions_fmax() { // verify fmax(),fmax(),fmaxl() simplifcation const char code_fmax[] ="void f() {\n" - " std::cout << fmax(-1.0,0);\n" - " std::cout << fmax(1.0,0);\n" - " std::cout << fmax(0,0);\n" - " std::cout << fmaxf(-1.0,0);\n" - " std::cout << fmaxf(1.0,0);\n" - " std::cout << fmaxf(0,0);\n" - " std::cout << fmaxl(-1.0,0);\n" - " std::cout << fmaxl(1.0,0);\n" - " std::cout << fmaxl(0,0);\n" - "}"; + " std::cout << fmax(-1.0,0);\n" + " std::cout << fmax(1.0,0);\n" + " std::cout << fmax(0,0);\n" + " std::cout << fmaxf(-1.0,0);\n" + " std::cout << fmaxf(1.0,0);\n" + " std::cout << fmaxf(0,0);\n" + " std::cout << fmaxl(-1.0,0);\n" + " std::cout << fmaxl(1.0,0);\n" + " std::cout << fmaxl(0,0);\n" + "}"; const char expected_fmax[] = "void f ( ) {\n" "std :: cout << 0 ;\n" @@ -1969,21 +1968,21 @@ private: void combine_strings() { const char code1[] = "void foo()\n" - "{\n" - "const char *a =\n" - "{\n" - "\"hello \"\n" - "\"world\"\n" - "};\n" - "}\n"; + "{\n" + "const char *a =\n" + "{\n" + "\"hello \"\n" + "\"world\"\n" + "};\n" + "}\n"; const char code2[] = "void foo()\n" - "{\n" - "const char *a =\n" - "{\n" - "\"hello world\"\n" - "};\n" - "}\n"; + "{\n" + "const char *a =\n" + "{\n" + "\"hello world\"\n" + "};\n" + "}\n"; ASSERT_EQUALS(tok(code2), tok(code1)); const char code3[] = "x = L\"1\" TEXT(\"2\") L\"3\";"; @@ -2056,61 +2055,61 @@ private: void double_plus() { { const char code1[] = "void foo( int a )\n" - "{\n" - "a++;\n" - "a--;\n" - "++a;\n" - "--a;\n" - "}\n"; + "{\n" + "a++;\n" + "a--;\n" + "++a;\n" + "--a;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a ++ ; a -- ; ++ a ; -- a ; }", tok(code1)); } { const char code1[] = "void foo( int a )\n" - "{\n" - "a=a+a;\n" - "}\n"; + "{\n" + "a=a+a;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a = a + a ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a+++b;\n" - "}\n"; + "{\n" + "a=a+++b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a ++ + b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a---b;\n" - "}\n"; + "{\n" + "a=a---b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a -- - b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a--+b;\n" - "}\n"; + "{\n" + "a=a--+b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a -- + b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a++-b;\n" - "}\n"; + "{\n" + "a=a++-b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a ++ - b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a+--b;\n" - "}\n"; + "{\n" + "a=a+--b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a + -- b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a-++b;\n" - "}\n"; + "{\n" + "a=a-++b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a - ++ b ; }", tok(code1)); } } @@ -2118,51 +2117,51 @@ private: void redundant_plus() { { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a + + b;\n" - "}\n"; + "{\n" + "a=a + + b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a + b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a + + + b;\n" - "}\n"; + "{\n" + "a=a + + + b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a + b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a + - b;\n" - "}\n"; + "{\n" + "a=a + - b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a - b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a - + b;\n" - "}\n"; + "{\n" + "a=a - + b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a - b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a - - b;\n" - "}\n"; + "{\n" + "a=a - - b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a + b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a - + - b;\n" - "}\n"; + "{\n" + "a=a - + - b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a + b ; }", tok(code1)); } { const char code1[] = "void foo( int a, int b )\n" - "{\n" - "a=a - - - b;\n" - "}\n"; + "{\n" + "a=a - - - b;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a , int b ) { a = a - b ; }", tok(code1)); } } @@ -2170,51 +2169,51 @@ private: void redundant_plus_numbers() { { const char code1[] = "void foo( int a )\n" - "{\n" - "a=a + + 1;\n" - "}\n"; + "{\n" + "a=a + + 1;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a = a + 1 ; }", tok(code1)); } { const char code1[] = "void foo( int a )\n" - "{\n" - "a=a + + + 1;\n" - "}\n"; + "{\n" + "a=a + + + 1;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a = a + 1 ; }", tok(code1)); } { const char code1[] = "void foo( int a )\n" - "{\n" - "a=a + - 1;\n" - "}\n"; + "{\n" + "a=a + - 1;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a = a - 1 ; }", tok(code1)); } { const char code1[] = "void foo( int a )\n" - "{\n" - "a=a - + 1;\n" - "}\n"; + "{\n" + "a=a - + 1;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a = a - 1 ; }", tok(code1)); } { const char code1[] = "void foo( int a )\n" - "{\n" - "a=a - - 1;\n" - "}\n"; + "{\n" + "a=a - - 1;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a = a + 1 ; }", tok(code1)); } { const char code1[] = "void foo( int a )\n" - "{\n" - "a=a - + - 1;\n" - "}\n"; + "{\n" + "a=a - + - 1;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a = a + 1 ; }", tok(code1)); } { const char code1[] = "void foo( int a )\n" - "{\n" - "a=a - - - 1;\n" - "}\n"; + "{\n" + "a=a - - - 1;\n" + "}\n"; ASSERT_EQUALS("void foo ( int a ) { a = a - 1 ; }", tok(code1)); } } @@ -2345,14 +2344,14 @@ private: { const char src[] = "void f(int g,int f) {\n" - "if(g==1) {poo();}\n" - "else if( g == 2 )\n" - "{\n" - " if( f == 0 ){coo();}\n" - " else if( f==1)\n" - " goo();\n" - "}\n" - "}"; + "if(g==1) {poo();}\n" + "else if( g == 2 )\n" + "{\n" + " if( f == 0 ){coo();}\n" + " else if( f==1)\n" + " goo();\n" + "}\n" + "}"; const char expected[] = "void f ( int g , int f ) " "{ " @@ -2562,7 +2561,7 @@ private: "{g(sizeof(a),sizeof(b),sizeof(c));}"; std::ostringstream expected; expected << "void f ( char * a , char * b , char * c ) { g ( " << - sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; ASSERT_EQUALS(expected.str(), tok(code)); } @@ -2571,7 +2570,7 @@ private: "{g(sizeof(a),sizeof(b),sizeof(c));}"; std::ostringstream expected; expected << "void f ( char a , char b , char c ) { g ( " << - sizeofFromTokenizer("char") << " , " << sizeofFromTokenizer("char") << " , " << sizeofFromTokenizer("char") << " ) ; }"; + sizeofFromTokenizer("char") << " , " << sizeofFromTokenizer("char") << " , " << sizeofFromTokenizer("char") << " ) ; }"; ASSERT_EQUALS(expected.str(), tok(code)); } @@ -2580,7 +2579,7 @@ private: "{g(sizeof(a),sizeof(b),sizeof(c));}"; std::ostringstream expected; expected << "void f ( const char * a , const char * b , const char * c ) { g ( " << - sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; ASSERT_EQUALS(expected.str(), tok(code)); } @@ -2589,7 +2588,7 @@ private: "{g(sizeof(a),sizeof(b),sizeof(c));}"; std::ostringstream expected; expected << "void f ( char a [ 10 ] , char b [ 10 ] , char c [ 10 ] ) { g ( " << - sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; ASSERT_EQUALS(expected.str(), tok(code)); } @@ -2598,9 +2597,9 @@ private: "{g(sizeof(a),sizeof(b),sizeof(c));}"; std::ostringstream expected; expected << "void f ( const char a [ 10 ] , " - "const char b [ 10 ] , " - "const char c [ 10 ] ) { g ( " << - sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + "const char b [ 10 ] , " + "const char c [ 10 ] ) { g ( " << + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; ASSERT_EQUALS(expected.str(), tok(code)); } @@ -2609,9 +2608,9 @@ private: "{g(sizeof(a),sizeof(b),sizeof(c));}"; std::ostringstream expected; expected << "void f ( const char * a [ 10 ] , " - "const char * b [ 10 ] , " - "const char * c [ 10 ] ) { g ( " << - sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + "const char * b [ 10 ] , " + "const char * c [ 10 ] ) { g ( " << + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; ASSERT_EQUALS(expected.str(), tok(code)); } @@ -2620,7 +2619,7 @@ private: "{g(sizeof(a),sizeof(b),sizeof(c));}"; std::ostringstream expected; expected << "void f ( char * a [ 10 ] , char * b [ 10 ] , char * c [ 10 ] ) { g ( " << - sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; + sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " , " << sizeofFromTokenizer("*") << " ) ; }"; ASSERT_EQUALS(expected.str(), tok(code)); } @@ -3128,12 +3127,12 @@ private: void ifAssignWithCast() { const char *code = "void foo()\n" - "{\n" - "FILE *f;\n" - "if( (f = fopen(\"foo\", \"r\")) == ((FILE*)NULL) )\n" - "return(-1);\n" - "fclose(f);\n" - "}\n"; + "{\n" + "FILE *f;\n" + "if( (f = fopen(\"foo\", \"r\")) == ((FILE*)NULL) )\n" + "return(-1);\n" + "fclose(f);\n" + "}\n"; const char *expected = "void foo ( ) " "{ " "FILE * f ; " @@ -6615,7 +6614,7 @@ private: " Other\n" " };\n" " enum { XX };\n" - "};", /*simplify=*/true); + "};", /*simplify=*/ true); ASSERT_EQUALS("", errout.str()); } @@ -6627,7 +6626,7 @@ private: tokenizeAndStringify("void foo(std::string str) {\n" " char *p = &str[0];\n" " *p = 0;\n" - "}", /*simplify=*/true)); + "}", /*simplify=*/ true)); } void simplifyKnownVariablesBailOutAssign1() { @@ -6856,7 +6855,7 @@ private: "printf ( \"test\" ) ;\n" "delete [ ] data ;\n" "}"; - ASSERT_EQUALS(exp, tokenizeAndStringify(code, /*simplify=*/true)); + ASSERT_EQUALS(exp, tokenizeAndStringify(code, /*simplify=*/ true)); } void simplifyKnownVariablesClassMember() { @@ -7051,16 +7050,16 @@ private: "foo < 1 ? 0 ? 1 : 6 : 2 > x ;\n" "foo < 1 ? 0 : 2 > y ;\n" "}"; - const char exp [] = "template < class T > struct foo ; " - "void bar ( ) { " - "foo < 6 > x ; " - "foo < 0 > y ; " - "}"; + const char exp[] = "template < class T > struct foo ; " + "void bar ( ) { " + "foo < 6 > x ; " + "foo < 0 > y ; " + "}"; ASSERT_EQUALS(exp, tok(code)); } { const char code[] = "bool b = true ? false : 1 > 2 ;"; - const char exp [] = "bool b ; b = false ;"; + const char exp[] = "bool b ; b = false ;"; ASSERT_EQUALS(exp, tok(code)); } } diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 3421781b6..b4c027dea 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -29,8 +29,7 @@ struct InternalError; class TestSimplifyTypedef : public TestFixture { public: - TestSimplifyTypedef() : TestFixture("TestSimplifyTypedef") { - } + TestSimplifyTypedef() : TestFixture("TestSimplifyTypedef") {} private: @@ -2438,7 +2437,7 @@ private: "}\n" "namespace Baz { }\n" "enum Bar { XX = 1 };"; - const char exp [] = "enum Bar { XX = 1 } ;"; + const char exp[] = "enum Bar { XX = 1 } ;"; ASSERT_EQUALS(exp, tok(code, false)); ASSERT_EQUALS("", errout.str()); } @@ -2447,8 +2446,8 @@ private: const char code[] = "typedef char test_utf8_char[5];\n" "static test_utf8_char const bad_chars[] = { };\n" "static void report_good(bool passed, test_utf8_char const c) { };"; - const char exp [] = "static const char bad_chars [ ] [ 5 ] = { } ; " - "static void report_good ( bool passed , const char c [ 5 ] ) { } ;"; + const char exp[] = "static const char bad_chars [ ] [ 5 ] = { } ; " + "static void report_good ( bool passed , const char c [ 5 ] ) { } ;"; ASSERT_EQUALS(exp, tok(code, false)); ASSERT_EQUALS("", errout.str()); } @@ -2471,21 +2470,21 @@ private: "mat3x3 & Fred::m() { return m3x3; }\n" "const vec3 & Fred::vc() const { return v3; }\n" "const mat3x3 & Fred::mc() const { return m3x3; }"; - const char exp [] = "float v3 [ 3 ] ; " - "float m3x3 [ 3 ] [ 3 ] ; " - "const float ( & gv ( ) ) [ 3 ] { return v3 ; } " - "const float ( & gm ( ) ) [ 3 ] [ 3 ] { return m3x3 ; } " - "class Fred { " - "public: " - "float ( & v ( ) ) [ 3 ] ; " - "float ( & m ( ) ) [ 3 ] [ 3 ] ; " - "const float ( & vc ( ) const ) [ 3 ] ; " - "const float ( & mc ( ) const ) [ 3 ] [ 3 ] ; " - "} ; " - "float ( & Fred :: v ( ) ) [ 3 ] { return v3 ; } " - "float ( & Fred :: m ( ) ) [ 3 ] [ 3 ] { return m3x3 ; } " - "const float ( & Fred :: vc ( ) const ) [ 3 ] { return v3 ; } " - "const float ( & Fred :: mc ( ) const ) [ 3 ] [ 3 ] { return m3x3 ; }"; + const char exp[] = "float v3 [ 3 ] ; " + "float m3x3 [ 3 ] [ 3 ] ; " + "const float ( & gv ( ) ) [ 3 ] { return v3 ; } " + "const float ( & gm ( ) ) [ 3 ] [ 3 ] { return m3x3 ; } " + "class Fred { " + "public: " + "float ( & v ( ) ) [ 3 ] ; " + "float ( & m ( ) ) [ 3 ] [ 3 ] ; " + "const float ( & vc ( ) const ) [ 3 ] ; " + "const float ( & mc ( ) const ) [ 3 ] [ 3 ] ; " + "} ; " + "float ( & Fred :: v ( ) ) [ 3 ] { return v3 ; } " + "float ( & Fred :: m ( ) ) [ 3 ] [ 3 ] { return m3x3 ; } " + "const float ( & Fred :: vc ( ) const ) [ 3 ] { return v3 ; } " + "const float ( & Fred :: mc ( ) const ) [ 3 ] [ 3 ] { return m3x3 ; }"; ASSERT_EQUALS(exp, tok(code, false)); ASSERT_EQUALS("", errout.str()); } @@ -2499,7 +2498,7 @@ private: void simplifyTypedef123() { // ticket #7406 const char code[] = "typedef int intvec[1];\n" "Dummy y;"; - const char exp [] = "Dummy < int [ 1 ] > y ;"; + const char exp[] = "Dummy < int [ 1 ] > y ;"; ASSERT_EQUALS(exp, tok(code, false)); ASSERT_EQUALS("", errout.str()); } @@ -2524,14 +2523,14 @@ private: void simplifyTypedef125() { // #8749 const char code[] = "typedef char A[3];\n" "char (*p)[3] = new A[4];"; - const char exp [] = "char ( * p ) [ 3 ] = new char [ 4 ] [ 3 ] ;"; + const char exp[] = "char ( * p ) [ 3 ] = new char [ 4 ] [ 3 ] ;"; ASSERT_EQUALS(exp, tok(code, false)); } void simplifyTypedef126() { // #5953 const char code[] = "typedef char automap_data_t[100];\n" "void write_array(automap_data_t *data) {}"; - const char exp [] = "void write_array ( char ( * data ) [ 100 ] ) { }"; + const char exp[] = "void write_array ( char ( * data ) [ 100 ] ) { }"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2539,9 +2538,9 @@ private: const char code[] = "class a; typedef int (a::*b); " "template struct c; " "template struct d { enum { e = c::f }; };"; - const char exp [] = "class a ; " - "template < long , class > struct c ; " - "template < int g > struct d { enum Anonymous0 { e = c < g , int ( a :: * ) > :: f } ; } ;"; + const char exp[] = "class a ; " + "template < long , class > struct c ; " + "template < int g > struct d { enum Anonymous0 { e = c < g , int ( a :: * ) > :: f } ; } ;"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2550,9 +2549,9 @@ private: "void f() {\n" " dostuff((const d){1,2,3,4});\n" "}"; - const char exp [] = "void f ( ) { " - "dostuff ( ( const int [ 4 ] ) { 1 , 2 , 3 , 4 } ) ; " - "}"; + const char exp[] = "void f ( ) { " + "dostuff ( ( const int [ 4 ] ) { 1 , 2 , 3 , 4 } ) ; " + "}"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2563,7 +2562,7 @@ private: " foo &f ;\n" "};"; - const char exp [] = "class c { char ( & f ) [ 4 ] ; } ;"; + const char exp[] = "class c { char ( & f ) [ 4 ] ; } ;"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2573,7 +2572,7 @@ private: " const foo &f;\n" "};"; - const char exp [] = "class c { const char ( & f ) [ 4 ] ; } ;"; + const char exp[] = "class c { const char ( & f ) [ 4 ] ; } ;"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2584,7 +2583,7 @@ private: " constexpr const foo &c_str() const noexcept { return _a; }\n" "};"; - const char exp [] = "class c { char _a [ 4 ] ; const constexpr char ( & c_str ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char exp[] = "class c { char _a [ 4 ] ; const constexpr char ( & c_str ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2595,8 +2594,8 @@ private: " constexpr operator foo &() const noexcept { return _a; }\n" "};"; - const char actual [] = "class c { char _a [ 4 ] ; constexpr operatorchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; - const char exp [] = "class c { char _a [ 4 ] ; const operator char ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char actual[] = "class c { char _a [ 4 ] ; constexpr operatorchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char exp[] = "class c { char _a [ 4 ] ; const operator char ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; TODO_ASSERT_EQUALS(exp, actual, tok(code, false)); } @@ -2607,8 +2606,8 @@ private: " constexpr operator const foo &() const noexcept { return _a; }\n" "};"; - const char actual [] = "class c { char _a [ 4 ] ; constexpr operatorconstchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; - const char exp [] = "class c { char _a [ 4 ] ; const operator const char ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char actual[] = "class c { char _a [ 4 ] ; constexpr operatorconstchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char exp[] = "class c { char _a [ 4 ] ; const operator const char ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; TODO_ASSERT_EQUALS(exp, actual, tok(code, false)); } } @@ -2619,9 +2618,9 @@ private: " a();\n" "}"; - const char exp [] = "template < class , class > void a ( ) { " - "a < int ( * ) [ 10 ] , int ( * ) [ 10 ] > ( ) ; " - "}"; + const char exp[] = "template < class , class > void a ( ) { " + "a < int ( * ) [ 10 ] , int ( * ) [ 10 ] > ( ) ; " + "}"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2633,11 +2632,11 @@ private: "a4* a4p = &(a4obj);\n" "a4*&& a4p_rref = std::move(a4p);"; - const char exp [] = "unsigned char a4obj [ 4 ] ; " - "unsigned char ( && a4_rref ) [ 4 ] = std :: move ( a4obj ) ; " - "unsigned char ( * a4p ) [ 4 ] ; " - "a4p = & ( a4obj ) ; " - "unsigned char ( * && a4p_rref ) [ 4 ] = std :: move ( a4p ) ;"; + const char exp[] = "unsigned char a4obj [ 4 ] ; " + "unsigned char ( && a4_rref ) [ 4 ] = std :: move ( a4obj ) ; " + "unsigned char ( * a4p ) [ 4 ] ; " + "a4p = & ( a4obj ) ; " + "unsigned char ( * && a4p_rref ) [ 4 ] = std :: move ( a4p ) ;"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2655,10 +2654,10 @@ private: "\n" "void A::DoSomething( MySpecialType wrongName ) {}"; - const char exp [] = "class A { " - "void DoSomething ( int special ) ; " - "} ; " - "void A :: DoSomething ( int wrongName ) { }"; + const char exp[] = "class A { " + "void DoSomething ( int special ) ; " + "} ; " + "void A :: DoSomething ( int wrongName ) { }"; ASSERT_EQUALS(exp, tok(code, false)); } diff --git a/test/testsimplifyusing.cpp b/test/testsimplifyusing.cpp index ae4317836..810f9f886 100644 --- a/test/testsimplifyusing.cpp +++ b/test/testsimplifyusing.cpp @@ -29,8 +29,7 @@ struct InternalError; class TestSimplifyUsing : public TestFixture { public: - TestSimplifyUsing() : TestFixture("TestSimplifyUsing") { - } + TestSimplifyUsing() : TestFixture("TestSimplifyUsing") {} private: diff --git a/test/testsizeof.cpp b/test/testsizeof.cpp index ee95578ab..6b4a8d204 100644 --- a/test/testsizeof.cpp +++ b/test/testsizeof.cpp @@ -27,8 +27,7 @@ class TestSizeof : public TestFixture { public: - TestSizeof() : TestFixture("TestSizeof") { - } + TestSizeof() : TestFixture("TestSizeof") {} private: Settings settings; diff --git a/test/teststl.cpp b/test/teststl.cpp index 3880c79a0..41db23eca 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -28,8 +28,7 @@ class TestStl : public TestFixture { public: - TestStl() : TestFixture("TestStl") { - } + TestStl() : TestFixture("TestStl") {} private: Settings settings; @@ -2634,7 +2633,7 @@ private: } template - static size_t getArraylength(const T(&)[n]) { + static size_t getArraylength(const T (&)[n]) { return n; } @@ -3070,10 +3069,10 @@ private: ASSERT_EQUALS("", errout.str()); code = "void f()\n" - "{\n" - " std::list x;\n" - " if (x.size() >= 1) {}\n" - "}"; + "{\n" + " std::list x;\n" + " if (x.size() >= 1) {}\n" + "}"; check(code, false, Standards::CPP03); ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str()); check(code); @@ -3137,10 +3136,10 @@ private: ASSERT_EQUALS("", errout.str()); code ="void f()\n" - "{\n" - " std::list x;\n" - " fun(!x.size());\n" - "}"; + "{\n" + " std::list x;\n" + " fun(!x.size());\n" + "}"; check(code, false, Standards::CPP03); ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str()); check(code); diff --git a/test/teststring.cpp b/test/teststring.cpp index 426201eef..32a8c67f0 100644 --- a/test/teststring.cpp +++ b/test/teststring.cpp @@ -25,8 +25,7 @@ class TestString : public TestFixture { public: - TestString() : TestFixture("TestString") { - } + TestString() : TestFixture("TestString") {} private: Settings settings; diff --git a/test/testsuite.cpp b/test/testsuite.cpp index 0bd62e41c..3ee2f4d34 100644 --- a/test/testsuite.cpp +++ b/test/testsuite.cpp @@ -67,7 +67,7 @@ public: **/ std::ostringstream TestFixture::errmsg; -unsigned int TestFixture::countTests; +unsigned int TestFixture::countTests; std::size_t TestFixture::fails_counter = 0; std::size_t TestFixture::todos_counter = 0; @@ -75,10 +75,10 @@ std::size_t TestFixture::succeeded_todos_counter = 0; std::set TestFixture::missingLibs; TestFixture::TestFixture(const char * const _name) - :mVerbose(false), - exename(), - quiet_tests(false), - classname(_name) + : mVerbose(false), + exename(), + quiet_tests(false), + classname(_name) { TestRegistry::theInstance().addTest(this); } @@ -298,21 +298,21 @@ void TestFixture::complainMissingLib(const char * const libname) const void TestFixture::printHelp() { std::cout << "Testrunner - run Cppcheck tests\n" - "\n" - "Syntax:\n" - " testrunner [OPTIONS] [TestClass::TestCase...]\n" - " run all test cases:\n" - " testrunner\n" - " run all test cases in TestClass:\n" - " testrunner TestClass\n" - " run TestClass::TestCase:\n" - " testrunner TestClass::TestCase\n" - " run all test cases in TestClass1 and TestClass2::TestCase:\n" - " testrunner TestClass1 TestClass2::TestCase\n" - "\n" - "Options:\n" - " -q Do not print the test cases that have run.\n" - " -h, --help Print this help.\n"; + "\n" + "Syntax:\n" + " testrunner [OPTIONS] [TestClass::TestCase...]\n" + " run all test cases:\n" + " testrunner\n" + " run all test cases in TestClass:\n" + " testrunner TestClass\n" + " run TestClass::TestCase:\n" + " testrunner TestClass::TestCase\n" + " run all test cases in TestClass1 and TestClass2::TestCase:\n" + " testrunner TestClass1 TestClass2::TestCase\n" + "\n" + "Options:\n" + " -q Do not print the test cases that have run.\n" + " -h, --help Print this help.\n"; } void TestFixture::run(const std::string &str) diff --git a/test/testsuite.h b/test/testsuite.h index b0e47b9d7..4e7e312d8 100644 --- a/test/testsuite.h +++ b/test/testsuite.h @@ -55,7 +55,7 @@ protected: bool assert_(const char * const filename, const unsigned int linenr, const bool condition) const; - template + template bool assertEquals(const char* const filename, const unsigned int linenr, const T& expected, const U& actual, const std::string& msg = emptyString) const { if (expected != actual) { std::ostringstream expectedStr; @@ -103,7 +103,7 @@ protected: void processOptions(const options& args); public: - void bughuntingReport(const std::string &/*str*/) OVERRIDE {} + void bughuntingReport(const std::string & /*str*/) OVERRIDE {} void reportOut(const std::string &outmsg, Color c = Color::Reset) OVERRIDE; void reportErr(const ErrorMessage &msg) OVERRIDE; void run(const std::string &str); @@ -111,7 +111,7 @@ public: const std::string classname; explicit TestFixture(const char * const _name); - ~TestFixture() OVERRIDE { } + ~TestFixture() OVERRIDE {} static std::size_t runTests(const options& args); }; @@ -119,27 +119,27 @@ public: extern std::ostringstream errout; extern std::ostringstream output; -#define TEST_CASE( NAME ) do { if ( prepareTest(#NAME) ) { setVerbose(false); NAME(); } } while(false) +#define TEST_CASE( NAME ) do { if (prepareTest(#NAME)) { setVerbose(false); NAME(); } } while (false) #define ASSERT( CONDITION ) if (!assert_(__FILE__, __LINE__, (CONDITION))) return -#define CHECK_EQUALS( EXPECTED , ACTUAL ) assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL)) -#define ASSERT_EQUALS( EXPECTED , ACTUAL ) if (!assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL))) return -#define ASSERT_EQUALS_WITHOUT_LINENUMBERS( EXPECTED , ACTUAL ) assertEqualsWithoutLineNumbers(__FILE__, __LINE__, EXPECTED, ACTUAL) -#define ASSERT_EQUALS_DOUBLE( EXPECTED , ACTUAL, TOLERANCE ) assertEqualsDouble(__FILE__, __LINE__, EXPECTED, ACTUAL, TOLERANCE) -#define ASSERT_EQUALS_MSG( EXPECTED , ACTUAL, MSG ) assertEquals(__FILE__, __LINE__, EXPECTED, ACTUAL, MSG) -#define ASSERT_THROW( CMD, EXCEPTION ) do { try { CMD ; assertThrowFail(__FILE__, __LINE__); } catch (const EXCEPTION&) { } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while(false) -#define ASSERT_THROW_EQUALS( CMD, EXCEPTION, EXPECTED ) do { try { CMD ; assertThrowFail(__FILE__, __LINE__); } catch (const EXCEPTION&e) { assertEquals(__FILE__, __LINE__, EXPECTED, e.errorMessage); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while(false) -#define ASSERT_NO_THROW( CMD ) do { try { CMD ; } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } } while(false) -#define TODO_ASSERT_THROW( CMD, EXCEPTION ) do { try { CMD ; } catch (const EXCEPTION&) { } catch (...) { assertThrow(__FILE__, __LINE__); } } while(false) -#define TODO_ASSERT( CONDITION ) do { const bool condition=(CONDITION); todoAssertEquals(__FILE__, __LINE__, true, false, condition); } while(false) -#define TODO_ASSERT_EQUALS( WANTED , CURRENT , ACTUAL ) todoAssertEquals(__FILE__, __LINE__, WANTED, CURRENT, ACTUAL) +#define CHECK_EQUALS( EXPECTED, ACTUAL ) assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL)) +#define ASSERT_EQUALS( EXPECTED, ACTUAL ) if (!assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL))) return +#define ASSERT_EQUALS_WITHOUT_LINENUMBERS( EXPECTED, ACTUAL ) assertEqualsWithoutLineNumbers(__FILE__, __LINE__, EXPECTED, ACTUAL) +#define ASSERT_EQUALS_DOUBLE( EXPECTED, ACTUAL, TOLERANCE ) assertEqualsDouble(__FILE__, __LINE__, EXPECTED, ACTUAL, TOLERANCE) +#define ASSERT_EQUALS_MSG( EXPECTED, ACTUAL, MSG ) assertEquals(__FILE__, __LINE__, EXPECTED, ACTUAL, MSG) +#define ASSERT_THROW( CMD, EXCEPTION ) do { try { CMD; assertThrowFail(__FILE__, __LINE__); } catch (const EXCEPTION&) {} catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) +#define ASSERT_THROW_EQUALS( CMD, EXCEPTION, EXPECTED ) do { try { CMD; assertThrowFail(__FILE__, __LINE__); } catch (const EXCEPTION&e) { assertEquals(__FILE__, __LINE__, EXPECTED, e.errorMessage); } catch (...) { assertThrowFail(__FILE__, __LINE__); } } while (false) +#define ASSERT_NO_THROW( CMD ) do { try { CMD; } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } } while (false) +#define TODO_ASSERT_THROW( CMD, EXCEPTION ) do { try { CMD; } catch (const EXCEPTION&) {} catch (...) { assertThrow(__FILE__, __LINE__); } } while (false) +#define TODO_ASSERT( CONDITION ) do { const bool condition=(CONDITION); todoAssertEquals(__FILE__, __LINE__, true, false, condition); } while (false) +#define TODO_ASSERT_EQUALS( WANTED, CURRENT, ACTUAL ) todoAssertEquals(__FILE__, __LINE__, WANTED, CURRENT, ACTUAL) #define EXPECT_EQ( EXPECTED, ACTUAL ) assertEquals(__FILE__, __LINE__, EXPECTED, ACTUAL) -#define REGISTER_TEST( CLASSNAME ) namespace { CLASSNAME instance_##CLASSNAME; } +#define REGISTER_TEST( CLASSNAME ) namespace { CLASSNAME instance_ ## CLASSNAME; } #define LOAD_LIB_2( LIB, NAME ) do { \ - if (((LIB).load(exename.c_str(), NAME).errorcode != Library::ErrorCode::OK)) { \ - complainMissingLib(NAME); \ - return; \ - } \ -} while(false) + if (((LIB).load(exename.c_str(), NAME).errorcode != Library::ErrorCode::OK)) { \ + complainMissingLib(NAME); \ + return; \ + } \ +} while (false) #endif diff --git a/test/testsuites/clang/outofbound.c b/test/testsuites/clang/outofbound.c index 60190b4bc..8be946474 100644 --- a/test/testsuites/clang/outofbound.c +++ b/test/testsuites/clang/outofbound.c @@ -9,120 +9,120 @@ void *malloc(size_t); void *calloc(size_t, size_t); char f1() { - char* s = "abcd"; - char c = s[4]; // no-warning - return s[5] + c; // expected-warning{{Access out-of-bound array element (buffer overflow)}} + char* s = "abcd"; + char c = s[4]; // no-warning + return s[5] + c; // expected-warning{{Access out-of-bound array element (buffer overflow)}} } void f2() { - int *p = malloc(12); - p[3] = 4; // expected-warning{{Access out-of-bound array element (buffer overflow)}} + int *p = malloc(12); + p[3] = 4; // expected-warning{{Access out-of-bound array element (buffer overflow)}} } struct three_words { - int c[3]; + int c[3]; }; struct seven_words { - int c[7]; + int c[7]; }; void f3() { - struct three_words a, *p; - p = &a; - p[0] = a; // no-warning - p[1] = a; // expected-warning{{Access out-of-bound array element (buffer overflow)}} + struct three_words a, *p; + p = &a; + p[0] = a; // no-warning + p[1] = a; // expected-warning{{Access out-of-bound array element (buffer overflow)}} } void f4() { - struct seven_words c; - struct three_words a, *p = (struct three_words *)&c; - p[0] = a; // no-warning - p[1] = a; // no-warning - p[2] = a; // expected-warning{{Access out-of-bound array element (buffer overflow)}} + struct seven_words c; + struct three_words a, *p = (struct three_words *)&c; + p[0] = a; // no-warning + p[1] = a; // no-warning + p[2] = a; // expected-warning{{Access out-of-bound array element (buffer overflow)}} } void f5() { - char *p = calloc(2,2); - p[3] = '.'; // no-warning - p[4] = '!'; // expected-warning{{out-of-bound}} + char *p = calloc(2,2); + p[3] = '.'; // no-warning + p[4] = '!'; // expected-warning{{out-of-bound}} } void f6() { - char a[2]; - int *b = (int*)a; - b[1] = 3; // expected-warning{{out-of-bound}} + char a[2]; + int *b = (int*)a; + b[1] = 3; // expected-warning{{out-of-bound}} } void f7() { - struct three_words a; - a.c[3] = 1; // expected-warning{{out-of-bound}} + struct three_words a; + a.c[3] = 1; // expected-warning{{out-of-bound}} } void vla(int a) { - if (a == 5) { - int x[a]; - x[4] = 4; // no-warning - x[5] = 5; // expected-warning{{out-of-bound}} - } + if (a == 5) { + int x[a]; + x[4] = 4; // no-warning + x[5] = 5; // expected-warning{{out-of-bound}} + } } void alloca_region(int a) { - if (a == 5) { - char *x = __builtin_alloca(a); - x[4] = 4; // no-warning - x[5] = 5; // expected-warning{{out-of-bound}} - } + if (a == 5) { + char *x = __builtin_alloca(a); + x[4] = 4; // no-warning + x[5] = 5; // expected-warning{{out-of-bound}} + } } int symbolic_index(int a) { - int x[2] = {1, 2}; - if (a == 2) { - return x[a]; // expected-warning{{out-of-bound}} - } - return 0; + int x[2] = {1, 2}; + if (a == 2) { + return x[a]; // expected-warning{{out-of-bound}} + } + return 0; } int symbolic_index2(int a) { - int x[2] = {1, 2}; - if (a < 0) { - return x[a]; // expected-warning{{out-of-bound}} - } - return 0; + int x[2] = {1, 2}; + if (a < 0) { + return x[a]; // expected-warning{{out-of-bound}} + } + return 0; } int overflow_binary_search(double in) { - int eee = 16; - if (in < 1e-8 || in > 1e23) { - return 0; - } else { - static const double ins[] = {1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, - 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, - 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; - if (in < ins[eee]) { - eee -= 8; + int eee = 16; + if (in < 1e-8 || in > 1e23) { + return 0; } else { - eee += 8; + static const double ins[] = {1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, + 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, + 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; + if (in < ins[eee]) { + eee -= 8; + } else { + eee += 8; + } + if (in < ins[eee]) { + eee -= 4; + } else { + eee += 4; + } + if (in < ins[eee]) { + eee -= 2; + } else { + eee += 2; + } + if (in < ins[eee]) { + eee -= 1; + } else { + eee += 1; + } + if (in < ins[eee]) { // expected-warning {{Access out-of-bound array element (buffer overflow)}} + eee -= 1; + } } - if (in < ins[eee]) { - eee -= 4; - } else { - eee += 4; - } - if (in < ins[eee]) { - eee -= 2; - } else { - eee += 2; - } - if (in < ins[eee]) { - eee -= 1; - } else { - eee += 1; - } - if (in < ins[eee]) { // expected-warning {{Access out-of-bound array element (buffer overflow)}} - eee -= 1; - } - } - return eee; + return eee; } diff --git a/test/testsuites/duma/leak1.c b/test/testsuites/duma/leak1.c index fdbc4a653..312a016ef 100644 --- a/test/testsuites/duma/leak1.c +++ b/test/testsuites/duma/leak1.c @@ -1,12 +1,12 @@ #include int main() { - printf("Hello world!\n"); + printf("Hello world!\n"); - int* pI; - pI = (int*)malloc(sizeof(int)); - printf("Let's leak a pointer to int\n"); - *pI = 303; + int* pI; + pI = (int*)malloc(sizeof(int)); + printf("Let's leak a pointer to int\n"); + *pI = 303; - return 0; + return 0; } diff --git a/test/testsuites/duma/leak2.c b/test/testsuites/duma/leak2.c index 923754d49..0fa6cb03d 100644 --- a/test/testsuites/duma/leak2.c +++ b/test/testsuites/duma/leak2.c @@ -1,20 +1,20 @@ #include int main() { - printf("Hello world!\n"); + printf("Hello world!\n"); - int* pI; - pI = (int*)malloc(10*sizeof(int)); + int* pI; + pI = (int*)malloc(10*sizeof(int)); - printf("Let's leak a pointer to an array of 10 ints\n"); - int i=0; - for (i=0; i<9; i++) { - pI[i] = 303+i; - } - int j=0; - for (j=0; j<9; j++) { - if (pI[j] != 303+j) printf(" Something strange is happening...\n"); - } + printf("Let's leak a pointer to an array of 10 ints\n"); + int i=0; + for (i=0; i<9; i++) { + pI[i] = 303+i; + } + int j=0; + for (j=0; j<9; j++) { + if (pI[j] != 303+j) printf(" Something strange is happening...\n"); + } - return 0; + return 0; } diff --git a/test/testsuites/duma/wrong1.c b/test/testsuites/duma/wrong1.c index bcbbd2113..196360da6 100644 --- a/test/testsuites/duma/wrong1.c +++ b/test/testsuites/duma/wrong1.c @@ -1,13 +1,13 @@ #include int main() { - printf("Hello world!\n"); + printf("Hello world!\n"); - int* pI = (int*)malloc(sizeof(int)); - *pI=2; - free(pI); - printf("Now freeing a pointer twice...\n"); - free(pI); - printf("Did you notice?\n"); - return 0; + int* pI = (int*)malloc(sizeof(int)); + *pI=2; + free(pI); + printf("Now freeing a pointer twice...\n"); + free(pI); + printf("Did you notice?\n"); + return 0; } diff --git a/test/testsuites/duma/wrong3.c b/test/testsuites/duma/wrong3.c index 80b4c3998..fd0bbf269 100644 --- a/test/testsuites/duma/wrong3.c +++ b/test/testsuites/duma/wrong3.c @@ -1,22 +1,22 @@ #include int main() { - printf("Hello world!\n"); + printf("Hello world!\n"); - int* pI = (int*)malloc(sizeof(int)); - int j; - printf("Now reading uninitialized memory\n"); - j = *pI+2; - printf("Did you notice? (value was %i)\n",j); - free(pI); - printf("(No memory leak here)\n"); + int* pI = (int*)malloc(sizeof(int)); + int j; + printf("Now reading uninitialized memory\n"); + j = *pI+2; + printf("Did you notice? (value was %i)\n",j); + free(pI); + printf("(No memory leak here)\n"); - int* pJ; - printf("Now writing to uninitialized pointer\n"); - *pJ = j; - printf("Did you notice?\n"); + int* pJ; + printf("Now writing to uninitialized pointer\n"); + *pJ = j; + printf("Did you notice?\n"); - // valgrind reports 8, but that's ok - printf("There should be 2 errors in this run\n"); - return 0; + // valgrind reports 8, but that's ok + printf("There should be 2 errors in this run\n"); + return 0; } diff --git a/test/testsuites/duma/wrong6.c b/test/testsuites/duma/wrong6.c index 973e89b9d..4666c07dd 100644 --- a/test/testsuites/duma/wrong6.c +++ b/test/testsuites/duma/wrong6.c @@ -1,19 +1,19 @@ #include struct Test { - int a; - char st[10]; + int a; + char st[10]; }; int main() { - printf("Hello world!\n"); + printf("Hello world!\n"); - struct Test ar[10]; - struct Test b; - printf("Let's index out of bounds \n"); - ar[10].a=10; - printf("Did you notice?\n"); - - printf("There should be 1 error in this run\n"); - return 0; + struct Test ar[10]; + struct Test b; + printf("Let's index out of bounds \n"); + ar[10].a=10; + printf("Did you notice?\n"); + + printf("There should be 1 error in this run\n"); + return 0; } diff --git a/test/testsuites/duma/wrong7.c b/test/testsuites/duma/wrong7.c index 0faf6913a..3773e75ea 100644 --- a/test/testsuites/duma/wrong7.c +++ b/test/testsuites/duma/wrong7.c @@ -1,13 +1,13 @@ #include int main() { - int *p; + int *p; - p = (int*) malloc( sizeof(int) * 10 ); - printf("Now writing before our allocated array\n"); - p[-1] ^= 0x0F; /* bash before */ - printf("... and now after our allocated array\n"); - p[10] ^= 0x0F; /* bash after */ - printf("Did you notice?\n"); - free(p); + p = (int*) malloc( sizeof(int) * 10 ); + printf("Now writing before our allocated array\n"); + p[-1] ^= 0x0F; /* bash before */ + printf("... and now after our allocated array\n"); + p[10] ^= 0x0F; /* bash after */ + printf("Did you notice?\n"); + free(p); } diff --git a/test/testsuppressions.cpp b/test/testsuppressions.cpp index f9757bac0..3bf8f364e 100644 --- a/test/testsuppressions.cpp +++ b/test/testsuppressions.cpp @@ -31,8 +31,7 @@ class TestSuppressions : public TestFixture { public: - TestSuppressions() : TestFixture("TestSuppressions") { - } + TestSuppressions() : TestFixture("TestSuppressions") {} private: diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 4c7b2ef40..0a873a601 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -46,27 +46,26 @@ struct InternalError; LOAD_LIB_2(settings1.library, "std.cfg"); \ const SymbolDatabase *db = getSymbolDB_inner(tokenizer, code, "test.cpp"); \ ASSERT(db); \ - do {} while(false) + do {} while (false) #define GET_SYMBOL_DB(code) \ Tokenizer tokenizer(&settings1, this); \ const SymbolDatabase *db = getSymbolDB_inner(tokenizer, code, "test.cpp"); \ ASSERT(db); \ - do {} while(false) + do {} while (false) #define GET_SYMBOL_DB_C(code) \ Tokenizer tokenizer(&settings1, this); \ const SymbolDatabase *db = getSymbolDB_inner(tokenizer, code, "test.c"); \ - do {} while(false) + do {} while (false) -class TestSymbolDatabase: public TestFixture { +class TestSymbolDatabase : public TestFixture { public: TestSymbolDatabase() - :TestFixture("TestSymbolDatabase") + : TestFixture("TestSymbolDatabase") ,nullScope(nullptr, nullptr, nullptr) ,vartok(nullptr) - ,typetok(nullptr) { - } + ,typetok(nullptr) {} private: const Scope nullScope; @@ -3175,11 +3174,11 @@ private: ASSERT(db && !db->functionScopes.empty() && db->functionScopes.front()->function && db->functionScopes.front()->function->functionScope == db->functionScopes.front()); const Token *f = Token::findsimplematch(tokenizer.tokens(), "MyClass ( ) ;"); - ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3 && f->function()->token->linenr() == 9); + ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3 && f->function()->token->linenr() == 9); f = Token::findsimplematch(tokenizer.tokens(), "~ MyClass ( ) ;"); f = f->next(); - ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4 && f->function()->token->linenr() == 8); + ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4 && f->function()->token->linenr() == 8); } void symboldatabase49() { // #6424 @@ -4735,7 +4734,7 @@ private: "void Fred::foo(const std::vector> &callbacks) { }"); ASSERT_EQUALS("", errout.str()); const Token *functok = Token::findsimplematch(tokenizer.tokens(), - "foo ( const std :: vector < std :: function < void ( const Fred :: Value & ) > > & callbacks ) { }"); + "foo ( const std :: vector < std :: function < void ( const Fred :: Value & ) > > & callbacks ) { }"); ASSERT(functok); ASSERT(functok->function()); ASSERT(functok->function()->name() == "foo"); @@ -4752,7 +4751,7 @@ private: void symboldatabase93() { // alignas attribute GET_SYMBOL_DB("struct alignas(int) A{\n" "};\n" - ); + ); ASSERT(db != nullptr); const Scope* scope = db->findScopeByName("A"); ASSERT(scope); @@ -4986,11 +4985,11 @@ private: } #define TEST(S) \ - v = db->getVariableFromVarId(id++); \ - ASSERT(v != nullptr); \ - ASSERT(v->isArray()); \ - ASSERT_EQUALS(1U, v->dimensions().size()); \ - ASSERT_EQUALS(S, v->dimension(0)) + v = db->getVariableFromVarId(id++); \ + ASSERT(v != nullptr); \ + ASSERT(v->isArray()); \ + ASSERT_EQUALS(1U, v->dimensions().size()); \ + ASSERT_EQUALS(S, v->dimension(0)) void enum7() { GET_SYMBOL_DB("enum E { X };\n" @@ -5248,7 +5247,7 @@ private: " foo(1);\n" /* 5 */ "}"); /* 6 */ ASSERT_EQUALS("", errout.str()); - ASSERT(db) ; + ASSERT(db); const Scope * bar = db->findScopeByName("bar"); ASSERT(bar != nullptr); const unsigned int linenrs[2] = { 2, 1 }; @@ -6621,10 +6620,10 @@ private: } #define FUNC(x) do { \ - const Function *x = findFunctionByName(#x, &db->scopeList.front()); \ - ASSERT_EQUALS(true, x != nullptr); \ - ASSERT_EQUALS(true, x->isNoExcept()); \ - } while(false) + const Function *x = findFunctionByName(#x, &db->scopeList.front()); \ + ASSERT_EQUALS(true, x != nullptr); \ + ASSERT_EQUALS(true, x->isNoExcept()); \ +} while (false) void noexceptFunction1() { GET_SYMBOL_DB("void func1() noexcept;\n" @@ -6650,10 +6649,10 @@ private: } #define CLASS_FUNC(x, y, z) do { \ - const Function *x = findFunctionByName(#x, y); \ - ASSERT_EQUALS(true, x != nullptr); \ - ASSERT_EQUALS(z, x->isNoExcept()); \ - } while(false) + const Function *x = findFunctionByName(#x, y); \ + ASSERT_EQUALS(true, x != nullptr); \ + ASSERT_EQUALS(z, x->isNoExcept()); \ +} while (false) void noexceptFunction3() { GET_SYMBOL_DB("struct Fred {\n" @@ -6711,10 +6710,10 @@ private: } #define FUNC_THROW(x) do { \ - const Function *x = findFunctionByName(#x, &db->scopeList.front()); \ - ASSERT_EQUALS(true, x != nullptr); \ - ASSERT_EQUALS(true, x->isThrow()); \ - } while(false) + const Function *x = findFunctionByName(#x, &db->scopeList.front()); \ + ASSERT_EQUALS(true, x != nullptr); \ + ASSERT_EQUALS(true, x->isThrow()); \ +} while (false) void throwFunction1() { GET_SYMBOL_DB("void func1() throw();\n" @@ -6731,10 +6730,10 @@ private: } #define CLASS_FUNC_THROW(x, y) do { \ - const Function *x = findFunctionByName(#x, y); \ - ASSERT_EQUALS(true, x != nullptr); \ - ASSERT_EQUALS(true, x->isThrow()); \ - } while(false) + const Function *x = findFunctionByName(#x, y); \ + ASSERT_EQUALS(true, x != nullptr); \ + ASSERT_EQUALS(true, x->isThrow()); \ +} while (false) void throwFunction2() { GET_SYMBOL_DB("struct Fred {\n" " void func1() throw();\n" @@ -6825,7 +6824,7 @@ private: "template [[nodiscard]] int func4() { }" "std::pair [[nodiscard]] func5();\n" "[[nodiscard]] std::pair func6();\n" - ); + ); ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS(true, db != nullptr); // not null @@ -7324,7 +7323,8 @@ private: doc.Parse(xmldata, sizeof(xmldata)); \ sF.library.load(doc); \ ASSERT_EQUALS(#type, typeOf("void f() { auto x = g(); }", "x", "test.cpp", &sF)); \ - } while (false) +} while (false) + // *INDENT-OFF* CHECK_LIBRARY_FUNCTION_RETURN_TYPE(bool); CHECK_LIBRARY_FUNCTION_RETURN_TYPE(signed char); CHECK_LIBRARY_FUNCTION_RETURN_TYPE(unsigned char); @@ -7339,6 +7339,7 @@ private: CHECK_LIBRARY_FUNCTION_RETURN_TYPE(void *); CHECK_LIBRARY_FUNCTION_RETURN_TYPE(void * *); CHECK_LIBRARY_FUNCTION_RETURN_TYPE(const void *); + // *INDENT-ON* #undef CHECK_LIBRARY_FUNCTION_RETURN_TYPE // Library types diff --git a/test/testthreadexecutor.cpp b/test/testthreadexecutor.cpp index 480fafeca..164cb605b 100644 --- a/test/testthreadexecutor.cpp +++ b/test/testthreadexecutor.cpp @@ -26,8 +26,7 @@ class TestThreadExecutor : public TestFixture { public: - TestThreadExecutor() : TestFixture("TestThreadExecutor") { - } + TestThreadExecutor() : TestFixture("TestThreadExecutor") {} private: Settings settings; diff --git a/test/testtimer.cpp b/test/testtimer.cpp index eb02990d0..3ef6b5400 100644 --- a/test/testtimer.cpp +++ b/test/testtimer.cpp @@ -24,8 +24,7 @@ class TestTimer : public TestFixture { public: - TestTimer() : TestFixture("TestTimer") { - } + TestTimer() : TestFixture("TestTimer") {} private: diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 14921b418..35a236ddf 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -31,8 +31,7 @@ struct InternalError; class TestToken : public TestFixture { public: - TestToken() : TestFixture("TestToken") { - } + TestToken() : TestFixture("TestToken") {} private: std::vector arithmeticalOps; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 73a475da1..224780225 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -35,8 +35,7 @@ struct InternalError; class TestTokenizer : public TestFixture { public: - TestTokenizer() : TestFixture("TestTokenizer") { - } + TestTokenizer() : TestFixture("TestTokenizer") {} private: Settings settings0; @@ -687,7 +686,7 @@ private: "};\n" "struct S { S(); };\n" "S::S() __attribute((pure)) = default;" - ); + ); // original code: glibc-2.18/posix/bug-regex20.c tokenizeAndStringify("static unsigned int re_string_context_at (const re_string_t *input, int idx, int eflags) internal_function __attribute__ ((pure));"); @@ -734,12 +733,12 @@ private: "};\n" "Container::Container() : mElements(nullptr) {}\n" "Container intContainer;"; - const char exp [] = "1: struct Container {\n" - "2: Container ( ) ;\n" - "3: int * mElements@1 ;\n" - "4: } ;\n" - "5: Container :: Container ( ) : mElements@1 ( nullptr ) { }\n" - "6: Container intContainer@2 ;\n"; + const char exp[] = "1: struct Container {\n" + "2: Container ( ) ;\n" + "3: int * mElements@1 ;\n" + "4: } ;\n" + "5: Container :: Container ( ) : mElements@1 ( nullptr ) { }\n" + "6: Container intContainer@2 ;\n"; ASSERT_EQUALS(exp, tokenizeDebugListing(code)); } { @@ -749,16 +748,16 @@ private: "};\n" "template Container::Container() : mElements(nullptr) {}\n" "Container intContainer;"; - const char exp [] = "1: struct Container ;\n" - "2:\n" - "|\n" - "5:\n" - "6: Container intContainer@1 ;\n" - "1: struct Container {\n" - "2: Container ( ) ;\n" - "3: int * mElements@2 ;\n" - "4: } ;\n" - "5: Container :: Container ( ) : mElements@2 ( nullptr ) { }\n"; + const char exp[] = "1: struct Container ;\n" + "2:\n" + "|\n" + "5:\n" + "6: Container intContainer@1 ;\n" + "1: struct Container {\n" + "2: Container ( ) ;\n" + "3: int * mElements@2 ;\n" + "4: } ;\n" + "5: Container :: Container ( ) : mElements@2 ( nullptr ) { }\n"; ASSERT_EQUALS(exp, tokenizeDebugListing(code)); } } @@ -777,14 +776,14 @@ private: const char codeC[] = "class name { public: static void init ( ) {} } ; " "typedef class name N; " "void foo ( ) { return N :: init ( ) ; }"; - const char expC [] = "class name { public: static void init ( ) { } } ; " - "void foo ( ) { return name :: init ( ) ; }"; + const char expC[] = "class name { public: static void init ( ) { } } ; " + "void foo ( ) { return name :: init ( ) ; }"; ASSERT_EQUALS(expC, tokenizeAndStringify(codeC)); const char codeS[] = "class name { public: static void init ( ) {} } ; " "typedef struct name N; " "void foo ( ) { return N :: init ( ) ; }"; - const char expS [] = "class name { public: static void init ( ) { } } ; " - "void foo ( ) { return name :: init ( ) ; }"; + const char expS[] = "class name { public: static void init ( ) { } } ; " + "void foo ( ) { return name :: init ( ) ; }"; ASSERT_EQUALS(expS, tokenizeAndStringify(codeS)); } @@ -993,17 +992,17 @@ private: "5:\n" "6: ;\n" "} ;", tokenizeAndStringify("int f0(Args args) {\n" - " return ^{\n" - " return sizeof...(Args);\n" - " }() + ^ {\n" - " return sizeof...(args);\n" - " }();\n" - "};")), InternalError); + " return ^{\n" + " return sizeof...(Args);\n" + " }() + ^ {\n" + " return sizeof...(args);\n" + " }();\n" + "};")), InternalError); ASSERT_THROW(ASSERT_EQUALS("int ( ^ block ) ( void ) = asm ( \"^{staticinttest=0;returntest;}\" )\n\n\n;", tokenizeAndStringify("int(^block)(void) = ^{\n" - " static int test = 0;\n" - " return test;\n" - "};")), InternalError); + " static int test = 0;\n" + " return test;\n" + "};")), InternalError); ASSERT_THROW(ASSERT_EQUALS("; return f ( a [ b = c ] , asm ( \"^{}\" ) ) ;", tokenizeAndStringify("; return f(a[b=c],^{});")), InternalError); // #7185 @@ -1382,13 +1381,13 @@ private: " return 0 ;\n" "}\n"; const char result[] = "void foo ( int c , int d ) {\n" - "do {\n" - "if ( c ) {\n" - "while ( c ) { c -- ; }\n" - "} }\n" - "while ( -- d > 0 ) ;\n" - "return 0 ;\n" - "}"; + "do {\n" + "if ( c ) {\n" + "while ( c ) { c -- ; }\n" + "} }\n" + "while ( -- d > 0 ) ;\n" + "return 0 ;\n" + "}"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } @@ -1400,11 +1399,11 @@ private: " return 0 ;\n" "}\n"; const char result[] = "void foo ( int c , int d ) {\n" - "do {\n" - "do { c -- ; } while ( c ) ; }\n" - "while ( -- d > 0 ) ;\n" - "return 0 ;\n" - "}"; + "do {\n" + "do { c -- ; } while ( c ) ; }\n" + "while ( -- d > 0 ) ;\n" + "return 0 ;\n" + "}"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } @@ -1842,11 +1841,11 @@ private: "char &(b); " "const static char *(c); " "} ;"; - static char exp[] = "struct S { " - "char * a ; " - "char & b ; " - "static const char * c ; " - "} ;"; + static char exp[] = "struct S { " + "char * a ; " + "char & b ; " + "static const char * c ; " + "} ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } @@ -1854,48 +1853,48 @@ private: // Reported case { static char code[] = "; * * p f ( ) int = { new int ( * [ 2 ] ) ; void }"; - static char exp[] = "; * * p f ( ) int = { new int ( * [ 2 ] ) ; void }"; + static char exp[] = "; * * p f ( ) int = { new int ( * [ 2 ] ) ; void }"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } // Various valid cases { static char code[] = "int * f [ 1 ] = { new ( int ) } ;"; - static char exp[] = "int * f [ 1 ] = { new int } ;"; + static char exp[] = "int * f [ 1 ] = { new int } ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } { static char code[] = "int * * f [ 1 ] = { new ( int ) [ 1 ] } ;"; - static char exp[] = "int * * f [ 1 ] = { new int [ 1 ] } ;"; + static char exp[] = "int * * f [ 1 ] = { new int [ 1 ] } ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } { static char code[] = "list < int > * f [ 1 ] = { new ( list < int > ) } ;"; - static char exp[] = "list < int > * f [ 1 ] = { new list < int > } ;"; + static char exp[] = "list < int > * f [ 1 ] = { new list < int > } ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } // don't remove parentheses in operator new overload { static char code[] = "void *operator new(__SIZE_TYPE__, int);"; - static char exp[] = "void * operatornew ( __SIZE_TYPE__ , int ) ;"; + static char exp[] = "void * operatornew ( __SIZE_TYPE__ , int ) ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } } void removeParentheses24() { // Ticket #7040 static char code[] = "std::hash()(t._data);"; - static char exp[] = "std :: hash < decltype ( t . _data ) > ( ) ( t . _data ) ;"; + static char exp[] = "std :: hash < decltype ( t . _data ) > ( ) ( t . _data ) ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } void removeParentheses25() { // daca@home - a=(b,c) static char code[] = "a=(b,c);"; - static char exp[] = "a = ( b , c ) ;"; + static char exp[] = "a = ( b , c ) ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } void removeParentheses26() { // Ticket #8875 a[0](0) static char code[] = "a[0](0);"; - static char exp[] = "a [ 0 ] ( 0 ) ;"; + static char exp[] = "a [ 0 ] ( 0 ) ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } @@ -1918,13 +1917,13 @@ private: void tokenize_strings() { const char code[] = "void f() {\n" - "const char *a =\n" - "{\n" - "\"hello \"\n" - "\"more \"\n" - "\"world\"\n" - "};\n" - "}"; + "const char *a =\n" + "{\n" + "\"hello \"\n" + "\"more \"\n" + "\"world\"\n" + "};\n" + "}"; ASSERT_EQUALS("void f ( ) {\n" "const char * a ; a =\n" "{\n" @@ -2474,7 +2473,7 @@ private: " return 0;\n" " return 0;\n" "}"; - tokenizeAndStringify(code, /*expand=*/true, Settings::Native, "test.c"); + tokenizeAndStringify(code, /*expand=*/ true, Settings::Native, "test.c"); } void vardecl28() { @@ -2486,7 +2485,7 @@ private: "const unsigned short x ; x = 1 ;\n" "return x ;\n" "}", - tokenizeAndStringify(code, /*expand=*/true, Settings::Native, "test.c")); + tokenizeAndStringify(code, /*expand=*/ true, Settings::Native, "test.c")); } void volatile_variables() { @@ -2506,18 +2505,18 @@ private: ASSERT_EQUALS("void f ( int a [ 5 ] ) ;", tokenizeAndStringify(code)); } { - const char in4 [] = "struct B final : A { void foo(); };"; - const char out4 [] = "struct B : A { void foo ( ) ; } ;"; + const char in4[] = "struct B final : A { void foo(); };"; + const char out4[] = "struct B : A { void foo ( ) ; } ;"; ASSERT_EQUALS(out4, tokenizeAndStringify(in4)); - const char in5 [] = "struct ArrayItemsValidator final {\n" - " SchemaError validate() const override {\n" - " for (; pos < value.size(); ++pos) {\n" - " }\n" - " return none;\n" - " }\n" - "};\n"; - const char out5 [] = + const char in5[] = "struct ArrayItemsValidator final {\n" + " SchemaError validate() const override {\n" + " for (; pos < value.size(); ++pos) {\n" + " }\n" + " return none;\n" + " }\n" + "};\n"; + const char out5[] = "struct ArrayItemsValidator {\n" "SchemaError validate ( ) const override {\n" "for ( ; pos < value . size ( ) ; ++ pos ) {\n" @@ -4520,25 +4519,25 @@ private: " } " "}"; - const char result1 [] = "class Counter : public QObject " - "{ " - "public: " - "Counter ( ) { m_value = 0 ; } " - "int value ( ) const { return m_value ; } " - "public: " - "void setValue ( int value ) ; " - "protected: " - "void valueChanged ( int newValue ) ; " - "private: " - "int m_value ; " - "} ; " - "void Counter :: setValue ( int value ) " - "{ " - "if ( value != m_value ) { " - "m_value = value ; " - "valueChanged ( value ) ; " - "} " - "}"; + const char result1[] = "class Counter : public QObject " + "{ " + "public: " + "Counter ( ) { m_value = 0 ; } " + "int value ( ) const { return m_value ; } " + "public: " + "void setValue ( int value ) ; " + "protected: " + "void valueChanged ( int newValue ) ; " + "private: " + "int m_value ; " + "} ; " + "void Counter :: setValue ( int value ) " + "{ " + "if ( value != m_value ) { " + "m_value = value ; " + "valueChanged ( value ) ; " + "} " + "}"; ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); @@ -4563,25 +4562,25 @@ private: " } " "}"; - const char result2 [] = "class Counter : public QObject " - "{ " - "public: " - "Counter ( ) { m_value = 0 ; } " - "int value ( ) const { return m_value ; } " - "public: " - "void setValue ( int value ) ; " - "protected: " - "void valueChanged ( int newValue ) ; " - "private: " - "int m_value ; " - "} ; " - "void Counter :: setValue ( int value ) " - "{ " - "if ( value != m_value ) { " - "m_value = value ; " - "valueChanged ( value ) ; " - "} " - "}"; + const char result2[] = "class Counter : public QObject " + "{ " + "public: " + "Counter ( ) { m_value = 0 ; } " + "int value ( ) const { return m_value ; } " + "public: " + "void setValue ( int value ) ; " + "protected: " + "void valueChanged ( int newValue ) ; " + "private: " + "int m_value ; " + "} ; " + "void Counter :: setValue ( int value ) " + "{ " + "if ( value != m_value ) { " + "m_value = value ; " + "valueChanged ( value ) ; " + "} " + "}"; ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); @@ -4592,13 +4591,13 @@ private: " signals:" " void test() {}" "};"; - const char result3 [] = "class MyObject : public QObject { " - "MyObject ( ) { } " - "~ MyObject ( ) { } " - "public: " - "protected: " - "void test ( ) { } " - "} ;"; + const char result3[] = "class MyObject : public QObject { " + "MyObject ( ) { } " + "~ MyObject ( ) { } " + "public: " + "protected: " + "void test ( ) { } " + "} ;"; ASSERT_EQUALS(result3, tokenizeAndStringify(code3)); ASSERT_EQUALS("", errout.str()); @@ -4704,13 +4703,13 @@ private: " operator();" "}"; - const char result [] = "void operator ( ) { } " - "int main ( ) " - "{ " - "operator ( ) ; " - "}"; + const char result[] = "void operator ( ) { } " + "int main ( ) " + "{ " + "operator ( ) ; " + "}"; - ASSERT_EQUALS(result, tokenizeAndStringify(code, /*expand=*/true, /*platform=*/Settings::Native, "test.c")); + ASSERT_EQUALS(result, tokenizeAndStringify(code, /*expand=*/ true, /*platform=*/ Settings::Native, "test.c")); } void simplifyOperatorName2() { @@ -4720,11 +4719,11 @@ private: " operator = ();" "}"; - const char result [] = "class Fred " - "{ " - "Fred ( const Fred & f ) { operator= ( f ) ; } " - "operator= ( ) ; " - "}"; + const char result[] = "class Fred " + "{ " + "Fred ( const Fred & f ) { operator= ( f ) ; } " + "operator= ( ) ; " + "}"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } @@ -5951,7 +5950,7 @@ private: ASSERT_EQUALS("pf.pf.12,(&&", testAst("((p.f) && (p.f)(1,2))")); - ASSERT_EQUALS("forresdirGetFirst.file&_T(,(=;;(", testAst("for ((res = dir.GetFirst(&file, _T("")));;) {}")); + ASSERT_EQUALS("forresdirGetFirst.file&_T(,(=;;(", testAst("for ((res = dir.GetFirst(&file, _T(" ")));;) {}")); // problems with: if (x[y]==z) ASSERT_EQUALS("ifa(0[1==(", testAst("if(a()[0]==1){}")); @@ -6789,7 +6788,7 @@ private: void noCrash1() { ASSERT_NO_THROW(tokenizeAndStringify( "struct A {\n" - " A( const std::string &name = "" );\n" + " A( const std::string &name = " " );\n" "};\n" "A::A( const std::string &name ) { return; }\n")); } diff --git a/test/testtokenlist.cpp b/test/testtokenlist.cpp index aad5ffa6e..154571126 100644 --- a/test/testtokenlist.cpp +++ b/test/testtokenlist.cpp @@ -25,8 +25,7 @@ class TestTokenList : public TestFixture { public: - TestTokenList() : TestFixture("TestTokenList") { - } + TestTokenList() : TestFixture("TestTokenList") {} private: Settings settings; diff --git a/test/testtokenrange.cpp b/test/testtokenrange.cpp index b33727aeb..9c5f0d5e7 100644 --- a/test/testtokenrange.cpp +++ b/test/testtokenrange.cpp @@ -33,8 +33,7 @@ struct InternalError; class TestTokenRange : public TestFixture { public: - TestTokenRange() : TestFixture("TestTokenRange") { - } + TestTokenRange() : TestFixture("TestTokenRange") {} private: void run() OVERRIDE { diff --git a/test/testtype.cpp b/test/testtype.cpp index 688ac2761..f80ec8a8a 100644 --- a/test/testtype.cpp +++ b/test/testtype.cpp @@ -26,8 +26,7 @@ class TestType : public TestFixture { public: - TestType() : TestFixture("TestType") { - } + TestType() : TestFixture("TestType") {} private: @@ -70,7 +69,7 @@ private: // unsigned types getting promoted to int sizeof(int) = 4 bytes // and unsigned types having already a size of 4 bytes { - const std::string types[] = {"unsigned char", /*[unsigned]*/"char", "bool", "unsigned short", "unsigned int", "unsigned long"}; + const std::string types[] = {"unsigned char", /*[unsigned]*/ "char", "bool", "unsigned short", "unsigned int", "unsigned long"}; for (const std::string& type : types) { check((type + " f(" + type +" x) { return x << 31; }").c_str(), &settings); ASSERT_EQUALS("", errout.str()); @@ -85,7 +84,7 @@ private: // signed types getting promoted to int sizeof(int) = 4 bytes // and signed types having already a size of 4 bytes { - const std::string types[] = {"signed char", "signed short", /*[signed]*/"short", "wchar_t", /*[signed]*/"int", "signed int", /*[signed]*/"long", "signed long"}; + const std::string types[] = {"signed char", "signed short", /*[signed]*/ "short", "wchar_t", /*[signed]*/ "int", "signed int", /*[signed]*/ "long", "signed long"}; for (const std::string& type : types) { // c++11 check((type + " f(" + type +" x) { return x << 33; }").c_str(), &settings); diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 0f2fa729b..b93add16f 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -30,8 +30,7 @@ struct InternalError; class TestUninitVar : public TestFixture { public: - TestUninitVar() : TestFixture("TestUninitVar") { - } + TestUninitVar() : TestFixture("TestUninitVar") {} private: Settings settings; diff --git a/test/testunusedfunctions.cpp b/test/testunusedfunctions.cpp index 88a9d8d9a..ac36f1fa8 100644 --- a/test/testunusedfunctions.cpp +++ b/test/testunusedfunctions.cpp @@ -26,8 +26,7 @@ class TestUnusedFunctions : public TestFixture { public: - TestUnusedFunctions() : TestFixture("TestUnusedFunctions") { - } + TestUnusedFunctions() : TestFixture("TestUnusedFunctions") {} private: Settings settings; diff --git a/test/testunusedprivfunc.cpp b/test/testunusedprivfunc.cpp index 4819fe12c..24f849e29 100644 --- a/test/testunusedprivfunc.cpp +++ b/test/testunusedprivfunc.cpp @@ -28,8 +28,7 @@ class TestUnusedPrivateFunction : public TestFixture { public: - TestUnusedPrivateFunction() : TestFixture("TestUnusedPrivateFunction") { - } + TestUnusedPrivateFunction() : TestFixture("TestUnusedPrivateFunction") {} private: Settings settings; @@ -663,7 +662,7 @@ private: "{" " MountOperation aExample(10);" "}" - ); + ); ASSERT_EQUALS("", errout.str()); } @@ -690,7 +689,7 @@ private: "{" " MountOperation aExample(10);" "}" - ); + ); ASSERT_EQUALS("", errout.str()); } @@ -717,7 +716,7 @@ private: "{" " MountOperation aExample(10);" "}" - ); + ); ASSERT_EQUALS("", errout.str()); } diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 8bf7d5bab..787770ca9 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -26,8 +26,7 @@ class TestUnusedVar : public TestFixture { public: - TestUnusedVar() : TestFixture("TestUnusedVar") { - } + TestUnusedVar() : TestFixture("TestUnusedVar") {} private: Settings settings; @@ -5732,7 +5731,7 @@ private: "void fun(short data[2]) {\n" " data[2] = 1;\n" "}" - ); + ); ASSERT_EQUALS("", errout.str()); // Unknown argument type @@ -5740,7 +5739,7 @@ private: "void A::b(Date& result) {" " result = 12;\n" "}" - ); + ); ASSERT_EQUALS("", errout.str()); { @@ -5749,7 +5748,7 @@ private: "void fun(Date result) {" " result.x = 12;\n" "}" - ); + ); ASSERT_EQUALS("", errout.str()); functionVariableUsage( // there is no reference type in C @@ -5757,7 +5756,7 @@ private: " result.x = 12;\n" "}", "test.c" - ); + ); ASSERT_EQUALS("[test.c:1]: (style) Variable 'result.x' is assigned a value that is never used.\n", errout.str()); functionVariableUsage( @@ -5765,7 +5764,7 @@ private: "void fun(Date result) {" " result.x = 12;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'result.x' is assigned a value that is never used.\n", errout.str()); } @@ -5775,7 +5774,7 @@ private: " struct FOO foo;\n" " foo.x = 123;\n" "}" - ); + ); ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'foo.x' is assigned a value that is never used.\n", errout.str()); } diff --git a/test/testutils.cpp b/test/testutils.cpp index 1782a1cdd..d8bfe445f 100644 --- a/test/testutils.cpp +++ b/test/testutils.cpp @@ -24,8 +24,7 @@ const Settings givenACodeSampleToTokenize::settings; class TestUtils : public TestFixture { public: - TestUtils() : TestFixture("TestUtils") { - } + TestUtils() : TestFixture("TestUtils") {} private: void run() OVERRIDE { diff --git a/test/testutils.h b/test/testutils.h index 7202bf185..902ae6c11 100644 --- a/test/testutils.h +++ b/test/testutils.h @@ -50,8 +50,7 @@ public: class SimpleSuppressor : public ErrorLogger { public: SimpleSuppressor(Settings &settings, ErrorLogger *next) - : settings(settings), next(next) { - } + : settings(settings), next(next) {} void reportOut(const std::string &outmsg, Color = Color::Reset) OVERRIDE { next->reportOut(outmsg); } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index f0a8f3a28..1ce2bf932 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -38,8 +38,7 @@ class TestValueFlow : public TestFixture { public: - TestValueFlow() : TestFixture("TestValueFlow") { - } + TestValueFlow() : TestFixture("TestValueFlow") {} private: Settings settings; @@ -47,10 +46,10 @@ private: void run() OVERRIDE { // strcpy, abort cfg const char cfg[] = "\n" - "\n" - " \n" - " true \n" // abort is a noreturn function - ""; + "\n" + " \n" + " true \n" // abort is a noreturn function + ""; settings.library.loadxmldata(cfg, sizeof(cfg)); LOAD_LIB_2(settings.library, "std.cfg"); @@ -970,14 +969,14 @@ private: ASSERT_EQUALS(4, values.back().intvalue); #define CHECK3(A, B, C) \ - do { \ + do { \ code = "void f() {\n" \ " x = sizeof(" A ");\n" \ "}"; \ values = tokenValues(code,"( " C " )"); \ ASSERT_EQUALS(1U, values.size()); \ - ASSERT_EQUALS(B, values.back().intvalue);\ - } while(false) + ASSERT_EQUALS(B, values.back().intvalue); \ + } while (false) #define CHECK(A, B) CHECK3(A, B, A) // standard types @@ -1017,7 +1016,7 @@ private: ASSERT_EQUALS(10, values.back().intvalue); #define CHECK(A, B, C, D) \ - do { \ + do { \ code = "enum " A " E " B " { E0, E1 };\n" \ "void f() {\n" \ " x = sizeof(" C ");\n" \ @@ -1025,7 +1024,7 @@ private: values = tokenValues(code,"( " C " )"); \ ASSERT_EQUALS(1U, values.size()); \ ASSERT_EQUALS(D, values.back().intvalue); \ - } while(false) + } while (false) // enums CHECK("", "", "E", settings.sizeof_int); @@ -1092,7 +1091,7 @@ private: #undef CHECK #define CHECK(A, B) \ - do { \ + do { \ code = "enum E " A " { E0, E1 };\n" \ "void f() {\n" \ " E arrE[] = { E0, E1 };\n" \ @@ -1100,8 +1099,8 @@ private: "}"; \ values = tokenValues(code,"( arrE )"); \ ASSERT_EQUALS(1U, values.size()); \ - ASSERT_EQUALS(B * 2U, values.back().intvalue);\ - } while(false) + ASSERT_EQUALS(B * 2U, values.back().intvalue); \ + } while (false) // enum array CHECK("", settings.sizeof_int); @@ -1127,7 +1126,7 @@ private: #undef CHECK #define CHECK(A, B) \ - do { \ + do { \ code = "enum class E " A " { E0, E1 };\n" \ "void f() {\n" \ " E arrE[] = { E::E0, E::E1 };\n" \ @@ -1135,8 +1134,8 @@ private: "}"; \ values = tokenValues(code,"( arrE )"); \ ASSERT_EQUALS(1U, values.size()); \ - ASSERT_EQUALS(B * 2U, values.back().intvalue);\ - } while(false) + ASSERT_EQUALS(B * 2U, values.back().intvalue); \ + } while (false) // enum array CHECK("", settings.sizeof_int); @@ -2444,20 +2443,20 @@ private: ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); code = "void f(int x) {\n" - " if (x != 123) { throw ""; }\n" + " if (x != 123) { throw " "; }\n" " a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); code = "void f(int x) {\n" " if (x != 123) { }\n" - " else { throw ""; }\n" + " else { throw " "; }\n" " a = x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 123)); code = "void f(int x) {\n" " if (x == 123) { }\n" - " else { throw ""; }\n" + " else { throw " "; }\n" " a = x;\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 123)); @@ -4714,8 +4713,8 @@ private: } static std::string isPossibleContainerSizeValue(std::list values, - MathLib::bigint i, - bool unique = true) { + MathLib::bigint i, + bool unique = true) { values.remove_if(std::mem_fn(&ValueFlow::Value::isSymbolicValue)); if (!unique) values.remove_if(&isNotPossible); @@ -4731,8 +4730,8 @@ private: } static std::string isImpossibleContainerSizeValue(std::list values, - MathLib::bigint i, - bool unique = true) { + MathLib::bigint i, + bool unique = true) { values.remove_if(std::mem_fn(&ValueFlow::Value::isSymbolicValue)); if (!unique) values.remove_if(&isNotImpossible); @@ -4748,8 +4747,8 @@ private: } static std::string isInconclusiveContainerSizeValue(std::list values, - MathLib::bigint i, - bool unique = true) { + MathLib::bigint i, + bool unique = true) { values.remove_if(std::mem_fn(&ValueFlow::Value::isSymbolicValue)); if (!unique) values.remove_if(&isNotInconclusive); @@ -5828,7 +5827,7 @@ private: " }\n" "\n" " return 0;\n" - "}" ; + "}"; ASSERT_EQUALS(false, testValueOfXKnown(code, 4U, 1)); } diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 97e4c46ac..27674402f 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -30,8 +30,7 @@ struct InternalError; class TestVarID : public TestFixture { public: - TestVarID() : TestFixture("TestVarID") { - } + TestVarID() : TestFixture("TestVarID") {} private: void run() OVERRIDE { @@ -287,14 +286,14 @@ private: void varid1() { { const std::string actual = tokenize( - "static int i = 1;\n" - "void f()\n" - "{\n" - " int i = 2;\n" - " for (int i = 0; i < 10; ++i)\n" - " i = 3;\n" - " i = 4;\n" - "}\n", "test.c"); + "static int i = 1;\n" + "void f()\n" + "{\n" + " int i = 2;\n" + " for (int i = 0; i < 10; ++i)\n" + " i = 3;\n" + " i = 4;\n" + "}\n", "test.c"); const char expected[] = "1: static int i@1 = 1 ;\n" "2: void f ( )\n" @@ -310,16 +309,16 @@ private: { const std::string actual = tokenize( - "static int i = 1;\n" - "void f()\n" - "{\n" - " int i = 2;\n" - " for (int i = 0; i < 10; ++i)\n" - " {\n" - " i = 3;\n" - " }\n" - " i = 4;\n" - "}\n", "test.c"); + "static int i = 1;\n" + "void f()\n" + "{\n" + " int i = 2;\n" + " for (int i = 0; i < 10; ++i)\n" + " {\n" + " i = 3;\n" + " }\n" + " i = 4;\n" + "}\n", "test.c"); const char expected[] = "1: static int i@1 = 1 ;\n" "2: void f ( )\n" @@ -338,12 +337,12 @@ private: void varid2() { const std::string actual = tokenize( - "void f()\n" - "{\n" - " struct ABC abc;\n" - " abc.a = 3;\n" - " i = abc.a;\n" - "}\n", "test.c"); + "void f()\n" + "{\n" + " struct ABC abc;\n" + " abc.a = 3;\n" + " i = abc.a;\n" + "}\n", "test.c"); const char expected[] = "1: void f ( )\n" "2: {\n" @@ -357,12 +356,12 @@ private: void varid3() { const std::string actual = tokenize( - "static char str[4];\n" - "void f()\n" - "{\n" - " char str[10];\n" - " str[0] = 0;\n" - "}\n", "test.c"); + "static char str[4];\n" + "void f()\n" + "{\n" + " char str[10];\n" + " str[0] = 0;\n" + "}\n", "test.c"); const char expected[] = "1: static char str@1 [ 4 ] ;\n" "2: void f ( )\n" @@ -376,10 +375,10 @@ private: void varid4() { const std::string actual = tokenize( - "void f(const unsigned int a[])\n" - "{\n" - " int i = *(a+10);\n" - "}\n", "test.c"); + "void f(const unsigned int a[])\n" + "{\n" + " int i = *(a+10);\n" + "}\n", "test.c"); const char expected[] = "1: void f ( const unsigned int a@1 [ ] )\n" "2: {\n" @@ -391,10 +390,10 @@ private: void varid5() { const std::string actual = tokenize( - "void f()\n" - "{\n" - " int a,b;\n" - "}\n", "test.c"); + "void f()\n" + "{\n" + " int a,b;\n" + "}\n", "test.c"); const char expected[] = "1: void f ( )\n" "2: {\n" @@ -407,10 +406,10 @@ private: void varid6() { const std::string actual = tokenize( - "int f(int a, int b)\n" - "{\n" - " return a+b;\n" - "}\n", "test.c"); + "int f(int a, int b)\n" + "{\n" + " return a+b;\n" + "}\n", "test.c"); const char expected[] = "1: int f ( int a@1 , int b@2 )\n" "2: {\n" @@ -423,12 +422,12 @@ private: void varid7() { const std::string actual = tokenize( - "void func() {\n" - " char a[256] = \"test\";\n" - " {\n" - " char b[256] = \"test\";\n" - " }\n" - "}\n", "test.c"); + "void func() {\n" + " char a[256] = \"test\";\n" + " {\n" + " char b[256] = \"test\";\n" + " }\n" + "}\n", "test.c"); const char expected[] = "1: void func ( ) {\n" "2: char a@1 [ 256 ] = \"test\" ;\n" @@ -442,11 +441,11 @@ private: void varidReturn1() { const std::string actual = tokenize( - "int f()\n" - "{\n" - " int a;\n" - " return a;\n" - "}\n", "test.c"); + "int f()\n" + "{\n" + " int a;\n" + " return a;\n" + "}\n", "test.c"); const char expected[] = "1: int f ( )\n" "2: {\n" @@ -459,11 +458,11 @@ private: void varidReturn2() { const std::string actual = tokenize( - "void foo()\n" - "{\n" - " unsigned long mask = (1UL << size_) - 1;\n" - " return (abits_val_ & mask);\n" - "}\n", "test.c"); + "void foo()\n" + "{\n" + " unsigned long mask = (1UL << size_) - 1;\n" + " return (abits_val_ & mask);\n" + "}\n", "test.c"); const char expected[] = "1: void foo ( )\n" "2: {\n" @@ -476,11 +475,11 @@ private: void varid8() { const std::string actual = tokenize( - "void func()\n" - "{\n" - " std::string str(\"test\");\n" - " str.clear();\n" - "}"); + "void func()\n" + "{\n" + " std::string str(\"test\");\n" + " str.clear();\n" + "}"); const char expected[] = "1: void func ( )\n" "2: {\n" @@ -493,7 +492,7 @@ private: void varid9() { const std::string actual = tokenize( - "typedef int INT32;\n", "test.c"); + "typedef int INT32;\n", "test.c"); const char expected[] = "1: ;\n"; @@ -502,11 +501,11 @@ private: void varid10() { const std::string actual = tokenize( - "void foo()\n" - "{\n" - " int abc;\n" - " struct abc abc1;\n" - "}", "test.c"); + "void foo()\n" + "{\n" + " int abc;\n" + " struct abc abc1;\n" + "}", "test.c"); const char expected[] = "1: void foo ( )\n" "2: {\n" @@ -527,10 +526,10 @@ private: void varid12() { const std::string actual = tokenize( - "static void a()\n" - "{\n" - " class Foo *foo;\n" - "}"); + "static void a()\n" + "{\n" + " class Foo *foo;\n" + "}"); const char expected[] = "1: static void a ( )\n" "2: {\n" @@ -542,11 +541,11 @@ private: void varid13() { const std::string actual = tokenize( - "void f()\n" - "{\n" - " int a; int b;\n" - " a = a;\n" - "}\n", "test.c"); + "void f()\n" + "{\n" + " int a; int b;\n" + " a = a;\n" + "}\n", "test.c"); const char expected[] = "1: void f ( )\n" "2: {\n" @@ -560,12 +559,12 @@ private: void varid14() { // Overloaded operator* const std::string actual = tokenize( - "void foo()\n" - "{\n" - "A a;\n" - "B b;\n" - "b * a;\n" - "}", "test.c"); + "void foo()\n" + "{\n" + "A a;\n" + "B b;\n" + "b * a;\n" + "}", "test.c"); const char expected[] = "1: void foo ( )\n" "2: {\n" @@ -580,10 +579,10 @@ private: void varid15() { { const std::string actual = tokenize( - "struct S {\n" - " struct T {\n" - " } t;\n" - "} s;", "test.c"); + "struct S {\n" + " struct T {\n" + " } t;\n" + "} s;", "test.c"); const char expected[] = "1: struct S {\n" "2: struct T {\n" @@ -595,10 +594,10 @@ private: { const std::string actual = tokenize( - "struct S {\n" - " struct T {\n" - " } t;\n" - "};", "test.c"); + "struct S {\n" + " struct T {\n" + " } t;\n" + "};", "test.c"); const char expected[] = "1: struct S {\n" "2: struct T {\n" @@ -611,10 +610,10 @@ private: void varid16() { const char code[] ="void foo()\n" - "{\n" - " int x = 1;\n" - " y = (z * x);\n" - "}\n"; + "{\n" + " int x = 1;\n" + " y = (z * x);\n" + "}\n"; const char expected[] = "1: void foo ( )\n" "2: {\n" @@ -627,10 +626,10 @@ private: void varid17() { // ticket #1810 const char code[] ="char foo()\n" - "{\n" - " char c('c');\n" - " return c;\n" - "}\n"; + "{\n" + " char c('c');\n" + " return c;\n" + "}\n"; const char expected[] = "1: char foo ( )\n" "2: {\n" @@ -643,9 +642,9 @@ private: void varid18() { const char code[] ="char foo(char c)\n" - "{\n" - " bar::c = c;\n" - "}\n"; + "{\n" + " bar::c = c;\n" + "}\n"; const char expected[] = "1: char foo ( char c@1 )\n" "2: {\n" @@ -657,9 +656,9 @@ private: void varid19() { const char code[] ="void foo()\n" - "{\n" - " std::pair, int> x;\n" - "}\n"; + "{\n" + " std::pair, int> x;\n" + "}\n"; const char expected[] = "1: void foo ( )\n" "2: {\n" @@ -671,9 +670,9 @@ private: void varid20() { const char code[] ="void foo()\n" - "{\n" - " pair, vector > x;\n" - "}\n"; + "{\n" + " pair, vector > x;\n" + "}\n"; const char expected[] = "1: void foo ( )\n" "2: {\n" @@ -685,12 +684,12 @@ private: void varid24() { const char code[] ="class foo()\n" - "{\n" - "public:\n" - " ;\n" - "private:\n" - " static int i;\n" - "};\n"; + "{\n" + "public:\n" + " ;\n" + "private:\n" + " static int i;\n" + "};\n"; const char expected[] = "1: class foo ( )\n" "2: {\n" @@ -705,12 +704,12 @@ private: void varid25() { const char code[] ="class foo()\n" - "{\n" - "public:\n" - " ;\n" - "private:\n" - " mutable int i;\n" - "};\n"; + "{\n" + "public:\n" + " ;\n" + "private:\n" + " mutable int i;\n" + "};\n"; const char expected[] = "1: class foo ( )\n" "2: {\n" @@ -731,7 +730,7 @@ private: void varid27() { const char code[] ="int fooled_ya;\n" - "fooled_ya::iterator iter;\n"; + "fooled_ya::iterator iter;\n"; const char expected[] = "1: int fooled_ya@1 ;\n" "2: fooled_ya :: iterator iter@2 ;\n"; ASSERT_EQUALS(expected, tokenize(code)); @@ -743,8 +742,8 @@ private: void varid29() { const char code[] ="class A {\n" - " B,1> b;\n" - "};\n"; + " B,1> b;\n" + "};\n"; const char expected[] = "1: class A {\n" "2: B < C < 1 > , 1 > b@1 ;\n" "3: } ;\n"; @@ -791,12 +790,12 @@ private: void varid34() { // ticket #2825 const char code[] ="class Fred : public B1, public B2\n" - "{\n" - "public:\n" - " Fred() { a = 0; }\n" - "private:\n" - " int a;\n" - "};\n"; + "{\n" + "public:\n" + " Fred() { a = 0; }\n" + "private:\n" + " int a;\n" + "};\n"; const char expected[] = "1: class Fred : public B1 , public B2\n" "2: {\n" "3: public:\n" @@ -811,9 +810,9 @@ private: void varid35() { // function declaration inside function body // #2937 const char code[] ="int foo() {\n" - " int f(x);\n" - " return f;\n" - "}\n"; + " int f(x);\n" + " return f;\n" + "}\n"; const char expected[] = "1: int foo ( ) {\n" "2: int f@1 ( x ) ;\n" "3: return f@1 ;\n" @@ -843,7 +842,7 @@ private: void varid36() { // ticket #2980 (segmentation fault) const char code[] ="#elif A\n" - "A,a > b[10];\n" - "B> c[10];"; + "B< C<> > b[10];\n" + "B> c[10];"; ASSERT_EQUALS("1: A < B < C > :: D > e@1 ;\n" "2: B < C < > > b@2 [ 10 ] ;\n" "3: B < C < > > c@3 [ 10 ] ;\n", @@ -1005,12 +1004,12 @@ private: void varid55() { // Ticket #5868 const char code[] = "typedef struct foo {} foo; " - "void bar1(struct foo foo) {} " - "void baz1(foo foo) {} " - "void bar2(struct foo& foo) {} " - "void baz2(foo& foo) {} " - "void bar3(struct foo* foo) {} " - "void baz3(foo* foo) {}"; + "void bar1(struct foo foo) {} " + "void baz1(foo foo) {} " + "void bar2(struct foo& foo) {} " + "void baz2(foo& foo) {} " + "void bar3(struct foo* foo) {} " + "void baz3(foo* foo) {}"; const char expected[] = "1: " "struct foo { } ; " "void bar1 ( struct foo foo@1 ) { } " @@ -1218,9 +1217,9 @@ private: void varidFunctionCall1() { const char code[] ="void f() {\n" - " int x;\n" - " x = a(y*x,10);\n" - "}"; + " int x;\n" + " x = a(y*x,10);\n" + "}"; const char expected[] = "1: void f ( ) {\n" "2: int x@1 ;\n" "3: x@1 = a ( y * x@1 , 10 ) ;\n" @@ -1231,8 +1230,8 @@ private: void varidFunctionCall2() { // #2491 const char code[] ="void f(int b) {\n" - " x(a*b,10);\n" - "}"; + " x(a*b,10);\n" + "}"; const std::string expected1("1: void f ( int b@1 ) {\n" "2: x ( a * b"); const std::string expected2(" , 10 ) ;\n" @@ -1243,9 +1242,9 @@ private: void varidFunctionCall3() { // Ticket #2339 const char code[] ="void f() {\n" - " int a = 0;\n" - " int b = c - (foo::bar * a);\n" - "}"; + " int a = 0;\n" + " int b = c - (foo::bar * a);\n" + "}"; const char expected[] = "1: void f ( ) {\n" "2: int a@1 ; a@1 = 0 ;\n" @@ -1273,15 +1272,15 @@ private: void varidStl() { const std::string actual = tokenize( - "list ints;\n" - "list::iterator it;\n" - "std::vector dirs;\n" - "std::map coords;\n" - "std::tr1::unordered_map xy;\n" - "std::list tokens;\n" - "static std::vector ex1;\n" - "extern std::vector ex2;\n" - "std::map m;"); + "list ints;\n" + "list::iterator it;\n" + "std::vector dirs;\n" + "std::map coords;\n" + "std::tr1::unordered_map xy;\n" + "std::list tokens;\n" + "static std::vector ex1;\n" + "extern std::vector ex2;\n" + "std::map m;"); const char expected[] = "1: list < int > ints@1 ;\n" "2: list < int > :: iterator it@2 ;\n" @@ -1311,11 +1310,11 @@ private: void varid_delete() { const std::string actual = tokenize( - "void f()\n" - "{\n" - " int *a;\n" - " delete a;\n" - "}"); + "void f()\n" + "{\n" + " int *a;\n" + " delete a;\n" + "}"); const char expected[] = "1: void f ( )\n" "2: {\n" @@ -1329,8 +1328,8 @@ private: void varid_functions() { { const std::string actual = tokenize( - "void f();\n" - "void f(){}\n", "test.c"); + "void f();\n" + "void f(){}\n", "test.c"); const char expected[] = "1: void f ( ) ;\n" "2: void f ( ) { }\n"; @@ -1340,10 +1339,10 @@ private: { const std::string actual = tokenize( - "A f(3);\n" - "A f2(true);\n" - "A g();\n" - "A e(int c);\n", "test.c"); + "A f(3);\n" + "A f2(true);\n" + "A g();\n" + "A e(int c);\n", "test.c"); const char expected[] = "1: A f@1 ( 3 ) ;\n" "2: A f2@2 ( true ) ;\n" @@ -1355,18 +1354,18 @@ private: { const std::string actual = tokenize( - "void f1(int &p)\n" - "{\n" - " p = 0;\n" - "}\n" - "void f2(std::string &str)\n" - "{\n" - " str.clear();\n" - "}\n" - "void f3(const std::string &s)\n" - "{\n" - " s.size();\n" - "}"); + "void f1(int &p)\n" + "{\n" + " p = 0;\n" + "}\n" + "void f2(std::string &str)\n" + "{\n" + " str.clear();\n" + "}\n" + "void f3(const std::string &s)\n" + "{\n" + " s.size();\n" + "}"); const char expected[] = "1: void f1 ( int & p@1 )\n" "2: {\n" @@ -1405,12 +1404,12 @@ private: void varid_reference_to_containers() { const std::string actual = tokenize( - "void f()\n" - "{\n" - " std::vector b;\n" - " std::vector &a = b;\n" - " std::vector *c = &b;\n" - "}"); + "void f()\n" + "{\n" + " std::vector b;\n" + " std::vector &a = b;\n" + " std::vector *c = &b;\n" + "}"); const char expected[] = "1: void f ( )\n" "2: {\n" @@ -1425,12 +1424,12 @@ private: void varid_in_class1() { { const std::string actual = tokenize( - "class Foo\n" - "{\n" - "public:\n" - " std::string name1;\n" - " std::string name2;\n" - "};"); + "class Foo\n" + "{\n" + "public:\n" + " std::string name1;\n" + " std::string name2;\n" + "};"); const char expected[] = "1: class Foo\n" "2: {\n" @@ -1444,19 +1443,19 @@ private: { const std::string actual = tokenize( - "class foo\n" - "{\n" - "public:\n" - " void do_something(const int x, const int y);\n" - " void bar();\n" - "};\n" - "\n" - "void foo::bar()\n" - "{\n" - " POINT pOutput = { 0 , 0 };\n" - " int x = pOutput.x;\n" - " int y = pOutput.y;\n" - "}"); + "class foo\n" + "{\n" + "public:\n" + " void do_something(const int x, const int y);\n" + " void bar();\n" + "};\n" + "\n" + "void foo::bar()\n" + "{\n" + " POINT pOutput = { 0 , 0 };\n" + " int x = pOutput.x;\n" + " int y = pOutput.y;\n" + "}"); const char expected[] = "1: class foo\n" "2: {\n" @@ -1478,20 +1477,20 @@ private: void varid_in_class2() { const std::string actual = tokenize( - "struct Foo {\n" - " int x;\n" - "};\n" - "\n" - "struct Bar {\n" - " Foo foo;\n" - " int x;\n" - " void f();\n" - "};\n" - "\n" - "void Bar::f()\n" - "{\n" - " foo.x = x;\n" - "}"); + "struct Foo {\n" + " int x;\n" + "};\n" + "\n" + "struct Bar {\n" + " Foo foo;\n" + " int x;\n" + " void f();\n" + "};\n" + "\n" + "void Bar::f()\n" + "{\n" + " foo.x = x;\n" + "}"); const char expected[] = "1: struct Foo {\n" "2: int x@1 ;\n" "3: } ;\n" @@ -2197,11 +2196,11 @@ private: void varid_operator() { { const std::string actual = tokenize( - "class Foo\n" - "{\n" - "public:\n" - " void operator=(const Foo &);\n" - "};"); + "class Foo\n" + "{\n" + "public:\n" + " void operator=(const Foo &);\n" + "};"); const char expected[] = "1: class Foo\n" "2: {\n" @@ -2213,9 +2212,9 @@ private: } { const std::string actual = tokenize( - "struct Foo {\n" - " void * operator new [](int);\n" - "};"); + "struct Foo {\n" + " void * operator new [](int);\n" + "};"); const char expected[] = "1: struct Foo {\n" "2: void * operatornew[] ( int ) ;\n" "3: } ;\n"; @@ -2226,8 +2225,8 @@ private: void varid_throw() { // ticket #1723 const std::string actual = tokenize( - "UserDefinedException* pe = new UserDefinedException();\n" - "throw pe;"); + "UserDefinedException* pe = new UserDefinedException();\n" + "throw pe;"); const char expected[] = "1: UserDefinedException * pe@1 ; pe@1 = new UserDefinedException ( ) ;\n" "2: throw pe@1 ;\n"; @@ -2750,22 +2749,22 @@ private: void varidclass1() { const std::string actual = tokenize( - "class Fred\n" - "{\n" - "private:\n" - " int i;\n" - "\n" - " void foo1();\n" - " void foo2()\n" - " {\n" - " ++i;\n" - " }\n" - "}\n" - "\n" - "Fred::foo1()\n" - "{\n" - " i = 0;\n" - "}"); + "class Fred\n" + "{\n" + "private:\n" + " int i;\n" + "\n" + " void foo1();\n" + " void foo2()\n" + " {\n" + " ++i;\n" + " }\n" + "}\n" + "\n" + "Fred::foo1()\n" + "{\n" + " i = 0;\n" + "}"); const char expected[] = "1: class Fred\n" "2: {\n" @@ -2790,18 +2789,18 @@ private: void varidclass2() { const std::string actual = tokenize( - "class Fred\n" - "{ void f(); };\n" - "\n" - "void A::foo1()\n" - "{\n" - " int i = 0;\n" - "}\n" - "\n" - "void Fred::f()\n" - "{\n" - " i = 0;\n" - "}"); + "class Fred\n" + "{ void f(); };\n" + "\n" + "void A::foo1()\n" + "{\n" + " int i = 0;\n" + "}\n" + "\n" + "void Fred::f()\n" + "{\n" + " i = 0;\n" + "}"); const char expected[] = "1: class Fred\n" "2: { void f ( ) ; } ;\n" @@ -2822,18 +2821,18 @@ private: void varidclass3() { const std::string actual = tokenize( - "class Fred\n" - "{ int i; void f(); };\n" - "\n" - "void Fred::f()\n" - "{\n" - " i = 0;\n" - "}\n" - "\n" - "void A::f()\n" - "{\n" - " i = 0;\n" - "}"); + "class Fred\n" + "{ int i; void f(); };\n" + "\n" + "void Fred::f()\n" + "{\n" + " i = 0;\n" + "}\n" + "\n" + "void A::f()\n" + "{\n" + " i = 0;\n" + "}"); const char expected[] = "1: class Fred\n" "2: { int i@1 ; void f ( ) ; } ;\n" @@ -2854,14 +2853,14 @@ private: void varidclass4() { const std::string actual = tokenize( - "class Fred\n" - "{ int i; void f(); };\n" - "\n" - "void Fred::f()\n" - "{\n" - " if (i) { }\n" - " i = 0;\n" - "}"); + "class Fred\n" + "{ int i; void f(); };\n" + "\n" + "void Fred::f()\n" + "{\n" + " if (i) { }\n" + " i = 0;\n" + "}"); const char expected[] = "1: class Fred\n" "2: { int i@1 ; void f ( ) ; } ;\n" @@ -2877,13 +2876,13 @@ private: void varidclass5() { const std::string actual = tokenize( - "class A { };\n" - "class B\n" - "{\n" - " A *a;\n" - " B() : a(new A)\n" - " { }\n" - "};"); + "class A { };\n" + "class B\n" + "{\n" + " A *a;\n" + " B() : a(new A)\n" + " { }\n" + "};"); const char expected[] = "1: class A { } ;\n" "2: class B\n" @@ -2898,17 +2897,17 @@ private: void varidclass6() { const std::string actual = tokenize( - "class A\n" - "{\n" - " public:\n" - " static char buf[20];\n" - "};\n" - "char A::buf[20];\n" - "int main()\n" - "{\n" - " char buf[2];\n" - " A::buf[10] = 0;\n" - "}"); + "class A\n" + "{\n" + " public:\n" + " static char buf[20];\n" + "};\n" + "char A::buf[20];\n" + "int main()\n" + "{\n" + " char buf[2];\n" + " A::buf[10] = 0;\n" + "}"); const char expected[] = "1: class A\n" "2: {\n" @@ -2927,11 +2926,11 @@ private: void varidclass7() { const std::string actual = tokenize( - "int main()\n" - "{\n" - " char buf[2];\n" - " A::buf[10] = 0;\n" - "}"); + "int main()\n" + "{\n" + " char buf[2];\n" + " A::buf[10] = 0;\n" + "}"); const char expected[] = "1: int main ( )\n" "2: {\n" @@ -2944,12 +2943,12 @@ private: void varidclass8() { const char code[] ="class Fred {\n" - "public:\n" - " void foo(int d) {\n" - " int i = bar(x * d);\n" - " }\n" - " int x;\n" - "}\n"; + "public:\n" + " void foo(int d) {\n" + " int i = bar(x * d);\n" + " }\n" + " int x;\n" + "}\n"; const char expected[] = "1: class Fred {\n" "2: public:\n" @@ -2964,14 +2963,14 @@ private: void varidclass9() { const char code[] ="typedef char Str[10];" - "class A {\n" - "public:\n" - " void f(Str &cl);\n" - " void g(Str cl);\n" - "}\n" - "void Fred::f(Str &cl) {\n" - " sizeof(cl);\n" - "}"; + "class A {\n" + "public:\n" + " void f(Str &cl);\n" + " void g(Str cl);\n" + "}\n" + "void Fred::f(Str &cl) {\n" + " sizeof(cl);\n" + "}"; const char expected[] = "1: class A {\n" "2: public:\n" @@ -2987,11 +2986,11 @@ private: void varidclass10() { const char code[] ="class A {\n" - " void f() {\n" - " a = 3;\n" - " }\n" - " int a;\n" - "};\n"; + " void f() {\n" + " a = 3;\n" + " }\n" + " int a;\n" + "};\n"; const char expected[] = "1: class A {\n" "2: void f ( ) {\n" @@ -3004,15 +3003,15 @@ private: void varidclass11() { const char code[] ="class Fred {\n" - " int a;\n" - " void f();\n" - "};\n" - "class Wilma {\n" - " int a;\n" - " void f();\n" - "};\n" - "void Fred::f() { a = 0; }\n" - "void Wilma::f() { a = 0; }\n"; + " int a;\n" + " void f();\n" + "};\n" + "class Wilma {\n" + " int a;\n" + " void f();\n" + "};\n" + "void Fred::f() { a = 0; }\n" + "void Wilma::f() { a = 0; }\n"; const char expected[] = "1: class Fred {\n" "2: int a@1 ;\n" @@ -3030,9 +3029,9 @@ private: void varidclass12() { const char code[] ="class Fred {\n" - " int a;\n" - " void f() { Fred::a = 0; }\n" - "};\n"; + " int a;\n" + " void f() { Fred::a = 0; }\n" + "};\n"; const char expected[] = "1: class Fred {\n" "2: int a@1 ;\n" @@ -3044,9 +3043,9 @@ private: void varidclass13() { const char code[] ="class Fred {\n" - " int a;\n" - " void f() { Foo::Fred::a = 0; }\n" - "};\n"; + " int a;\n" + " void f() { Foo::Fred::a = 0; }\n" + "};\n"; const char expected[] = "1: class Fred {\n" "2: int a@1 ;\n" @@ -3060,8 +3059,8 @@ private: // don't give friend classes varid { const char code[] ="class A {\n" - "friend class B;\n" - "}"; + "friend class B;\n" + "}"; const char expected[] = "1: class A {\n" "2: friend class B ;\n" @@ -3072,8 +3071,8 @@ private: { const char code[] ="class A {\n" - "private: friend class B;\n" - "}"; + "private: friend class B;\n" + "}"; const char expected[] = "1: class A {\n" "2: private: friend class B ;\n" @@ -3411,14 +3410,14 @@ private: void exprid1() { const std::string actual = tokenizeExpr( - "struct A {\n" - " int x, y;\n" - "};\n" - "int f(A a, A b) {\n" - " int x = a.x + b.x;\n" - " int y = b.x + a.x;\n" - " return x + y + a.y + b.y;\n" - "}\n"); + "struct A {\n" + " int x, y;\n" + "};\n" + "int f(A a, A b) {\n" + " int x = a.x + b.x;\n" + " int y = b.x + a.x;\n" + " return x + y + a.y + b.y;\n" + "}\n"); const char expected[] = "1: struct A {\n" "2: int x ; int y ;\n" diff --git a/tools/dmake.cpp b/tools/dmake.cpp index fb3d729b9..9d41c53b1 100644 --- a/tools/dmake.cpp +++ b/tools/dmake.cpp @@ -65,7 +65,7 @@ static void getDeps(const std::string &filename, std::vector &depfi return; std::ifstream f(filename.c_str()); - if (! f.is_open()) { + if (!f.is_open()) { /* * Recursively search for includes in other directories. * Files are searched according to the following priority: diff --git a/tools/generate_cfg_tests.cpp b/tools/generate_cfg_tests.cpp index d0b570357..b5c66bcdd 100644 --- a/tools/generate_cfg_tests.cpp +++ b/tools/generate_cfg_tests.cpp @@ -56,7 +56,7 @@ int main(int argc, char **argv) std::cout << "// Recommended cppcheck command line:" << std::endl; std::cout << "// $ cppcheck --enable=warning,information --inline-suppr --platform=unix64 " << testfile << std::endl; std::cout << "// => 'unmatched suppression' warnings are false negatives." << std::endl; - std::cout << "//" << std::endl << std::endl ; + std::cout << "//" << std::endl << std::endl; const tinyxml2::XMLElement * const rootnode = doc.FirstChildElement();