| /* |
| * Copyright (c) 2019-2024, Arm Limited. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| * |
| */ |
| |
| /* |
| * These functions produce random-gibberish quasi-words in a quasi-sentence. |
| * Random character streams may be conceptually sufficient, but for testing |
| * purposes, it's much easier for humans to remember and to distinguish semi- |
| * pro-nounceable gibberish like "dokwab neltiegib..." than |
| * "f7H%r^&B*5|j6@Mz>\#...". |
| */ |
| |
| #include <string> |
| #include <cstdlib> |
| |
| #include "gibberish.hpp" // shouldn't need any other project headers |
| |
| |
| /** |
| * \brief Returns a letter for random-gibberish quasi-words in a quasi-sentence. |
| * |
| * \return A letter character value. |
| * |
| */ |
| char gibberish::letter(void) |
| { |
| return 'a' + (rand() % ('z'-'a' + 1)); |
| } |
| |
| |
| /** |
| * \brief Returns a vowel for random-gibberish quasi-words in a quasi-sentence. |
| * |
| * \return A vowel character value. |
| * |
| */ |
| char gibberish::vowel(void) |
| { |
| char vowels[] = "aeiou"; |
| |
| return vowels[rand() % 5]; |
| } |
| |
| |
| /** |
| * \brief Returns a consonant for random-gibberish quasi-words in a quasi-sentence. |
| * |
| * \return A consonant character value. |
| * |
| */ |
| char gibberish::consonant(void) |
| { |
| char candidate; |
| |
| do { |
| candidate = letter(); |
| } while ( candidate == 'a' || candidate == 'e' || candidate == 'i' |
| || candidate == 'o' || candidate == 'u'); |
| return candidate; |
| } |
| |
| |
| /** |
| * \brief Appends a semi-pronounceable syllable onto a string, stopping before |
| * the end of the string, for random-gibberish quasi-words in a |
| * quasi-sentence. Returns a pointer to the next open spot in the string. |
| * |
| * \param[in] string_ptr Pointer to where to put the word. |
| * |
| * \param[in] stop Pointer to last character in quasi-sentence. |
| * |
| * \return Pointer to first character after the word. |
| * |
| */ |
| char *gibberish::syllable (char *string_ptr, char *stop) |
| { |
| char *parser; /* points into string while building it */ |
| |
| parser = string_ptr; |
| if ((rand() % 4) < 3) { |
| if (parser < stop) *parser++ = consonant(); |
| if (parser < stop) *parser++ = vowel(); |
| if (parser < stop) *parser++ = letter(); |
| } else { |
| if (parser < stop) *parser++ = vowel(); |
| if (((rand() % 4) < 1) && parser < stop) { |
| *parser++ = vowel(); |
| } |
| if (parser < stop) *parser++ = consonant(); |
| } |
| return parser; |
| } |
| |
| |
| /** |
| * \brief Appends a mostly-pronounceable quasi-word onto a quasi-sentence string, |
| * stopping before the end of the string. Returns a pointer to the next |
| * open spot in the string. |
| * |
| * \param[in] initial_cap: True if the first character should be capitalized. |
| * |
| * \param[in] string_ptr Pointer to where to put the word. |
| * |
| * \param[in] stop Pointer to last character in quasi-sentence. |
| * |
| * \return Pointer to first character after the word. |
| * |
| */ |
| char *gibberish::word (bool initial_cap, char *string_ptr, char *stop) |
| { |
| int syllable_count; |
| char *parser; /* points into string while building it */ |
| string avoid_check; |
| bool has_avoid_words; |
| do { |
| has_avoid_words = false; |
| for (syllable_count = 0, parser = string_ptr; |
| syllable_count < 4 |
| && (rand() % 5) >= syllable_count |
| && parser < stop; |
| syllable_count++) { |
| parser = syllable (parser, stop); |
| } |
| for (int i = 0; i < n_avoids; i++) { |
| avoid_check = string_ptr; |
| if (avoid[i] == avoid_check) { |
| has_avoid_words = true; |
| break; |
| } |
| } |
| if (initial_cap) { |
| *string_ptr -= 'a' - 'A'; /* more or less assumes ASCII */ |
| } |
| } while (has_avoid_words); |
| return parser; |
| } |
| |
| |
| /** |
| * \brief Creates a mostly-pronounceable, random-gibberish quasi-sentence, |
| * stopping before the end of the string. |
| * |
| * \param[in] string_ptr Pointer to beginning of string for quasi-sentence. |
| * |
| * \param[in] stop Pointer to last character in quasi-sentence. |
| * |
| */ |
| void gibberish::sentence (char *string_ptr, char *stop) |
| { |
| char *parser; /* points into string while building it */ |
| char punctuation[] = ".?!"; |
| |
| *stop = '\0'; /* null-terminate the string */ |
| --stop; |
| parser = word (capitalize, string_ptr, stop); |
| if (parser < stop) { |
| *parser++ = ' '; |
| } |
| for (; parser < stop; ) { |
| parser = word (dont_capitalize, parser, stop); |
| if (parser < stop) { |
| *parser++ = ' '; |
| } |
| } |
| parser--; |
| if (*parser == ' ') { |
| *parser = vowel(); // just to not have a blank at the end |
| } |
| *stop = punctuation[rand() % 3]; |
| } |
| |
| |
| /** |
| * \brief Chooses a gibberish-sentence length. |
| * |
| */ |
| int gibberish::pick_sentence_len (void) |
| { |
| return min_literal_data_len + (rand() % literal_data_len_span); |
| } |
| |
| |
| /** |
| * \brief Constructor for gibberish object. |
| * |
| */ |
| gibberish::gibberish (void) |
| { |
| string holder; |
| |
| for (int i = 0; i < n_avoids; i++) { |
| holder = avoid[i]; |
| for (long unsigned int j = 0; j < holder.length(); j++) { |
| holder[j] = holder[j] - 1; |
| } |
| avoid[i] = holder; |
| } |
| } |
| |
| |
| /** |
| * \brief Destructor for gibberish object. |
| * |
| */ |
| gibberish::~gibberish (void) |
| { |
| // Nothing to tear down. |
| } |