blob: 436ace4119f9a2b013ae3822752c47360743fedc [file] [log] [blame]
Karl Zhang3de5ab12021-05-31 11:45:48 +08001/*
Nik Dewallybacae6c2024-07-30 16:58:14 +01002 * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
Karl Zhang3de5ab12021-05-31 11:45:48 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8/*
9 * These functions produce random-gibberish quasi-words in a quasi-sentence.
10 * Random character streams may be conceptually sufficient, but for testing
11 * purposes, it's much easier for humans to remember and to distinguish semi-
12 * pro-nounceable gibberish like "dokwab neltiegib..." than
13 * "f7H%r^&B*5|j6@Mz>\#...".
14 */
15
16#include <string>
Nik Dewallybacae6c2024-07-30 16:58:14 +010017#include <cstdlib>
Karl Zhang3de5ab12021-05-31 11:45:48 +080018
19#include "gibberish.hpp" // shouldn't need any other project headers
20
21
22/**
23 * \brief Returns a letter for random-gibberish quasi-words in a quasi-sentence.
24 *
25 * \return A letter character value.
26 *
27 */
28char gibberish::letter(void)
29{
30 return 'a' + (rand() % ('z'-'a' + 1));
31}
32
33
34/**
35 * \brief Returns a vowel for random-gibberish quasi-words in a quasi-sentence.
36 *
37 * \return A vowel character value.
38 *
39 */
40char gibberish::vowel(void)
41{
42 char vowels[] = "aeiou";
43
44 return vowels[rand() % 5];
45}
46
47
48/**
49 * \brief Returns a consonant for random-gibberish quasi-words in a quasi-sentence.
50 *
51 * \return A consonant character value.
52 *
53 */
54char gibberish::consonant(void)
55{
56 char candidate;
57
58 do {
59 candidate = letter();
60 } while ( candidate == 'a' || candidate == 'e' || candidate == 'i'
61 || candidate == 'o' || candidate == 'u');
62 return candidate;
63}
64
65
66/**
67 * \brief Appends a semi-pronounceable syllable onto a string, stopping before
68 * the end of the string, for random-gibberish quasi-words in a
69 * quasi-sentence. Returns a pointer to the next open spot in the string.
70 *
71 * \param[in] string_ptr Pointer to where to put the word.
72 *
73 * \param[in] stop Pointer to last character in quasi-sentence.
74 *
75 * \return Pointer to first character after the word.
76 *
77 */
78char *gibberish::syllable (char *string_ptr, char *stop)
79{
80 char *parser; /* points into string while building it */
81
82 parser = string_ptr;
83 if ((rand() % 4) < 3) {
84 if (parser < stop) *parser++ = consonant();
85 if (parser < stop) *parser++ = vowel();
86 if (parser < stop) *parser++ = letter();
87 } else {
88 if (parser < stop) *parser++ = vowel();
89 if (((rand() % 4) < 1) && parser < stop) {
90 *parser++ = vowel();
91 }
92 if (parser < stop) *parser++ = consonant();
93 }
94 return parser;
95}
96
97
98/**
99 * \brief Appends a mostly-pronounceable quasi-word onto a quasi-sentence string,
100 * stopping before the end of the string. Returns a pointer to the next
101 * open spot in the string.
102 *
103 * \param[in] initial_cap: True if the first character should be capitalized.
104 *
105 * \param[in] string_ptr Pointer to where to put the word.
106 *
107 * \param[in] stop Pointer to last character in quasi-sentence.
108 *
109 * \return Pointer to first character after the word.
110 *
111 */
112char *gibberish::word (bool initial_cap, char *string_ptr, char *stop)
113{
114 int syllable_count;
115 char *parser; /* points into string while building it */
116 string avoid_check;
117 bool has_avoid_words;
118 do {
119 has_avoid_words = false;
120 for (syllable_count = 0, parser = string_ptr;
121 syllable_count < 4
122 && (rand() % 5) >= syllable_count
123 && parser < stop;
124 syllable_count++) {
125 parser = syllable (parser, stop);
126 }
127 for (int i = 0; i < n_avoids; i++) {
128 avoid_check = string_ptr;
129 if (avoid[i] == avoid_check) {
130 has_avoid_words = true;
131 break;
132 }
133 }
134 if (initial_cap) {
135 *string_ptr -= 'a' - 'A'; /* more or less assumes ASCII */
136 }
137 } while (has_avoid_words);
138 return parser;
139}
140
141
142/**
143 * \brief Creates a mostly-pronounceable, random-gibberish quasi-sentence,
144 * stopping before the end of the string.
145 *
146 * \param[in] string_ptr Pointer to beginning of string for quasi-sentence.
147 *
148 * \param[in] stop Pointer to last character in quasi-sentence.
149 *
150 */
151void gibberish::sentence (char *string_ptr, char *stop)
152{
153 char *parser; /* points into string while building it */
154 char punctuation[] = ".?!";
155
156 *stop = '\0'; /* null-terminate the string */
157 --stop;
158 parser = word (capitalize, string_ptr, stop);
159 if (parser < stop) {
160 *parser++ = ' ';
161 }
162 for (; parser < stop; ) {
163 parser = word (dont_capitalize, parser, stop);
164 if (parser < stop) {
165 *parser++ = ' ';
166 }
167 }
168 parser--;
169 if (*parser == ' ') {
170 *parser = vowel(); // just to not have a blank at the end
171 }
172 *stop = punctuation[rand() % 3];
173}
174
175
176/**
177 * \brief Chooses a gibberish-sentence length.
178 *
179 */
180int gibberish::pick_sentence_len (void)
181{
182 return min_literal_data_len + (rand() % literal_data_len_span);
183}
184
185
186/**
187 * \brief Constructor for gibberish object.
188 *
189 */
190gibberish::gibberish (void)
191{
192 string holder;
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200193
Karl Zhang3de5ab12021-05-31 11:45:48 +0800194 for (int i = 0; i < n_avoids; i++) {
195 holder = avoid[i];
196 for (long unsigned int j = 0; j < holder.length(); j++) {
197 holder[j] = holder[j] - 1;
198 }
199 avoid[i] = holder;
200 }
201}
202
203
204/**
205 * \brief Destructor for gibberish object.
206 *
207 */
208gibberish::~gibberish (void)
209{
210 // Nothing to tear down.
211}