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/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 6621 : return -1; 52 : } 53 : 54 : // parse tokens and pattern 55 206279 : for(size_t i = 0; i < pattern_pos; i++) { 56 192795 : int ret = passgen_token_parse( 57 : &token_parser, 58 : &token, 59 192795 : pattern_widths[i], 60 : pattern[i]); 61 : 62 : // make sure parsing the token was successful 63 192795 : if(ret < 0) { 64 43 : passgen_error_init(error, passgen_token_parse_error_str(ret)); 65 43 : passgen_error_offset_set( 66 : error, 67 : token.offset, 68 : token.byte_offset); 69 43 : passgen_parser_free(&parser); 70 43 : return -1; 71 : } 72 : 73 : // if we have a token, feed it to the parser 74 192752 : if(ret == PASSGEN_TOKEN_INIT) { 75 189820 : ret = passgen_parse_token(&parser, &token); 76 : // make sure that the parser accepts the token 77 189820 : if(ret != 0) { 78 6570 : passgen_error_init(error, "invalid token"); 79 6570 : passgen_error_offset_set( 80 : error, 81 : token.offset, 82 : token.byte_offset); 83 6570 : passgen_parser_free(&parser); 84 6570 : return -1; 85 : } 86 183250 : assert(ret == 0); 87 : } 88 : } 89 13484 : } while(decode_ret > PASSGEN_UTF8_SUCCESS); 90 : 91 : // make sure we aren't still parsing tokens 92 13483 : if(token_parser.state != PASSGEN_TOKEN_INIT) { 93 233 : passgen_error_init( 94 : error, 95 : passgen_token_parse_error_str(token_parser.state)); 96 233 : passgen_error_offset_set(error, pattern_pos_total, pattern_raw_pos); 97 233 : passgen_parser_free(&parser); 98 233 : return -1; 99 : } 100 : 101 : // make sure we are done parsing 102 13250 : if(0 != passgen_parse_finish(&parser)) { 103 3849 : passgen_error_init(error, "parsing not finished"); 104 3849 : passgen_error_offset_set(error, pattern_pos_total, pattern_raw_pos); 105 3849 : passgen_parser_free(&parser); 106 3849 : return -1; 107 : } 108 : 109 9401 : passgen_parser_free(&parser); 110 : 111 9401 : return 0; 112 : }