LCOV - code coverage report
Current view: top level - src - passgen.c (source / functions) Hit Total Coverage
Test: passgen-test.info Lines: 54 54 100.0 %
Date: 2024-11-15 06:04:45 Functions: 1 1 100.0 %

          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             : }

Generated by: LCOV version 1.14