Пример #1
0
/**
Look ahead function to test whether a dictionary matches a condition
*/
t_bool _dict_recurse_match_dict(t_dict_recurse *x, t_dictionary *dict, t_symbol **key_match, t_symbol **value_match)
{
  TRACE("_dict_recurse_match_dict");

  // Get the dictionary keys
  long  key_cnt = 0;
  t_symbol **key_arr = NULL;
  t_symbol *key = gensym("");
  t_atom value[1];

  *key_match = gensym("");
  *value_match = gensym("");

  dictionary_getkeys(dict, &key_cnt, &key_arr);

  t_bool test = false;
  for (t_int32 ind = 0; ind < key_cnt; ind++) {

    key = key_arr[ind];

    if (!regexpr_match(x->search_key_expr, key)) { continue; }

    dictionary_getatom(dict, key, value);
    if (regexpr_match(x->search_val_expr, atom_getsym(value))) {
      test = true;
      *key_match = key;
      *value_match = atom_getsym(value);
      break; } }

  if (key_arr) { dictionary_freekeys(dict, key_cnt, key_arr); }
  
  return test;
}
Пример #2
0
void  dict_recurse_test_match(t_dict_recurse *x, t_symbol *sym, long argc, t_atom *argv)
{
  t_symbol *expr = atom_getsym(argv);
  t_symbol *key_sym = atom_getsym(argv + 1);

  regexpr_set(x->search_key_expr, expr);
  regexpr_match(x->search_key_expr, key_sym);
  regexpr_reset(x->search_key_expr);
}
Пример #3
0
	void FilterList::convert(const std::vector<std::string> & ruleList, const std::set<std::string> & disabled_list, std::vector<RegExpFilter *> & regexpList, std::vector<ElemHideSelector *> & elemHideFilter)
	{
		static const char * ELEMHIDE_PATTERN = "^([^\\/\\*\\|\\@\"]*?)#(?:([\\w\\-]+|\\*)((?:\\([\\w\\-]+(?:[$^*]?=[^\\(\\)\"]*)?\\))*)|#([^{}]+))$";
		static const char * REGEXPR_PATTERN = "^\\/(.*)\\/$";
		static const char * OPTIONS_PATTERN = "\\$(~?[\\w\\-]+(?:=[^,\\s]+)?(?:,~?[\\w\\-]+(?:=[^,\\s]+)?)*)$";

		for ( auto iter = ruleList.begin(); iter != ruleList.end(); iter++ )
		{
			std::string rule( * iter );

			if ( disabled_list.find(rule) != disabled_list.end() )
			{
				// 被禁用的规则,不做任何处理
				continue;
			}

			auto pos = knownFilters.find(rule);
			if ( pos != knownFilters.end() )
			{
				Filter * p = pos->second;
				if ( p )
				{
					RegExpFilter * regexpFilter = dynamic_cast<RegExpFilter *>(p);
					if ( regexpFilter )
					{
						regexpList.push_back(regexpFilter);
						// 加引用计数, 以免被释放
						regexpFilter->AddRef();
					}
					else
					{
						ElemHideSelector * selector = dynamic_cast<ElemHideSelector *>(p);
						if ( selector )
						{
							elemHideFilter.push_back(selector);
							// 加引用计数, 以免被释放
							selector->AddRef();
						}
						else
						{
							// 不应该走到这里, 但是如果真到这里了, 把 p 从 map 里面去掉
							knownFilters.erase(pos);
							p->Release();
						}
					}

					continue;
				}
			}

			// 元素隐藏规则
			std::string results[4];
			if ( regexpr_match(ELEMHIDE_PATTERN, rule.c_str(), FALSE, results, 4) )
			{
				const std::string & domain = results[0];
				const std::string & tagName = results[1];
				const std::string & attrRules = results[2];
				const std::string & selector = results[3];
				if ( ElemHideSelector * filter = ElemHideSelector::fromText(domain, tagName, attrRules, selector) )
				{
					elemHideFilter.push_back(filter);

					knownFilters[rule] = filter;
				}
			}
			else
			{
				std::string re_rule(rule);

				// 访问过滤规则
				std::string options_str;
				if ( regexpr_match(OPTIONS_PATTERN, re_rule.c_str(), FALSE, &options_str, 1) )
				{
					// 把参数部分去掉
					regexpr_replace(OPTIONS_PATTERN, re_rule.c_str(), "", re_rule);
				}
				
				if ( regexpr_match(REGEXPR_PATTERN, re_rule.c_str(), FALSE, results, 1) )
				{
					re_rule = results[0];
				}
				else
				{
					// 将 adblockplus 规则转换成正则表达式规则
					regexpr_replace("\\*+", re_rule.c_str(), "*", re_rule, TRUE);
					regexpr_replace("\\^\\|$", re_rule.c_str(), "^", re_rule, FALSE);
					regexpr_replace("(\\W)", re_rule.c_str(), "\r\\1", re_rule, TRUE);
					string_replace(re_rule, "\r", "\\");
					regexpr_replace("\\\\\\*", re_rule.c_str(), ".*", re_rule, TRUE);
					regexpr_replace("\\\\\\^", re_rule.c_str(), "(?:[^\rw\r-.%\ru0080-\ruFFFF]|$)", re_rule, TRUE);
					regexpr_replace("^\\\\\\|\\\\\\|", re_rule.c_str(), "^[\rw\r-]+:\r/+(?!\r/)(?:[^\r/]+\r.)?", re_rule, FALSE);
					string_replace(re_rule, "\r", "\\");
					regexpr_replace("^\\\\\\|", re_rule.c_str(), "^", re_rule, FALSE);
					regexpr_replace("\\\\\\|$", re_rule.c_str(), "$", re_rule, FALSE);
					regexpr_replace("^(\\.\\*)", re_rule.c_str(), "", re_rule, FALSE);
					regexpr_replace("(\\.\\*)$", re_rule.c_str(), "", re_rule, FALSE);
				}

				if ( RegExpFilter * filter = RegExpFilter::fromText(re_rule, options_str) )
				{
					regexpList.push_back(filter);

					knownFilters[rule] = filter;
				}
			}
		}
	}
Пример #4
0
/**
Called by _dict_recurse_dict() for each entry and _dict_recurse_array() for each index
*/
t_int32 _dict_recurse_value(t_dict_recurse *x, t_atom *value, t_int32 depth)
{
  TRACE("_dict_recurse_value");

  long type = atom_gettype(value);

  // ====  INT  ====
  if (type == A_LONG) {
    snprintf_zero(x->str_tmp, MAX_LEN_NUMBER, "%i", atom_getlong(value));
    _dict_recurse_value_find(x, value, x->str_tmp); }

  // ====  FLOAT  ====
  else if (type == A_FLOAT) {
    snprintf_zero(x->str_tmp, MAX_LEN_NUMBER, "%i", atom_getfloat(value));
    _dict_recurse_value_find(x, value, x->str_tmp); }
    
  // ====  SYMBOL / STRING  ====
  // NB: values in arrays are not A_SYM but A_OBJ 
  else if ((type == A_SYM) || atomisstring(value)) {

    t_symbol *value_sym = atom_getsym(value);

    switch (x->command) {
    
    // == FIND A SYMBOL VALUE
    case CMD_FIND_VALUE_SYM:

      if (regexpr_match(x->search_val_expr, value_sym)) {
        POST("  %s  \"%s\"", x->path, value_sym->s_name); x->count++; }
      break;

    // == FIND AN ENTRY
    case CMD_FIND_ENTRY:

      if (regexpr_match(x->search_key_expr, x->key_iter)
          && regexpr_match(x->search_val_expr, value_sym)
          && (x->type_iter == VALUE_TYPE_DICT)) {

        POST("  %s  \"%s\"", x->path, value_sym->s_name); x->count++; }
      break;

    // == REPLACE A SYMBOL VALUE
    case CMD_REPLACE_VALUE_SYM:
      
      if (regexpr_match(x->search_val_expr, value_sym)) {

        // If the value is from a dictionary entry
        if (x->type_iter == VALUE_TYPE_DICT) {
          dictionary_chuckentry(x->dict_iter, x->key_iter);
          dictionary_appendsym(x->dict_iter, x->key_iter, x->replace_val_sym); }

        // If the value is from an array
        else if (x->type_iter == VALUE_TYPE_ARRAY) { atom_setsym(value, x->replace_val_sym); }

        x->count++;
        if (x->a_verbose) {
          POST("  %s  \"%s\"  replaced by  \"%s\"",
            x->path, value_sym->s_name, x->replace_val_sym->s_name); } }
      break;

    // == REPLACE AN ENTRY
    case CMD_REPLACE_ENTRY:
      
      if (regexpr_match(x->search_key_expr, x->key_iter)
          && regexpr_match(x->search_val_expr, value_sym)
          && (x->type_iter == VALUE_TYPE_DICT)) {

        dictionary_chuckentry(x->dict_iter, x->key_iter);
        dictionary_appendsym(x->dict_iter, x->replace_key_sym, x->replace_val_sym);

        x->count++;
        if (x->a_verbose) {
          POST("  %s  \"%s\"  replaced by  (%s : %s)",
            x->path, value_sym->s_name, x->replace_key_sym->s_name, x->replace_val_sym->s_name); } }
      break;

    // == DELETE A SYMBOL VALUE
    case CMD_DELETE_VALUE_SYM:

      if (regexpr_match(x->search_val_expr, value_sym)) {

        // If the value is from a dictionary entry
        if (x->type_iter == VALUE_TYPE_DICT) {
          dictionary_deleteentry(x->dict_iter, x->key_iter); }

        // If the value is from an array
        else if (x->type_iter == VALUE_TYPE_ARRAY) {
          atomarray_chuckindex(x->array_iter, x->index_iter); }

        x->count++;
        if (x->a_verbose) {
          POST("  %s  \"%s\"  deleted",
            x->path, value_sym->s_name); }
        return VALUE_DEL; }
      break;

    // == DELETE A SYMBOL VALUE
    case CMD_DELETE_ENTRY:

      if (regexpr_match(x->search_key_expr, x->key_iter)
          && regexpr_match(x->search_val_expr, value_sym)
          && (x->type_iter == VALUE_TYPE_DICT)) {

        dictionary_deleteentry(x->dict_iter, x->key_iter);

        x->count++;
        if (x->a_verbose) {
          POST("  %s  \"%s\"  deleted",
            x->path, value_sym->s_name); }
        return VALUE_DEL; }
      break;

    // == DEFAULT: CMD_FIND_KEY or CMD_FIND_KEY_IN
    default:
      snprintf_zero(x->str_tmp, MAX_LEN_NUMBER, "\"%s\"", atom_getsym(value)->s_name);
      _dict_recurse_value_find(x, value, x->str_tmp);
      break; } }

  // ====  DICTIONARY  ====
  else if (atomisdictionary(value)) {

    t_dictionary *sub_dict = (t_dictionary *)atom_getobj(value);
    t_symbol *key_match = gensym("");
    t_symbol *value_match = gensym("");

    switch (x->command) {

    case CMD_FIND_DICT_CONT_ENTRY:
      
      if (_dict_recurse_match_dict(x, sub_dict, &key_match, &value_match)) {

        x->count++;
        POST("  %s:  dict containing  (%s : %s)",
          x->path, key_match->s_name, value_match->s_name); }
      break;

    case CMD_REPLACE_DICT_CONT_ENTRY:

      if (_dict_recurse_match_dict(x, sub_dict, &key_match, &value_match)) {

        t_dictionary *dict_cpy = dictionary_new();
        dictionary_clone_to_existing(x->replace_dict, dict_cpy);
        
        // If the value is from a dictionary entry
        if (x->type_iter == VALUE_TYPE_DICT) {
          dictionary_deleteentry(x->dict_iter, x->key_iter);
          dictionary_appenddictionary(x->dict_iter, x->key_iter, (t_object *)dict_cpy); }

        // If the value is from an array
        else if (x->type_iter == VALUE_TYPE_ARRAY) {
          long array_len;
          t_atom *atom_arr;
          atomarray_getatoms(x->array_iter, &array_len, &atom_arr);
          atom_setobj(atom_arr + x->index_iter, dict_cpy); } 

        x->count++;
        if (x->a_verbose) {
          POST("  %s:  dict containing  (%s : %s):  replaced by  \"%s\"",
            x->path, key_match->s_name, value_match->s_name, x->replace_dict_sym->s_name); } 
      
        return VALUE_NO_DEL; }
      break;

    case CMD_DELETE_DICT_CONT_ENTRY:

      if (_dict_recurse_match_dict(x, sub_dict, &key_match, &value_match)) {

        // If the value is from a dictionary entry
        if (x->type_iter == VALUE_TYPE_DICT) {
          dictionary_deleteentry(x->dict_iter, x->key_iter); }

        // If the value is from an array
        else if (x->type_iter == VALUE_TYPE_ARRAY) {
          atomarray_chuckindex(x->array_iter, x->index_iter);
          object_free(sub_dict); } 

        x->count++;
        if (x->a_verbose) {
          POST("  %s:  dict containing  (%s : %s):  deleted",
            x->path, key_match->s_name, value_match->s_name); }

        return VALUE_DEL; }
      break;

    case CMD_APPEND_IN_DICT_CONT_ENTRY:

      if (_dict_recurse_match_dict(x, sub_dict, &key_match, &value_match)) {

        dictionary_appendsym(sub_dict, x->replace_key_sym, x->replace_val_sym);

        x->count++;
        if (x->a_verbose) {
          POST("  %s:  dict containing  (%s : %s):  appended  (%s : %s)",
            x->path, key_match->s_name, value_match->s_name, x->replace_key_sym->s_name, x->replace_val_sym->s_name); } }
      break;

    case CMD_APPEND_IN_DICT_CONT_ENTRY_D:

      if (_dict_recurse_match_dict(x, sub_dict, &key_match, &value_match)
          && dictionary_hasentry(x->replace_dict, x->replace_key_sym)) {

        t_symbol *key[2]; key[0] = x->replace_key_sym; key[1] = NULL;
        dictionary_copyentries(x->replace_dict, sub_dict, key);    // NB: Strange it does not require the array size

        x->count++;
        if (x->a_verbose) {
          POST("  %s:  dict containing  (%s : %s):  appended entry  (%s : ...)  from \"%s\"",
            x->path, key_match->s_name, value_match->s_name, x->replace_key_sym->s_name, x->replace_dict_sym->s_name); } }
      break;

    case CMD_APPEND_IN_DICT_FROM_KEY:

      if (regexpr_match(x->search_key_expr, x->key_iter)
          && (x->type_iter == VALUE_TYPE_DICT)
          && dictionary_hasentry(x->replace_dict, x->replace_key_sym)) {

        t_symbol *key[2]; key[0] = x->replace_key_sym; key[1] = NULL;
        dictionary_copyentries(x->replace_dict, sub_dict, key);    // NB: Strange it does not require the array size
        
        x->count++;
        if (x->a_verbose) {
          POST("  %s:  dict value:  appended entry  (%s : ...)  from \"%s\"",
            x->path, x->replace_key_sym->s_name, x->replace_dict_sym->s_name); } }
      break;
    
    default:
      _dict_recurse_value_find(x, value, "_DICT_"); }    // End of command "switch ..."

    _dict_recurse_dict(x, sub_dict, depth); }    // End of dictionary "else if ..."

  // ====  ARRAY  ====
  else if (atomisatomarray(value)) {

    _dict_recurse_value_find(x, value, "_ARRAY_");

    t_atomarray *atomarray = (t_atomarray *)atom_getobj(value);
    _dict_recurse_array(x, atomarray, depth);  }

  return VALUE_NO_DEL;
}
Пример #5
0
void _dict_recurse_dict(t_dict_recurse *x, t_dictionary *dict, t_int32 depth)
{
  TRACE("_dict_recurse_dict");

  t_atom atom[1];

  // ==== Store the state variables on the beginning of the function
  t_bool has_match_ini = x->has_match;
  t_int32 path_len_ini = (t_int32)strlen(x->path);
  t_value_type type_iter_ini = x->type_iter;
  t_dictionary *dict_iter_ini = x->dict_iter;
  t_symbol *key_iter_ini = x->key_iter;
  
  // ==== Add :: to the path
  strncat_zero(x->path, "::", x->path_len_max);

  // ==== Get the dictionary keys
  long  key_cnt = 0;
  t_symbol **key_arr = NULL;
  dictionary_getkeys(dict, &key_cnt, &key_arr);

  // ==== Increment the depth
  depth++;

  // ==== Set the trailing variables before for the recursions
  x->type_iter = VALUE_TYPE_DICT;
  x->dict_iter = dict;

  // ==== Loop through the keys
  for (t_int32 ind = 0; ind < key_cnt; ind++) {

    x->key_iter = key_arr[ind];

    // == Opening actions depending on which command is being processed
    switch (x->command) {
    
    case CMD_FIND_KEY_IN:
    case CMD_FIND_KEY:
      if (regexpr_match(x->search_key_expr, x->key_iter)) {
        x->has_match = true; x->count++; }    // x->has_match changed
      break;

    case CMD_REPLACE_KEY:
      if (regexpr_match(x->search_key_expr, x->key_iter)) {
        dictionary_getatom(dict, x->key_iter, atom);
        dictionary_chuckentry(dict, x->key_iter);
        dictionary_appendatom(dict, x->replace_key_sym, atom);
        x->count++;

        if (x->a_verbose == true) {
          POST("  %s%s  replaced by  \"%s\"",
            x->path, x->key_iter->s_name, x->replace_key_sym->s_name); }
        x->key_iter = x->replace_key_sym; }
      break;
    
    case CMD_DELETE_KEY:
      if (regexpr_match(x->search_key_expr, x->key_iter)) {
        dictionary_deleteentry(dict, x->key_iter);
        x->count++;

        if (x->a_verbose == true) {
          POST("  %s%s  deleted",
            x->path, x->key_iter->s_name, x->replace_key_sym->s_name); }

        continue; }    // NB: No further recursion
      break;

    case CMD_REPLACE_VALUE_FROM_DICT:
      if (regexpr_match(x->search_key_expr, x->key_iter)
          && dictionary_hasentry(x->replace_dict, x->key_iter)) {

        t_symbol *key_iter[2]; key_iter[0] = x->key_iter; key_iter[1] = NULL;
        dictionary_copyentries(x->replace_dict, dict, key_iter);    // NB: Strange it does not require the array size
        x->count++;

        if (x->a_verbose == true) {
          POST("  %s%s  replaced from  \"%s\"",
            x->path, x->key_iter->s_name, x->replace_dict_sym->s_name); }

        continue; }    // NB: No further recursion
      break;
        
    default: break;
    }    // >>>> END switch through potential commands

    // == Set the trailing variables before for the recursion
    strncat_zero(x->path, x->key_iter->s_name, x->path_len_max);    // NB: x->path changed
    
    // == Get the value and recurse to it
    dictionary_getatom(dict, x->key_iter, atom);    // NB: This creates a copy
    _dict_recurse_value(x, atom, depth);
    
    // == Reset the values that changed in this loop
    x->path[path_len_ini + 2] = '\0';
    x->has_match = has_match_ini; }    // >>>> END of loop through the keys
  
  // ==== Restore the remaining state variables to their beginning values
  x->type_iter = type_iter_ini;
  x->dict_iter = dict_iter_ini;
  x->key_iter = key_iter_ini;
  
  if (key_arr) { dictionary_freekeys(dict, key_cnt, key_arr); }
}