From e35ddb58811d5f74c166d750d7101f5652993773 Mon Sep 17 00:00:00 2001 From: simone Date: Fri, 19 Apr 2024 04:03:20 +0200 Subject: [PATCH] New random mode --- .github/workflows/valgrind.yml | 2 + README.md | 42 +++++++++++++++++++- src/Makefile | 2 +- src/main.c | 72 ++++++++++++++++++++++++---------- src/main.h | 71 +++++++++++++++++---------------- src/queue.h | 4 +- src/random.c | 65 ++++++++++++++++++++++++++++++ src/random.h | 19 +++++++++ 8 files changed, 218 insertions(+), 59 deletions(-) create mode 100644 src/random.c create mode 100644 src/random.h diff --git a/.github/workflows/valgrind.yml b/.github/workflows/valgrind.yml index 68c503f..dbf814e 100644 --- a/.github/workflows/valgrind.yml +++ b/.github/workflows/valgrind.yml @@ -26,3 +26,5 @@ jobs: valgrind --show-leak-kinds=all -s --leak-check=full --track-origins=yes ./seqperm --reverse full --upper full --leet full --start 1 --end 5 --only_transformations --last 2024,001,1,355 --connectors .,- hi how ar,e you fi,ne 1>/dev/null valgrind --show-leak-kinds=all -s --leak-check=full --track-origins=yes ./seqperm --reverse full --upper full --leet full --start 1 --end 5 --last 2024,001,1,355 --connectors .,- hi how ar,e you fi,ne 1>/dev/null valgrind --show-leak-kinds=all -s --leak-check=full --track-origins=yes ./seqperm --start 1 --end 10 a b c d e f g h i l 1>/dev/null + valgrind --show-leak-kinds=all -s --leak-check=full --track-origins=yes ./seqperm --random 10000,12 --charset ascii 1>/dev/null + valgrind --show-leak-kinds=all -s --leak-check=full --track-origins=yes ./seqperm --random 10000,12 abcedfg0123456789 diff --git a/README.md b/README.md index a608f01..a393d1c 100644 --- a/README.md +++ b/README.md @@ -28,20 +28,60 @@ Instead, if "," is used, and in input you have fish,es the permutation fishesfis ``` words/chars go after parameters separeted by space ``` +## Random mode parameters +``` +You can also generate a random dataset with these parameters +``` +``` +--random where ntimes are the number of strings printed and length the (obv) length of each string +--charset the charset used +``` +``` +In which charset parameters are + +ascii: [\x00-\x7F] +num: [0-9] +alpha: [A-Za-z] +alpha lower: [a-z] +alpha upper: [A-Z] +alphanum: [0-9A-Za-z] +alphanum upper: [0-9A-Z] +``` +``` +You can also use your own charset, passed after the parameter --random x,y +``` ## Compile and Run ``` 1) Change number of threads directly in file main.h (best probably would be same number of phisical core) 2) $ make 3) $ ./seperm ``` -## Sample Usage +## Sample usage normal mode We want all permutation without repetition of ``` a b c d e f g h i l m ``` of 3/4/5 characters length with connectors ```,``` and ```.``` between chars and numbers ```0``` and ```1``` at the end. We dont't want any uppercase first character. ``` ./seqperm --start 3 --end 5 --last 0,1 --connectors ,. a b c d e f g h i l m ``` +We want all the permutation of length 2/3/4 words of `john titor ibm time travel` with shortened string on `titor` with connector `.` and last chars `!?` and numers `2024 24` with leet only with vowel and upper case in first character, we don't want reverse +To print all permutations for every possible combination of modifiers +``` +./seqperm --start 2 --end 4 --connectors . --last !,?,2024,24 --leet vowel --upper first john tit,or ibm time travel +``` +If we want only the permutations with all the modifiers simultaneously +``` +./seqperm --start 2 --end 4 --connectors . --last !,?,2024,24 --leet vowel --upper first --only-transformations john tit,or ibm time travel +``` ## Complexity as number of permutation generated $$ (\sum_{k=start}^{end}{\binom{words}{k} \cdot k!}) \times (connectors + 1) \times (upper + 1) \times (last + 1) \times (leet + 1) \times (reverse + 1) $$ +## Sample usage random mode +We want to generate 1M strings of length 12 with our own charset +``` +./seqperm --random 1000000,12 abcdefgh1234 +``` +We want to generate 1M strings of length 12 with default charset ascii +``` +./seqperm --random 1000000,12 --charset ascii +``` \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index a002747..4890861 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,7 +7,7 @@ endif CC = cc TARGET = seqperm LINK = -lpthread -OBJ = main.o queue.o +OBJ = main.o queue.o random.o .PHONY = clean re $(TARGET): $(OBJ) diff --git a/src/main.c b/src/main.c index a112522..dd9d47e 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include "main.h" #include "queue.h" +#include "random.h" #include #include #include @@ -37,12 +38,6 @@ void gen_bin_to_arr(unsigned short *arr, size_t size, size_t idx, size_t max, si } } -void free_inputs_optind(void) -{ - FREE_P(connectors); - FREE_P(last); -} - static struct option long_options[] = { {"upper", required_argument, 0, 'u'}, @@ -50,6 +45,8 @@ static struct option long_options[] = {"only_transformations", no_argument, 0, 'p'}, {"reverse", required_argument, 0, 'r'}, {"leet", required_argument, 0, 'k'}, + {"random", required_argument, 0, 'm'}, + {"charset", required_argument, 0, 'i'}, {"connectors", required_argument, 0, 'c'}, {"start", required_argument, 0, 's'}, {"end", required_argument, 0, 'e'}, @@ -386,31 +383,52 @@ void gen_bin_perms(unsigned short *arr, size_t size, size_t idx, size_t max, siz int main(int argc, char **argv) { int c, option_index = 0; - while ((c = getopt_long(argc, argv, "u:l:pk:c:s:e:r:", long_options, &option_index)) != -1) + enum c_t rand_type = _NULL; + size_t rand_times = 0, rand_len = 0; + while ((c = getopt_long(argc, argv, "u:l:pk:c:s:e:r:m:i:", long_options, &option_index)) != -1) { switch (c) { + case 'i': + { + CALL_SET(strcmp(optarg, "ascii"), 0, rand_type, ASCII); + CALL_SET(strcmp(optarg, "num"), 0, rand_type, NUM); + CALL_SET(strcmp(optarg, "alpha"), 0, rand_type, ALPHA); + CALL_SET(strcmp(optarg, "alphalower"), 0, rand_type, ALPHALOWER); + CALL_SET(strcmp(optarg, "alphaupper"), 0, rand_type, ALPHAUPPER); + CALL_SET(strcmp(optarg, "alphanum"), 0, rand_type, ALPHANUM); + CALL_SET(strcmp(optarg, "alphanumupper"), 0, rand_type, ALPHANUMUPPER); + break; + } + case 'm': + { + char *token = strtok(optarg, ","); + ERR("random times can't be less than 0 or null", rand_times, strtoul(token, NULL, 10)); + token = strtok(NULL, ","); + ERR("random length can't be less than 0 or null", rand_len, strtoul(token, NULL, 10)); + break; + } case 'r': { - CALL_ZERO_SET_TRUE(strcmp(optarg, "full"), bool_modifiers.reverse_full); - CALL_ZERO_SET_TRUE(strcmp(optarg, "words"), bool_modifiers.reverse_words); + CALL_SET(strcmp(optarg, "full"), 0, bool_modifiers.reverse_full, true); + CALL_SET(strcmp(optarg, "words"), 0, bool_modifiers.reverse_words, true); break; } case 'k': { - CALL_ZERO_SET_TRUE(strcmp(optarg, "full"), bool_modifiers.leet_full); - CALL_ZERO_SET_TRUE(strcmp(optarg, "vowel"), bool_modifiers.leet_vowel); + CALL_SET(strcmp(optarg, "full"), 0, bool_modifiers.leet_full, true); + CALL_SET(strcmp(optarg, "vowel"), 0, bool_modifiers.leet_vowel, true); break; } case 'u': { - CALL_ZERO_SET_TRUE(strcmp(optarg, "full"), bool_modifiers.upper_full); - CALL_ZERO_SET_TRUE(strcmp(optarg, "first"), bool_modifiers.upper_first); + CALL_SET(strcmp(optarg, "full"), 0, bool_modifiers.upper_full, true); + CALL_SET(strcmp(optarg, "first"), 0, bool_modifiers.upper_first, true); break; } case 'p': { - CALL_ZERO_SET_TRUE(0, bool_modifiers.only_transform); + CALL_SET(0, 0, bool_modifiers.only_transform, true); break; } case 'c': @@ -448,12 +466,12 @@ int main(int argc, char **argv) } case 's': { - ERR("min_len can't be less than 0 or null", min_len, strtoul(optarg, NULL, 10)); + ERR("min_len in normal mode can't be less than 0 or null", min_len, strtoul(optarg, NULL, 10)); break; } case 'e': { - ERR("max_len can't be less than 0 or null", max_len, strtoul(optarg, NULL, 10)); + ERR("max_len in normal mode can't be less than 0 or null", max_len, strtoul(optarg, NULL, 10)); break; } case '?': @@ -468,10 +486,24 @@ int main(int argc, char **argv) } } - CHECK_TRUE(!min_len, "max_len must be stated"); - CHECK_TRUE(!max_len, "min_len must be stated"); - LOW("max_len must be greater than min_len", max_len, min_len); - CHECK_TRUE(optind == argc, "words not provided"); + CHECK_TRUE(optind == argc && rand_type == _NULL, "words or charset not provided"); + + if (rand_len || rand_times) + { + CHECK_TRUE(!rand_len, "rand_len must be stated in rand mode"); + CHECK_TRUE(!rand_times, "rand_times must be stated in rand mode"); + char *charset = rand_type != _NULL ? NULL : strdup(argv[optind]); + rand_type = rand_type == _NULL ? USER : rand_type; + main_random(rand_times, rand_len, rand_type, charset, N_THREAD); + FREE_P(charset); + FREE_PP(connectors, 0, connectors_size); + FREE_PP(last, 0, last_size); + return 0; + } + + CHECK_TRUE(!min_len, "max_len must be stated in normal mode"); + CHECK_TRUE(!max_len, "min_len must be stated in normal mode"); + LOW("max_len in normal mode must be greater than min_len", max_len, min_len); leet_map['a'] = leet_map['A'] = '4'; leet_map['e'] = leet_map['E'] = '3'; diff --git a/src/main.h b/src/main.h index 3f1856e..d882f0f 100644 --- a/src/main.h +++ b/src/main.h @@ -1,5 +1,4 @@ -#ifndef MAIN_H -#define MAIN_H +#pragma once #include #include #include @@ -12,11 +11,14 @@ #define FREE_PPP(p, fc, size, sc, size2) \ ({ \ - for (size_t i = fc; i < size; i++) \ + if (p) \ { \ - FREE_PP(p[i], sc, size2); \ + for (size_t i = fc; i < size; i++) \ + { \ + FREE_PP(p[i], sc, size2); \ + } \ + FREE_P(p); \ } \ - FREE_P(p); \ }) #define FREE_PP(p, fc, size) \ @@ -47,21 +49,22 @@ copy_len; \ }) -#define CALL_ZERO_SET_TRUE(call, var) \ - ({ \ - if (call == 0) \ - { \ - var = true; \ - } \ +#define CALL_SET(call, eq, var, to) \ + ({ \ + if (call == eq) \ + { \ + var = to; \ + } \ }) -#define CHECK_TRUE(var, message) \ - ({ \ - if (var) \ - { \ - free_inputs_optind(); \ - exit_usage(#message); \ - } \ +#define CHECK_TRUE(var, message) \ + ({ \ + if (var) \ + { \ + FREE_PP(connectors, 0, connectors_size); \ + FREE_PP(last, 0, last_size); \ + exit_usage(#message); \ + } \ }) typedef struct bool_t @@ -73,7 +76,7 @@ typedef struct bool_t uint8_t only_transform : 1; uint8_t reverse_words : 1; uint8_t reverse_full : 1; - uint8_t __padding : 1; + uint8_t charset : 1; } modifiers_t; typedef struct delim_t @@ -106,21 +109,21 @@ void exit_usage(char *plus) exit(EXIT_FAILURE); } -#define ERR(NAME, VAR, CALL) \ - errno = 0; \ - VAR = CALL; \ - if (errno != 0) \ - { \ - perror(#NAME); \ - free_inputs_optind(); \ - exit(EXIT_FAILURE); \ +#define ERR(NAME, VAR, CALL) \ + errno = 0; \ + VAR = CALL; \ + if (errno != 0) \ + { \ + perror(#NAME); \ + FREE_PP(connectors, 0, connectors_size); \ + FREE_PP(last, 0, last_size); \ + exit(EXIT_FAILURE); \ } -#define LOW(NAME, VAR1, VAR2) \ - if (VAR1 < VAR2) \ - { \ - free_inputs_optind(); \ - exit_usage(#NAME); \ +#define LOW(NAME, VAR1, VAR2) \ + if (VAR1 < VAR2) \ + { \ + FREE_PP(connectors, 0, connectors_size); \ + FREE_PP(last, 0, last_size); \ + exit_usage(#NAME); \ } - -#endif diff --git a/src/queue.h b/src/queue.h index a8e465c..fe20173 100644 --- a/src/queue.h +++ b/src/queue.h @@ -1,5 +1,4 @@ -#ifndef QUEUE -#define QUEUE +#pragma once #include #include #include @@ -41,4 +40,3 @@ input_t *pop_queue(Queue_t *Q); void free_queue(Queue_t *Q); void resize(Queue_t *Q); Queue_t *default_init_queue(); -#endif diff --git a/src/random.c b/src/random.c new file mode 100644 index 0000000..eaff990 --- /dev/null +++ b/src/random.c @@ -0,0 +1,65 @@ +#include "random.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *ascii = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; +char *dataset; +const size_t se[8][2] = {{0, 96}, {0, 10}, {10, 62}, {36, 62}, {10, 36}, {0, 62}, {0, 36}}; + +typedef struct random_t +{ + size_t size; + size_t times; + enum c_t type; +} random_t; + +void *thread_random(void *in) +{ + random_t *x = (random_t *)in; + unsigned int myseed = time(NULL) ^ (size_t)pthread_self(); + char *out = calloc(x->size + 1, sizeof(char)); + size_t start, end; + start = x->type != USER ? se[x->type][0] : 0; + end = x->type != USER ? se[x->type][1] : strlen(dataset); + for (size_t i = 0; i < x->times; i++) + { + for (size_t i = 0; i < x->size; i++) + { + out[i] = dataset[(rand_r(&myseed) % (end - start)) + start]; + } + printf("%s\n", out); + } + free(x); + free(out); + return NULL; +} + +void main_random(size_t times, size_t length, enum c_t type, char *charset, size_t N_THREAD_) +{ + dataset = ascii; + dataset = type == USER && charset != NULL ? charset : dataset; + pthread_t tworker[N_THREAD_]; + memset(&tworker, 0x0, sizeof(tworker)); + size_t ttimes = times / N_THREAD_; + size_t mod = times % N_THREAD_; + for (size_t i = 0; i < N_THREAD_; i++) + { + random_t *x = (random_t *)malloc(sizeof(random_t)); + x->size = length; + x->type = type; + x->times = i == 0 ? ttimes + mod : ttimes; + pthread_create(&tworker[i], NULL, thread_random, (void *)x); + } + for (size_t i = 0; i < N_THREAD_; i++) + { + pthread_join(tworker[i], NULL); + } + return; +} \ No newline at end of file diff --git a/src/random.h b/src/random.h new file mode 100644 index 0000000..413a2bc --- /dev/null +++ b/src/random.h @@ -0,0 +1,19 @@ +#pragma once +#include + +enum c_t +{ + ASCII = 0, + NUM, + ALPHA, + ALPHALOWER, + ALPHAUPPER, + ALPHANUM, + ALPHANUMUPPER, + USER, + _NULL +}; + +void main_random(size_t times, size_t length, enum c_t type, char *charset, size_t N_THREAD_); +void *thread_random(void *in); +void rand_gen(unsigned int *seed, char *buff, enum c_t type, size_t n);