Line data Source code
1 : #include "passgen/parser/parser.h" 2 : #include "passgen/parser/token.h" 3 : #include "passgen/pattern/pattern.h" 4 : #include "passgen/util/random.h" 5 : #include "passgen/util/utf8.h" 6 : #include <assert.h> 7 : #include <passgen/passgen.h> 8 : #include <string.h> 9 : 10 20104 : int passgen_parse( 11 : passgen_pattern *output, 12 : passgen_error *error, 13 20104 : const char *string) { 14 : passgen_parser parser; 15 20104 : passgen_token_parser token_parser = {0}; 16 20104 : passgen_token token = {0}; 17 20104 : passgen_parser_init(&parser, output); 18 : 19 20104 : const uint8_t *pattern_raw = (const uint8_t *) string; 20 20104 : size_t pattern_len = 256; 21 20104 : uint32_t pattern[pattern_len]; 22 20104 : uint8_t pattern_widths[pattern_len]; 23 20104 : size_t pattern_pos = 0; 24 20104 : size_t pattern_pos_total = 0; 25 20104 : size_t pattern_raw_pos = 0; 26 20104 : size_t pattern_raw_len = strlen(string); 27 : 28 20104 : int decode_ret = 0; 29 : 30 : do { 31 20105 : uint32_t *pattern_cur = &pattern[0]; 32 20105 : const uint8_t *pattern_raw_cur = &pattern_raw[pattern_raw_pos]; 33 : 34 : // decode input utf8 into unicode codepoints 35 20105 : decode_ret = passgen_utf8_decode( 36 : &pattern_cur, 37 : pattern_len, 38 : pattern_widths, 39 : &pattern_raw_cur, 40 : pattern_raw_len - pattern_raw_pos); 41 : 42 20105 : pattern_raw_pos += pattern_raw_cur - &pattern_raw[pattern_raw_pos]; 43 20105 : pattern_pos = pattern_cur - &pattern[0]; 44 20105 : pattern_pos_total += pattern_pos; 45 : 46 : // make sure utf8 decoding was successful 47 20105 : if(decode_ret < PASSGEN_UTF8_SUCCESS) { 48 8 : passgen_error_init(error, passgen_utf8_error(decode_ret)); 49 8 : passgen_error_offset_set(error, pattern_pos_total, pattern_raw_pos); 50 8 : passgen_parser_free(&parser); 51 6350 : return -1; 52 : } 53 : 54 : // parse tokens and pattern 55 206977 : for(size_t i = 0; i < pattern_pos; i++) { 56 193222 : int ret = passgen_token_parse( 57 : &token_parser, 58 : &token, 59 193222 : pattern_widths[i], 60 : pattern[i]); 61 : 62 : // make sure parsing the token was successful 63 193222 : if(ret < 0) { 64 38 : passgen_error_init(error, passgen_token_parse_error_str(ret)); 65 38 : passgen_error_offset_set(error, token.offset, token.byte_offset); 66 38 : passgen_parser_free(&parser); 67 38 : return -1; 68 : } 69 : 70 : // if we have a token, feed it to the parser 71 193184 : if(ret == PASSGEN_TOKEN_INIT) { 72 190315 : ret = passgen_parse_token(&parser, &token); 73 : // make sure that the parser accepts the token 74 190315 : if(ret != 0) { 75 6304 : passgen_error_init(error, "invalid token"); 76 6304 : passgen_error_offset_set(error, token.offset, token.byte_offset); 77 6304 : passgen_parser_free(&parser); 78 6304 : return -1; 79 : } 80 184011 : assert(ret == 0); 81 : } 82 : } 83 13755 : } while(decode_ret > PASSGEN_UTF8_SUCCESS); 84 : 85 : // make sure we aren't still parsing tokens 86 13754 : if(token_parser.state != PASSGEN_TOKEN_INIT) { 87 240 : passgen_error_init(error, passgen_token_parse_error_str(token_parser.state)); 88 240 : passgen_error_offset_set(error, pattern_pos_total, pattern_raw_pos); 89 240 : passgen_parser_free(&parser); 90 240 : return -1; 91 : } 92 : 93 : // make sure we are done parsing 94 13514 : if(0 != passgen_parse_finish(&parser)) { 95 4029 : passgen_error_init(error, "parsing not finished"); 96 4029 : passgen_error_offset_set(error, pattern_pos_total, pattern_raw_pos); 97 4029 : passgen_parser_free(&parser); 98 4029 : return -1; 99 : } 100 : 101 9485 : passgen_parser_free(&parser); 102 : 103 9485 : return 0; 104 : }