1 /* expr.c -- filter expression parsing and processing. 2 3 Copyright (C) 2020, 2022 Genome Research Ltd. 4 5 Author: James Bonfield <jkb@sanger.ac.uk> 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy 8 of this software and associated documentation files (the "Software"), to deal 9 in the Software without restriction, including without limitation the rights 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 copies of the Software, and to permit persons to whom the Software is 12 furnished to do so, subject to the following conditions: 13 14 The above copyright notices and this permission notice shall be included in 15 all copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 DEALINGS IN THE SOFTWARE. */ 24 module htslib.hts_expr; 25 26 import htslib.kstring: kstring_t; 27 28 @system: 29 nothrow: 30 @nogc: 31 32 extern (C): 33 34 /// Holds a filter variable. This is also used to return the results. 35 /** 36 * The expression language has 3-states of string, numeric, and unknown. 37 * The unknown state is either a NaN numeric or a null string, with both 38 * internally considered to have the same "unknown" meaning. 39 * 40 * These largely match the IEE 754 semantics for NaN comparisons: <, >, ==, 41 * != all fail, (even NaN == NaN). Similarly arithmetic (+,-,/,*,%) with 42 * unknown values are still unknown (and false). 43 * 44 * The departure from NaN semantics though is that our unknown/null state is 45 * considered to be false while NaN in C is true. Similarly the false nature 46 * of our unknown state meants !val becomes true, !!val is once again false, 47 * val && 1 is false, val || 0 is false, and val || 1 is true along with 48 * !val || 0 and !val && 1. 49 * 50 * Note it is possible for empty strings and zero numbers to also be true. 51 * An example of this is the aux string '[NM]' which returns true if the 52 * NM tag is found, regardless of whether it is also zero. However the 53 * better approach added in 1.16 is 'exists([NM])'. 54 */ 55 struct hts_expr_val_t 56 { 57 char is_str; // Use .s vs .d 58 char is_true; // Force true if even zero 59 kstring_t s; // is_str and empty s permitted (eval as false) 60 double d; // otherwise this 61 } 62 63 64 /* An example usage of this is in the SAM expression filter where an 65 * [X0] aux tag will be the value of X0 (string or numeric) if set, or 66 * a false nul-string (not the same as an empty one) when not set. 67 */ 68 int hts_expr_val_exists(hts_expr_val_t* v); 69 70 71 int hts_expr_val_existsT(hts_expr_val_t* v); 72 73 74 void hts_expr_val_undef(hts_expr_val_t* v); 75 76 /// Frees a hts_expr_val_t type. 77 void hts_expr_val_free(hts_expr_val_t* f); 78 79 /// Opaque hts_filter_t type. Definition in hts_expr.c 80 struct hts_filter_t; 81 82 /// For static initialisation of hts_expr_val_t values 83 84 /// Creates a filter for expression "str". 85 /** @param str The filter expression 86 * @return A pointer on success, NULL on failure 87 */ 88 hts_filter_t* hts_filter_init(const(char)* str); 89 90 /// Frees an hts_filter_t created via hts_filter_init 91 /** @param filt The filter pointer. 92 */ 93 void hts_filter_free(hts_filter_t* filt); 94 95 /// Type for expression symbol lookups; name -> value. 96 alias hts_expr_sym_func = int function( 97 void* data, 98 char* str, 99 char** end, 100 hts_expr_val_t* res); 101 102 /// Evaluates a filter expression and returns the value 103 /** @param filt The filter, produced by hts_filter_init 104 * @param data Arbitrary caller data, passed into sym_func 105 * @param sym_func Callback function to lookup variables. 106 * @param res Filled out with the result of the filter evaluation 107 * @return Returns 0 on success, -1 on failure 108 * 109 * sym_func and data may be NULL if the caller does not need its own data 110 * pointer or if it has no variables to lookup. 111 * 112 * The type of the returned result may be numeric of string, as defined by 113 * the is_str member. It can also be explicitly defined to be true even 114 * for a null value. This may be used to check for the existence of 115 * something, irrespective of whether that something evaluates to zero. 116 * 117 * @p res must be initialized using HTS_EXPR_VAL_INIT before passing it 118 * to this function for the first time. 119 */ 120 int hts_filter_eval2( 121 hts_filter_t* filt, 122 void* data, 123 int function() sym_func, 124 hts_expr_val_t* res); 125 126 127 /* 128 * @copydetails hts_filter_eval2() 129 * 130 * If calling this function more than once with the same @p res 131 * parameter, hts_expr_val_free(res) must be used between invocations 132 * to clear any allocated memory prior to reuse. 133 * 134 * @deprecated This function has been replaced by hts_filter_eval2(), 135 * which clears @p res properly itself. 136 */ 137 int hts_filter_eval( 138 hts_filter_t* filt, 139 void* data, 140 int function() sym_func, 141 hts_expr_val_t* res); 142 143 /* HTS_EXPR_H */