void zrex_test (bool verbose) { printf (" * zrex: "); // @selftest // This shows the pattern of matching many lines to a single pattern zrex_t *rex = zrex_new ("\\d+-\\d+-\\d+"); assert (rex); assert (zrex_valid (rex)); bool matches = zrex_matches (rex, "123-456-789"); assert (matches); assert (zrex_hits (rex) == 1); assert (streq (zrex_hit (rex, 0), "123-456-789")); assert (zrex_hit (rex, 1) == NULL); zrex_destroy (&rex); // Here we pick out hits using capture groups rex = zrex_new ("(\\d+)-(\\d+)-(\\d+)"); assert (rex); assert (zrex_valid (rex)); matches = zrex_matches (rex, "123-456-ABC"); assert (!matches); matches = zrex_matches (rex, "123-456-789"); assert (matches); assert (zrex_hits (rex) == 4); assert (streq (zrex_hit (rex, 0), "123-456-789")); assert (streq (zrex_hit (rex, 1), "123")); assert (streq (zrex_hit (rex, 2), "456")); assert (streq (zrex_hit (rex, 3), "789")); zrex_destroy (&rex); // This shows the pattern of matching one line against many // patterns and then handling the case when it hits rex = zrex_new (NULL); // No initial pattern assert (rex); char *input = "Mechanism: CURVE"; matches = zrex_eq (rex, input, "Version: (.+)"); assert (!matches); assert (zrex_hits (rex) == 0); matches = zrex_eq (rex, input, "Mechanism: (.+)"); assert (matches); assert (zrex_hits (rex) == 2); const char *mechanism; zrex_fetch (rex, &mechanism, NULL); assert (streq (zrex_hit (rex, 1), "CURVE")); assert (streq (mechanism, "CURVE")); zrex_destroy (&rex); #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
int zrex_test (bool verbose) { printf (" * zrex: "); zrex_t *rex = zrex_new (""); assert (rex); assert (!zrex_valid (rex)); if (verbose) puts (zrex_strerror (rex)); zrex_destroy (&rex); // This shows the pattern of matching many lines to a single pattern rex = zrex_new ("[0-9]+\\-[0-9]+\\-[0-9]+"); assert (rex); int hits = zrex_hits (rex, "123-456-789"); assert (hits == 1); assert (streq (zrex_hit (rex, 0), "123-456-789")); assert (zrex_hit (rex, 1) == NULL); zrex_destroy (&rex); // Here we pick out hits using capture groups rex = zrex_new ("([0-9]+)\\-([0-9]+)\\-([0-9]+)"); assert (rex); assert (zrex_valid (rex)); hits = zrex_hits (rex, "123-456-ABC"); assert (hits == 0); hits = zrex_hits (rex, "123-456-789"); assert (hits == 4); assert (streq (zrex_hit (rex, 0), "123-456-789")); assert (streq (zrex_hit (rex, 1), "123")); assert (streq (zrex_hit (rex, 2), "456")); assert (streq (zrex_hit (rex, 3), "789")); zrex_destroy (&rex); // This shows the pattern of matching one line against many // patterns and then handling the case when it hits rex = zrex_new (NULL); // No initial pattern char *input = "Mechanism: CURVE"; if (zrex_eq (rex, input, "Version: (.+)")) assert (false); else if (zrex_eq (rex, input, "Mechanism: (.+)")) assert (streq (zrex_hit (rex, 1), "CURVE")); zrex_destroy (&rex); printf ("OK\n"); return 0; }
static ztrie_node_t * s_ztrie_matches_token (ztrie_node_t *parent, char *token, int len) { char firstbyte = *token; ztrie_node_t *child = (ztrie_node_t *) zlistx_first (parent->children); while (child) { if (child->token_type == NODE_TYPE_STRING) { if (firstbyte == *child->token // This achieves a small performance boost && child->token_len == len && strncmp (child->token, token, MIN_LEN (child->token_len, len)) == 0) return child; } else if (child->token_type == NODE_TYPE_ASTERISK) { child->asterisk_match = strdup (token); return child; } else { // Need to copy token as zrex_matches expects '\0' terminated string char *token_term = s_strndup (token, len); if (zrex_matches (child->regex, token_term)) { if (child->token_type == NODE_TYPE_PARAM) { // One hit means no capturing group was defined // More than one hit indicates that at least on capturing group. // In this case only the values of the capturing groups are considered. if (zrex_hits (child->regex) == 1) s_ztrie_node_update_param (child, 1, zrex_hit (child->regex, 0)); else if (zrex_hits (child->regex) > 1) { int index; for (index = 1; index < zrex_hits (child->regex); index++) s_ztrie_node_update_param (child, index, zrex_hit (child->regex, index)); } } free (token_term); return child; } free (token_term); } child = (ztrie_node_t *) zlistx_next (parent->children); } return NULL; }
int zrex_eq (zrex_t *self, const char *text, const char *expression) { assert (self); assert (text); assert (expression); // If we had any previous expression, destroy it if (self->trex) { trex_free (self->trex); self->trex = NULL; } // Compile the new expression if (*expression) self->trex = trex_compile (expression, &self->strerror); else self->strerror = "Missing pattern"; // zrex_hits takes care of the rest for us return zrex_hits (self, text); }
int zsock_bind (zsock_t *self, const char *format, ...) { assert (self); assert (zsock_is (self)); // Expand format to get full endpoint va_list argptr; va_start (argptr, format); char *endpoint = zsys_vprintf (format, argptr); va_end (argptr); int rc; // If tcp:// endpoint, parse to get or make port number zrex_t *rex = zrex_new (NULL); if (zrex_eq (rex, endpoint, "^tcp://.*:(\\d+)$")) { assert (zrex_hits (rex) == 2); if (zmq_bind (self->handle, endpoint) == 0) rc = atoi (zrex_hit (rex, 1)); else rc = -1; } else if (zrex_eq (rex, endpoint, "^(tcp://.*):([*!])(\\[(\\d+)?-(\\d+)?\\])?$")) { assert (zrex_hits (rex) == 6); const char *hostname, *opcode, *group, *first_str, *last_str; zrex_fetch (rex, &hostname, &opcode, &group, &first_str, &last_str, NULL); int first = *first_str? atoi (first_str): DYNAMIC_FIRST; int last = *last_str? atoi (last_str): DYNAMIC_LAST; // This is how many times we'll try before giving up int attempts = last - first + 1; // If operator is '*', take first available port. // If operator is '!', take a random leap into our port space; we'll // still scan sequentially to make sure we find a free slot rapidly. int port = first; if (streq (opcode, "!")) port += randof (attempts); rc = -1; // Assume we don't succeed while (rc == -1 && attempts--) { free (endpoint); endpoint = zsys_sprintf ("%s:%d", hostname, port); if (zmq_bind (self->handle, endpoint) == 0) rc = port; if (++port > last) port = first; } } else rc = zmq_bind (self->handle, endpoint); // Store successful endpoint for later reference if (rc >= 0) { free (self->endpoint); self->endpoint = endpoint; } else free (endpoint); zrex_destroy (&rex); return rc; }