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