technician1 commited on
Commit
8cd1209
·
verified ·
1 Parent(s): 117e3f3

Upload ChatIPC.cpp

Browse files
Files changed (1) hide show
  1. ChatIPC.cpp +114 -51
ChatIPC.cpp CHANGED
@@ -495,63 +495,105 @@ static const char* const scales[] = {"", "thousand", "million", "billion", "tril
495
  "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion",
496
  "octodecillion", "novemdecillion", "vigintillion", "googol"};
497
 
498
- static std::vector<std::string> digit_to_words(const std::string& s) {
499
  std::vector<std::string> words;
500
- if (s.empty()) return words;
501
 
502
- // Strip leading zeros
503
- size_t first_non_zero = s.find_first_not_of('0');
504
- if (first_non_zero == std::string::npos) {
505
- words.push_back("zero");
506
- return words;
 
 
507
  }
508
- std::string num = s.substr(first_non_zero);
509
 
510
- // If it's very large (e.g. googolplex logic), fall back to single digits to prevent overflow
511
- // and maintain semantic definitions of the numbers.
512
- if (num.length() > 69) {
513
- for (char c : num) {
514
- words.push_back(ones[c - '0']);
515
  }
516
- return words;
517
  }
518
 
519
- int scale_idx = 0;
520
- while (!num.empty()) {
521
- int chunk_len = std::min<int>(3, num.length());
522
- std::string chunk_str = num.substr(num.length() - chunk_len);
523
- num = num.substr(0, num.length() - chunk_len);
 
 
 
 
 
 
 
 
 
 
524
 
525
- int chunk = std::stoi(chunk_str);
526
- if (chunk > 0) {
527
- std::vector<std::string> chunk_words;
528
- int h = chunk / 100;
529
- int remainder = chunk % 100;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
530
 
531
- if (h > 0) {
532
- chunk_words.push_back(ones[h]);
533
- chunk_words.push_back("hundred");
534
- }
 
 
 
 
 
 
535
 
536
- if (remainder > 0) {
537
- if (remainder < 20) {
538
- chunk_words.push_back(ones[remainder]);
539
- } else {
540
- chunk_words.push_back(tens[remainder / 10]);
541
- if (remainder % 10 > 0) {
542
- chunk_words.push_back(ones[remainder % 10]);
543
  }
 
544
  }
545
  }
 
 
546
 
547
- if (scale_idx > 0 && scale_idx < static_cast<int>(sizeof(scales)/sizeof(scales[0]))) {
548
- chunk_words.push_back(scales[scale_idx]);
 
 
 
 
 
 
 
 
 
 
549
  }
550
-
551
- words.insert(words.begin(), chunk_words.begin(), chunk_words.end());
552
  }
553
- scale_idx++;
554
  }
 
555
  return words;
556
  }
557
 
@@ -565,10 +607,13 @@ static std::vector<std::string> tokenize_others(const std::string &s) {
565
  return { lower_s };
566
  }
567
 
568
- // Convert pure digits to words
569
- bool is_all_digits = !s.empty() && std::all_of(s.begin(), s.end(), [](unsigned char c) {
570
- return std::isdigit(c) != 0;
571
- });
 
 
 
572
  if (is_all_digits) {
573
  return digit_to_words(s);
574
  }
@@ -578,9 +623,15 @@ static std::vector<std::string> tokenize_others(const std::string &s) {
578
 
579
  auto flush = [&]() {
580
  if (!cur.empty()) {
581
- // Check numbers inside mixed tokens (e.g. "word123")
582
- bool cur_all_digits = std::all_of(cur.begin(), cur.end(), [](unsigned char c) { return std::isdigit(c) != 0; });
583
- if (cur_all_digits) {
 
 
 
 
 
 
584
  auto words = digit_to_words(cur);
585
  out.insert(out.end(), words.begin(), words.end());
586
  } else {
@@ -598,13 +649,25 @@ static std::vector<std::string> tokenize_others(const std::string &s) {
598
  char ch = static_cast<char>(uc);
599
 
600
  // Check for Operator/Symbol extraction
601
- if (std::ispunct(uc) || (std::isprint(uc) && !std::isalnum(uc) && !std::isspace(uc))) { flush();
 
 
 
 
 
 
 
 
 
 
 
602
  std::string sym(1, ch);
603
 
604
- // Check for double-character operators (==, <=, >=, !=, ++, --, &&, ||, <<, >>)
605
  if (i + 1 < s.size()) {
606
  unsigned char nxt_uc = static_cast<unsigned char>(s[i+1]);
607
- if (std::ispunct(nxt_uc) || (std::isprint(nxt_uc) && !std::isalnum(nxt_uc) && !std::isspace(nxt_uc))) { std::string sym2 = sym + static_cast<char>(nxt_uc);
 
608
  if (check_dictionary(sym2)) {
609
  out.push_back(sym2);
610
  ++i;
@@ -636,7 +699,7 @@ static std::vector<std::string> tokenize_others(const std::string &s) {
636
  bool digit_boundary = false;
637
  if (!cur.empty()) {
638
  unsigned char prev = static_cast<unsigned char>(s[i - 1]);
639
- bool prev_digit = std::isdigit(prev) != 0;
640
  bool curr_digit = std::isdigit(uc) != 0;
641
  if (prev_digit != curr_digit) {
642
  digit_boundary = true;
 
495
  "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion",
496
  "octodecillion", "novemdecillion", "vigintillion", "googol"};
497
 
498
+ static std::vector<std::string> digit_to_words(const std::string& input_s) {
499
  std::vector<std::string> words;
500
+ if (input_s.empty()) return words;
501
 
502
+ // Split the number into integer and fractional parts
503
+ std::string int_part = input_s;
504
+ std::string frac_part = "";
505
+ size_t dot_pos = input_s.find('.');
506
+ if (dot_pos != std::string::npos) {
507
+ int_part = input_s.substr(0, dot_pos);
508
+ frac_part = input_s.substr(dot_pos + 1);
509
  }
 
510
 
511
+ // Clean the integer part by removing commas
512
+ std::string s;
513
+ for (char c : int_part) {
514
+ if (std::isdigit(static_cast<unsigned char>(c))) {
515
+ s.push_back(c);
516
  }
 
517
  }
518
 
519
+ // Process the integer part
520
+ if (s.empty()) {
521
+ // If there are no integer digits, ensure there are fractional digits before parsing
522
+ bool has_frac_digits = false;
523
+ for (char c : frac_part) {
524
+ if (std::isdigit(static_cast<unsigned char>(c))) has_frac_digits = true;
525
+ }
526
+ if (!has_frac_digits) return words;
527
+ words.push_back("zero");
528
+ } else {
529
+ size_t first_non_zero = s.find_first_not_of('0');
530
+ if (first_non_zero == std::string::npos) {
531
+ words.push_back("zero");
532
+ } else {
533
+ std::string num = s.substr(first_non_zero);
534
 
535
+ // Fallback for extremely large numbers to prevent overflow
536
+ if (num.length() > 69) {
537
+ for (char c : num) {
538
+ words.push_back(ones[c - '0']);
539
+ }
540
+ } else {
541
+ int scale_idx = 0;
542
+ while (!num.empty()) {
543
+ int chunk_len = std::min<int>(3, num.length());
544
+ std::string chunk_str = num.substr(num.length() - chunk_len);
545
+ num = num.substr(0, num.length() - chunk_len);
546
+
547
+ int chunk = std::stoi(chunk_str);
548
+ if (chunk > 0) {
549
+ std::vector<std::string> chunk_words;
550
+ int h = chunk / 100;
551
+ int remainder = chunk % 100;
552
+
553
+ if (h > 0) {
554
+ chunk_words.push_back(ones[h]);
555
+ chunk_words.push_back("hundred");
556
+ }
557
 
558
+ if (remainder > 0) {
559
+ if (remainder < 20) {
560
+ chunk_words.push_back(ones[remainder]);
561
+ } else {
562
+ chunk_words.push_back(tens[remainder / 10]);
563
+ if (remainder % 10 > 0) {
564
+ chunk_words.push_back(ones[remainder % 10]);
565
+ }
566
+ }
567
+ }
568
 
569
+ if (scale_idx > 0 && scale_idx < static_cast<int>(sizeof(scales)/sizeof(scales[0]))) {
570
+ chunk_words.push_back(scales[scale_idx]);
571
+ }
572
+
573
+ words.insert(words.begin(), chunk_words.begin(), chunk_words.end());
 
 
574
  }
575
+ scale_idx++;
576
  }
577
  }
578
+ }
579
+ }
580
 
581
+ // Process the fractional part
582
+ if (!frac_part.empty()) {
583
+ bool has_frac_digits = false;
584
+ for (char c : frac_part) {
585
+ if (std::isdigit(static_cast<unsigned char>(c))) has_frac_digits = true;
586
+ }
587
+ if (has_frac_digits) {
588
+ words.push_back("point");
589
+ for (char c : frac_part) {
590
+ if (std::isdigit(static_cast<unsigned char>(c))) {
591
+ words.push_back(ones[c - '0']);
592
+ }
593
  }
 
 
594
  }
 
595
  }
596
+
597
  return words;
598
  }
599
 
 
607
  return { lower_s };
608
  }
609
 
610
+ // Check if the entire string is a formatted number (pure digits, commas, and dots)
611
+ auto is_num_char = [](unsigned char c) {
612
+ return std::isdigit(c) != 0 || c == ',' || c == '.';
613
+ };
614
+ bool is_all_digits = !s.empty() && std::all_of(s.begin(), s.end(), is_num_char) &&
615
+ std::any_of(s.begin(), s.end(), [](unsigned char c) { return std::isdigit(c) != 0; });
616
+
617
  if (is_all_digits) {
618
  return digit_to_words(s);
619
  }
 
623
 
624
  auto flush = [&]() {
625
  if (!cur.empty()) {
626
+ // Check numbers inside mixed tokens (e.g. "word1,234.56")
627
+ bool cur_all_digits = std::all_of(cur.begin(), cur.end(), [](unsigned char c) {
628
+ return std::isdigit(c) != 0 || c == ',' || c == '.';
629
+ });
630
+ bool has_digits = std::any_of(cur.begin(), cur.end(), [](unsigned char c) {
631
+ return std::isdigit(c) != 0;
632
+ });
633
+
634
+ if (cur_all_digits && has_digits) {
635
  auto words = digit_to_words(cur);
636
  out.insert(out.end(), words.begin(), words.end());
637
  } else {
 
649
  char ch = static_cast<char>(uc);
650
 
651
  // Check for Operator/Symbol extraction
652
+ if (std::ispunct(uc) || (std::isprint(uc) && !std::isalnum(uc) && !std::isspace(uc))) {
653
+
654
+ // Bypass regular punctuation extraction inside a formatted number
655
+ if ((ch == ',' || ch == '.') &&
656
+ !cur.empty() &&
657
+ (std::isdigit(static_cast<unsigned char>(cur.back())) != 0 || cur.back() == ',' || cur.back() == '.') &&
658
+ (i + 1 < s.size()) && std::isdigit(static_cast<unsigned char>(s[i+1])) != 0) {
659
+ cur.push_back(ch);
660
+ continue;
661
+ }
662
+
663
+ flush();
664
  std::string sym(1, ch);
665
 
666
+ // Check for double-character operators
667
  if (i + 1 < s.size()) {
668
  unsigned char nxt_uc = static_cast<unsigned char>(s[i+1]);
669
+ if (std::ispunct(nxt_uc) || (std::isprint(nxt_uc) && !std::isalnum(nxt_uc) && !std::isspace(nxt_uc))) {
670
+ std::string sym2 = sym + static_cast<char>(nxt_uc);
671
  if (check_dictionary(sym2)) {
672
  out.push_back(sym2);
673
  ++i;
 
699
  bool digit_boundary = false;
700
  if (!cur.empty()) {
701
  unsigned char prev = static_cast<unsigned char>(s[i - 1]);
702
+ bool prev_digit = (std::isdigit(prev) != 0) || prev == ',' || prev == '.';
703
  bool curr_digit = std::isdigit(uc) != 0;
704
  if (prev_digit != curr_digit) {
705
  digit_boundary = true;