Skip to content

Commit

Permalink
New random mode
Browse files Browse the repository at this point in the history
  • Loading branch information
simo981 committed Apr 19, 2024
1 parent b10710a commit e35ddb5
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 59 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/valgrind.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
42 changes: 41 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <ntimes,length> where ntimes are the number of strings printed and length the (obv) length of each string
--charset <ascii/num/alpha/alphalower/alphaupper/alphanum/alphanumupper> 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 <parameters>
```
## 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
```
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
72 changes: 52 additions & 20 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "main.h"
#include "queue.h"
#include "random.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -37,19 +38,15 @@ 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'},
{"last", required_argument, 0, 'l'},
{"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'},
Expand Down Expand Up @@ -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':
Expand Down Expand Up @@ -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 '?':
Expand All @@ -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';
Expand Down
71 changes: 37 additions & 34 deletions src/main.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef MAIN_H
#define MAIN_H
#pragma once
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
Expand All @@ -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) \
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
4 changes: 1 addition & 3 deletions src/queue.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef QUEUE
#define QUEUE
#pragma once
#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
Expand Down Expand Up @@ -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
65 changes: 65 additions & 0 deletions src/random.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "random.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdatomic.h>

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;
}
Loading

0 comments on commit e35ddb5

Please sign in to comment.