xref: /aosp_15_r20/external/lz4/programs/lorem.c (revision 27162e4e17433d5aa7cb38e7b6a433a09405fc7f)
1*27162e4eSAndroid Build Coastguard Worker /*
2*27162e4eSAndroid Build Coastguard Worker     lorem.c - lorem ipsum generator
3*27162e4eSAndroid Build Coastguard Worker     Copyright (C) Yann Collet 2024
4*27162e4eSAndroid Build Coastguard Worker 
5*27162e4eSAndroid Build Coastguard Worker     GPL v2 License
6*27162e4eSAndroid Build Coastguard Worker 
7*27162e4eSAndroid Build Coastguard Worker     This program is free software; you can redistribute it and/or modify
8*27162e4eSAndroid Build Coastguard Worker     it under the terms of the GNU General Public License as published by
9*27162e4eSAndroid Build Coastguard Worker     the Free Software Foundation; either version 2 of the License, or
10*27162e4eSAndroid Build Coastguard Worker     (at your option) any later version.
11*27162e4eSAndroid Build Coastguard Worker 
12*27162e4eSAndroid Build Coastguard Worker     This program is distributed in the hope that it will be useful,
13*27162e4eSAndroid Build Coastguard Worker     but WITHOUT ANY WARRANTY; without even the implied warranty of
14*27162e4eSAndroid Build Coastguard Worker     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*27162e4eSAndroid Build Coastguard Worker     GNU General Public License for more details.
16*27162e4eSAndroid Build Coastguard Worker 
17*27162e4eSAndroid Build Coastguard Worker     You should have received a copy of the GNU General Public License along
18*27162e4eSAndroid Build Coastguard Worker     with this program; if not, write to the Free Software Foundation, Inc.,
19*27162e4eSAndroid Build Coastguard Worker     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20*27162e4eSAndroid Build Coastguard Worker 
21*27162e4eSAndroid Build Coastguard Worker     You can contact the author at :
22*27162e4eSAndroid Build Coastguard Worker    - LZ4 source repository : https://github.com/lz4/lz4
23*27162e4eSAndroid Build Coastguard Worker    - Public forum : https://groups.google.com/forum/#!forum/lz4c
24*27162e4eSAndroid Build Coastguard Worker */
25*27162e4eSAndroid Build Coastguard Worker 
26*27162e4eSAndroid Build Coastguard Worker /* Implementation notes:
27*27162e4eSAndroid Build Coastguard Worker  *
28*27162e4eSAndroid Build Coastguard Worker  * This is a very simple lorem ipsum generator
29*27162e4eSAndroid Build Coastguard Worker  * which features a static list of words
30*27162e4eSAndroid Build Coastguard Worker  * and print them one after another randomly
31*27162e4eSAndroid Build Coastguard Worker  * with a fake sentence / paragraph structure.
32*27162e4eSAndroid Build Coastguard Worker  *
33*27162e4eSAndroid Build Coastguard Worker  * The goal is to generate a printable text
34*27162e4eSAndroid Build Coastguard Worker  * that can be used to fake a text compression scenario.
35*27162e4eSAndroid Build Coastguard Worker  * The resulting compression / ratio curve of the lorem ipsum generator
36*27162e4eSAndroid Build Coastguard Worker  * is more satisfying than the previous statistical generator,
37*27162e4eSAndroid Build Coastguard Worker  * which was initially designed for entropy compression,
38*27162e4eSAndroid Build Coastguard Worker  * and lacks a regularity more representative of text.
39*27162e4eSAndroid Build Coastguard Worker  *
40*27162e4eSAndroid Build Coastguard Worker  * The compression ratio achievable on the generated lorem ipsum
41*27162e4eSAndroid Build Coastguard Worker  * is still a bit too good, presumably because the dictionary is a bit too
42*27162e4eSAndroid Build Coastguard Worker  * small. It would be possible to create some more complex scheme, notably by
43*27162e4eSAndroid Build Coastguard Worker  * enlarging the dictionary with a word generator, and adding grammatical rules
44*27162e4eSAndroid Build Coastguard Worker  * (composition) and syntax rules. But that's probably overkill for the intended
45*27162e4eSAndroid Build Coastguard Worker  * goal.
46*27162e4eSAndroid Build Coastguard Worker  */
47*27162e4eSAndroid Build Coastguard Worker 
48*27162e4eSAndroid Build Coastguard Worker #include "lorem.h"
49*27162e4eSAndroid Build Coastguard Worker #include <assert.h>
50*27162e4eSAndroid Build Coastguard Worker #include <limits.h> /* INT_MAX */
51*27162e4eSAndroid Build Coastguard Worker #include <stdlib.h> /* malloc, abort */
52*27162e4eSAndroid Build Coastguard Worker #include <string.h> /* memcpy */
53*27162e4eSAndroid Build Coastguard Worker 
54*27162e4eSAndroid Build Coastguard Worker /* Define the word pool
55*27162e4eSAndroid Build Coastguard Worker  * Note: all words must have a len <= 16 */
56*27162e4eSAndroid Build Coastguard Worker static const char* kWords[] = {
57*27162e4eSAndroid Build Coastguard Worker     "lorem",        "ipsum",      "dolor",       "sit",          "amet",
58*27162e4eSAndroid Build Coastguard Worker     "consectetur",  "adipiscing", "elit",        "sed",          "do",
59*27162e4eSAndroid Build Coastguard Worker     "eiusmod",      "tempor",     "incididunt",  "ut",           "labore",
60*27162e4eSAndroid Build Coastguard Worker     "et",           "dolore",     "magna",       "aliqua",       "dis",
61*27162e4eSAndroid Build Coastguard Worker     "lectus",       "vestibulum", "mattis",      "ullamcorper",  "velit",
62*27162e4eSAndroid Build Coastguard Worker     "commodo",      "a",          "lacus",       "arcu",         "magnis",
63*27162e4eSAndroid Build Coastguard Worker     "parturient",   "montes",     "nascetur",    "ridiculus",    "mus",
64*27162e4eSAndroid Build Coastguard Worker     "mauris",       "nulla",      "malesuada",   "pellentesque", "eget",
65*27162e4eSAndroid Build Coastguard Worker     "gravida",      "in",         "dictum",      "non",          "erat",
66*27162e4eSAndroid Build Coastguard Worker     "nam",          "voluptat",   "maecenas",    "blandit",      "aliquam",
67*27162e4eSAndroid Build Coastguard Worker     "etiam",        "enim",       "lobortis",    "scelerisque",  "fermentum",
68*27162e4eSAndroid Build Coastguard Worker     "dui",          "faucibus",   "ornare",      "at",           "elementum",
69*27162e4eSAndroid Build Coastguard Worker     "eu",           "facilisis",  "odio",        "morbi",        "quis",
70*27162e4eSAndroid Build Coastguard Worker     "eros",         "donec",      "ac",          "orci",         "purus",
71*27162e4eSAndroid Build Coastguard Worker     "turpis",       "cursus",     "leo",         "vel",          "porta",
72*27162e4eSAndroid Build Coastguard Worker     "consequat",    "interdum",   "varius",      "vulputate",    "aliquet",
73*27162e4eSAndroid Build Coastguard Worker     "pharetra",     "nunc",       "auctor",      "urna",         "id",
74*27162e4eSAndroid Build Coastguard Worker     "metus",        "viverra",    "nibh",        "cras",         "mi",
75*27162e4eSAndroid Build Coastguard Worker     "unde",         "omnis",      "iste",        "natus",        "error",
76*27162e4eSAndroid Build Coastguard Worker     "perspiciatis", "voluptatem", "accusantium", "doloremque",   "laudantium",
77*27162e4eSAndroid Build Coastguard Worker     "totam",        "rem",        "aperiam",     "eaque",        "ipsa",
78*27162e4eSAndroid Build Coastguard Worker     "quae",         "ab",         "illo",        "inventore",    "veritatis",
79*27162e4eSAndroid Build Coastguard Worker     "quasi",        "architecto", "beatae",      "vitae",        "dicta",
80*27162e4eSAndroid Build Coastguard Worker     "sunt",         "explicabo",  "nemo",        "ipsam",        "quia",
81*27162e4eSAndroid Build Coastguard Worker     "voluptas",     "aspernatur", "aut",         "odit",         "fugit",
82*27162e4eSAndroid Build Coastguard Worker     "consequuntur", "magni",      "dolores",     "eos",          "qui",
83*27162e4eSAndroid Build Coastguard Worker     "ratione",      "sequi",      "nesciunt",    "neque",        "porro",
84*27162e4eSAndroid Build Coastguard Worker     "quisquam",     "est",        "dolorem",     "adipisci",     "numquam",
85*27162e4eSAndroid Build Coastguard Worker     "eius",         "modi",       "tempora",     "incidunt",     "magnam",
86*27162e4eSAndroid Build Coastguard Worker     "quaerat",      "ad",         "minima",      "veniam",       "nostrum",
87*27162e4eSAndroid Build Coastguard Worker     "ullam",        "corporis",   "suscipit",    "laboriosam",   "nisi",
88*27162e4eSAndroid Build Coastguard Worker     "aliquid",      "ex",         "ea",          "commodi",      "consequatur",
89*27162e4eSAndroid Build Coastguard Worker     "autem",        "eum",        "iure",        "voluptate",    "esse",
90*27162e4eSAndroid Build Coastguard Worker     "quam",         "nihil",      "molestiae",   "illum",        "fugiat",
91*27162e4eSAndroid Build Coastguard Worker     "quo",          "pariatur",   "vero",        "accusamus",    "iusto",
92*27162e4eSAndroid Build Coastguard Worker     "dignissimos",  "ducimus",    "blanditiis",  "praesentium",  "voluptatum",
93*27162e4eSAndroid Build Coastguard Worker     "deleniti",     "atque",      "corrupti",    "quos",         "quas",
94*27162e4eSAndroid Build Coastguard Worker     "molestias",    "excepturi",  "sint",        "occaecati",    "cupiditate",
95*27162e4eSAndroid Build Coastguard Worker     "provident",    "similique",  "culpa",       "officia",      "deserunt",
96*27162e4eSAndroid Build Coastguard Worker     "mollitia",     "animi",      "laborum",     "dolorum",      "fuga",
97*27162e4eSAndroid Build Coastguard Worker     "harum",        "quidem",     "rerum",       "facilis",      "expedita",
98*27162e4eSAndroid Build Coastguard Worker     "distinctio",   "libero",     "tempore",     "cum",          "soluta",
99*27162e4eSAndroid Build Coastguard Worker     "nobis",        "eligendi",   "optio",       "cumque",       "impedit",
100*27162e4eSAndroid Build Coastguard Worker     "minus",        "quod",       "maxime",      "placeat",      "facere",
101*27162e4eSAndroid Build Coastguard Worker     "possimus",     "assumenda",  "repellendus", "temporibus",   "quibusdam",
102*27162e4eSAndroid Build Coastguard Worker     "officiis",     "debitis",    "saepe",       "eveniet",      "voluptates",
103*27162e4eSAndroid Build Coastguard Worker     "repudiandae",  "recusandae", "itaque",      "earum",        "hic",
104*27162e4eSAndroid Build Coastguard Worker     "tenetur",      "sapiente",   "delectus",    "reiciendis",   "cillum",
105*27162e4eSAndroid Build Coastguard Worker     "maiores",      "alias",      "perferendis", "doloribus",    "asperiores",
106*27162e4eSAndroid Build Coastguard Worker     "repellat",     "minim",      "nostrud",     "exercitation", "ullamco",
107*27162e4eSAndroid Build Coastguard Worker     "laboris",      "aliquip",    "duis",        "aute",         "irure",
108*27162e4eSAndroid Build Coastguard Worker };
109*27162e4eSAndroid Build Coastguard Worker #define KNBWORDS (sizeof(kWords) / sizeof(kWords[0]))
110*27162e4eSAndroid Build Coastguard Worker static const unsigned kNbWords = KNBWORDS;
111*27162e4eSAndroid Build Coastguard Worker 
112*27162e4eSAndroid Build Coastguard Worker static const char* g_words[KNBWORDS] = { NULL };
113*27162e4eSAndroid Build Coastguard Worker static unsigned g_wordLen[KNBWORDS] = {0};
114*27162e4eSAndroid Build Coastguard Worker static char* g_wordBuffer = NULL;
115*27162e4eSAndroid Build Coastguard Worker 
116*27162e4eSAndroid Build Coastguard Worker /* simple 1-dimension distribution, based on word's length, favors small words
117*27162e4eSAndroid Build Coastguard Worker  */
118*27162e4eSAndroid Build Coastguard Worker static const int kWeights[]      = { 0, 8, 6, 4, 3, 2 };
119*27162e4eSAndroid Build Coastguard Worker static const unsigned kNbWeights = sizeof(kWeights) / sizeof(kWeights[0]);
120*27162e4eSAndroid Build Coastguard Worker 
121*27162e4eSAndroid Build Coastguard Worker #define DISTRIB_SIZE_MAX 650
122*27162e4eSAndroid Build Coastguard Worker static int g_distrib[DISTRIB_SIZE_MAX] = { 0 };
123*27162e4eSAndroid Build Coastguard Worker static unsigned g_distribCount         = 0;
124*27162e4eSAndroid Build Coastguard Worker 
countFreqs(const unsigned wordLen[],size_t nbWords,const int * weights,unsigned long nbWeights)125*27162e4eSAndroid Build Coastguard Worker static void countFreqs(
126*27162e4eSAndroid Build Coastguard Worker         const unsigned wordLen[],
127*27162e4eSAndroid Build Coastguard Worker         size_t nbWords,
128*27162e4eSAndroid Build Coastguard Worker         const int* weights,
129*27162e4eSAndroid Build Coastguard Worker         unsigned long nbWeights)
130*27162e4eSAndroid Build Coastguard Worker {
131*27162e4eSAndroid Build Coastguard Worker     unsigned total = 0;
132*27162e4eSAndroid Build Coastguard Worker     size_t w;
133*27162e4eSAndroid Build Coastguard Worker     for (w = 0; w < nbWords; w++) {
134*27162e4eSAndroid Build Coastguard Worker         size_t len = wordLen[w];
135*27162e4eSAndroid Build Coastguard Worker         int lmax;
136*27162e4eSAndroid Build Coastguard Worker         if (len >= nbWeights)
137*27162e4eSAndroid Build Coastguard Worker             len = nbWeights - 1;
138*27162e4eSAndroid Build Coastguard Worker         lmax = weights[len];
139*27162e4eSAndroid Build Coastguard Worker         total += (unsigned)lmax;
140*27162e4eSAndroid Build Coastguard Worker     }
141*27162e4eSAndroid Build Coastguard Worker     g_distribCount = total;
142*27162e4eSAndroid Build Coastguard Worker     assert(g_distribCount <= DISTRIB_SIZE_MAX);
143*27162e4eSAndroid Build Coastguard Worker }
144*27162e4eSAndroid Build Coastguard Worker 
init_word_len(const char * words[],size_t nbWords)145*27162e4eSAndroid Build Coastguard Worker static void init_word_len(
146*27162e4eSAndroid Build Coastguard Worker         const char* words[],
147*27162e4eSAndroid Build Coastguard Worker         size_t nbWords)
148*27162e4eSAndroid Build Coastguard Worker {
149*27162e4eSAndroid Build Coastguard Worker     size_t n;
150*27162e4eSAndroid Build Coastguard Worker     assert(words != NULL);
151*27162e4eSAndroid Build Coastguard Worker     for (n=0; n<nbWords; n++) {
152*27162e4eSAndroid Build Coastguard Worker         assert(words[n] != NULL);
153*27162e4eSAndroid Build Coastguard Worker         assert(strlen(words[n]) < 256);
154*27162e4eSAndroid Build Coastguard Worker         g_wordLen[n] = (unsigned char)strlen(words[n]);
155*27162e4eSAndroid Build Coastguard Worker     }
156*27162e4eSAndroid Build Coastguard Worker 
157*27162e4eSAndroid Build Coastguard Worker }
158*27162e4eSAndroid Build Coastguard Worker 
sumLen(const unsigned * sizes,size_t s)159*27162e4eSAndroid Build Coastguard Worker static size_t sumLen(const unsigned* sizes, size_t s)
160*27162e4eSAndroid Build Coastguard Worker {
161*27162e4eSAndroid Build Coastguard Worker     size_t total = 0;
162*27162e4eSAndroid Build Coastguard Worker     size_t n;
163*27162e4eSAndroid Build Coastguard Worker     assert(sizes != NULL);
164*27162e4eSAndroid Build Coastguard Worker     for (n=0; n<s; n++) {
165*27162e4eSAndroid Build Coastguard Worker         total += sizes[n];
166*27162e4eSAndroid Build Coastguard Worker     }
167*27162e4eSAndroid Build Coastguard Worker     return total;
168*27162e4eSAndroid Build Coastguard Worker }
169*27162e4eSAndroid Build Coastguard Worker 
init_word_buffer(void)170*27162e4eSAndroid Build Coastguard Worker static void init_word_buffer(void)
171*27162e4eSAndroid Build Coastguard Worker {
172*27162e4eSAndroid Build Coastguard Worker     size_t n;
173*27162e4eSAndroid Build Coastguard Worker     size_t const bufSize = sumLen(g_wordLen, kNbWords) + 16;
174*27162e4eSAndroid Build Coastguard Worker     char* ptr;
175*27162e4eSAndroid Build Coastguard Worker     assert(g_wordBuffer == NULL);
176*27162e4eSAndroid Build Coastguard Worker     g_wordBuffer = (char*)calloc(1, bufSize);
177*27162e4eSAndroid Build Coastguard Worker     if (g_wordBuffer == NULL) abort();
178*27162e4eSAndroid Build Coastguard Worker     ptr = g_wordBuffer;
179*27162e4eSAndroid Build Coastguard Worker     for (n=0; n<kNbWords; n++) {
180*27162e4eSAndroid Build Coastguard Worker         memcpy(ptr, kWords[n], g_wordLen[n]);
181*27162e4eSAndroid Build Coastguard Worker         g_words[n] = ptr;
182*27162e4eSAndroid Build Coastguard Worker         ptr += g_wordLen[n];
183*27162e4eSAndroid Build Coastguard Worker     }
184*27162e4eSAndroid Build Coastguard Worker }
185*27162e4eSAndroid Build Coastguard Worker 
init_word_distrib(const unsigned wordLen[],size_t nbWords,const int * weights,unsigned long nbWeights)186*27162e4eSAndroid Build Coastguard Worker static void init_word_distrib(
187*27162e4eSAndroid Build Coastguard Worker         const unsigned wordLen[],
188*27162e4eSAndroid Build Coastguard Worker         size_t nbWords,
189*27162e4eSAndroid Build Coastguard Worker         const int* weights,
190*27162e4eSAndroid Build Coastguard Worker         unsigned long nbWeights)
191*27162e4eSAndroid Build Coastguard Worker {
192*27162e4eSAndroid Build Coastguard Worker     size_t w, d = 0;
193*27162e4eSAndroid Build Coastguard Worker     countFreqs(wordLen, nbWords, weights, nbWeights);
194*27162e4eSAndroid Build Coastguard Worker     for (w = 0; w < nbWords; w++) {
195*27162e4eSAndroid Build Coastguard Worker         size_t len = wordLen[w];
196*27162e4eSAndroid Build Coastguard Worker         int l, lmax;
197*27162e4eSAndroid Build Coastguard Worker         if (len >= nbWeights)
198*27162e4eSAndroid Build Coastguard Worker             len = nbWeights - 1;
199*27162e4eSAndroid Build Coastguard Worker         lmax = weights[len];
200*27162e4eSAndroid Build Coastguard Worker         for (l = 0; l < lmax; l++) {
201*27162e4eSAndroid Build Coastguard Worker             g_distrib[d++] = (int)w;
202*27162e4eSAndroid Build Coastguard Worker         }
203*27162e4eSAndroid Build Coastguard Worker     }
204*27162e4eSAndroid Build Coastguard Worker }
205*27162e4eSAndroid Build Coastguard Worker 
206*27162e4eSAndroid Build Coastguard Worker /* Note: this unit only works when invoked sequentially.
207*27162e4eSAndroid Build Coastguard Worker  * No concurrent access is allowed */
208*27162e4eSAndroid Build Coastguard Worker static char* g_ptr         = NULL;
209*27162e4eSAndroid Build Coastguard Worker static size_t g_nbChars    = 0;
210*27162e4eSAndroid Build Coastguard Worker static size_t g_maxChars   = 10000000;
211*27162e4eSAndroid Build Coastguard Worker static unsigned g_randRoot = 0;
212*27162e4eSAndroid Build Coastguard Worker 
213*27162e4eSAndroid Build Coastguard Worker #define RDG_rotl32(x, r) ((x << r) | (x >> (32 - r)))
LOREM_rand(unsigned range)214*27162e4eSAndroid Build Coastguard Worker static unsigned LOREM_rand(unsigned range)
215*27162e4eSAndroid Build Coastguard Worker {
216*27162e4eSAndroid Build Coastguard Worker     static const unsigned prime1 = 2654435761U;
217*27162e4eSAndroid Build Coastguard Worker     static const unsigned prime2 = 2246822519U;
218*27162e4eSAndroid Build Coastguard Worker     unsigned rand32              = g_randRoot;
219*27162e4eSAndroid Build Coastguard Worker     rand32 *= prime1;
220*27162e4eSAndroid Build Coastguard Worker     rand32 ^= prime2;
221*27162e4eSAndroid Build Coastguard Worker     rand32     = RDG_rotl32(rand32, 13);
222*27162e4eSAndroid Build Coastguard Worker     g_randRoot = rand32;
223*27162e4eSAndroid Build Coastguard Worker     return (unsigned)(((unsigned long long)rand32 * range) >> 32);
224*27162e4eSAndroid Build Coastguard Worker }
225*27162e4eSAndroid Build Coastguard Worker 
writeLastCharacters(void)226*27162e4eSAndroid Build Coastguard Worker static void writeLastCharacters(void)
227*27162e4eSAndroid Build Coastguard Worker {
228*27162e4eSAndroid Build Coastguard Worker     size_t lastChars = g_maxChars - g_nbChars;
229*27162e4eSAndroid Build Coastguard Worker     assert(g_maxChars >= g_nbChars);
230*27162e4eSAndroid Build Coastguard Worker     if (lastChars == 0)
231*27162e4eSAndroid Build Coastguard Worker         return;
232*27162e4eSAndroid Build Coastguard Worker     g_ptr[g_nbChars++] = '.';
233*27162e4eSAndroid Build Coastguard Worker     if (lastChars > 2) {
234*27162e4eSAndroid Build Coastguard Worker         memset(g_ptr + g_nbChars, ' ', lastChars - 2);
235*27162e4eSAndroid Build Coastguard Worker     }
236*27162e4eSAndroid Build Coastguard Worker     if (lastChars > 1) {
237*27162e4eSAndroid Build Coastguard Worker         g_ptr[g_maxChars - 1] = '\n';
238*27162e4eSAndroid Build Coastguard Worker     }
239*27162e4eSAndroid Build Coastguard Worker     g_nbChars = g_maxChars;
240*27162e4eSAndroid Build Coastguard Worker }
241*27162e4eSAndroid Build Coastguard Worker 
generateLastWord(const char * word,size_t wordLen,int upCase)242*27162e4eSAndroid Build Coastguard Worker static void generateLastWord(const char* word, size_t wordLen, int upCase)
243*27162e4eSAndroid Build Coastguard Worker {
244*27162e4eSAndroid Build Coastguard Worker     if (g_nbChars + wordLen + 2 > g_maxChars) {
245*27162e4eSAndroid Build Coastguard Worker         writeLastCharacters();
246*27162e4eSAndroid Build Coastguard Worker         return;
247*27162e4eSAndroid Build Coastguard Worker     }
248*27162e4eSAndroid Build Coastguard Worker     memcpy(g_ptr + g_nbChars, word, wordLen);
249*27162e4eSAndroid Build Coastguard Worker     if (upCase) {
250*27162e4eSAndroid Build Coastguard Worker         static const char toUp = 'A' - 'a';
251*27162e4eSAndroid Build Coastguard Worker         g_ptr[g_nbChars]       = (char)(g_ptr[g_nbChars] + toUp);
252*27162e4eSAndroid Build Coastguard Worker     }
253*27162e4eSAndroid Build Coastguard Worker     g_nbChars += wordLen;
254*27162e4eSAndroid Build Coastguard Worker     writeLastCharacters();
255*27162e4eSAndroid Build Coastguard Worker }
256*27162e4eSAndroid Build Coastguard Worker 
257*27162e4eSAndroid Build Coastguard Worker #define MAX(a,b)  ((a)<(b)?(b):(a))
generateWord(const char * word,size_t wordLen,const char * separator,size_t sepLen,int upCase)258*27162e4eSAndroid Build Coastguard Worker static void generateWord(const char* word, size_t wordLen, const char* separator, size_t sepLen, int upCase)
259*27162e4eSAndroid Build Coastguard Worker {
260*27162e4eSAndroid Build Coastguard Worker     size_t const wlen = MAX(16, wordLen + 2);
261*27162e4eSAndroid Build Coastguard Worker     if (g_nbChars + wlen > g_maxChars) {
262*27162e4eSAndroid Build Coastguard Worker         generateLastWord(word, wordLen, upCase);
263*27162e4eSAndroid Build Coastguard Worker         return;
264*27162e4eSAndroid Build Coastguard Worker     }
265*27162e4eSAndroid Build Coastguard Worker     assert(wordLen <= 16);
266*27162e4eSAndroid Build Coastguard Worker     memcpy(g_ptr + g_nbChars, word, 16);
267*27162e4eSAndroid Build Coastguard Worker     if (upCase) {
268*27162e4eSAndroid Build Coastguard Worker         static const char toUp = 'A' - 'a';
269*27162e4eSAndroid Build Coastguard Worker         g_ptr[g_nbChars]       = (char)(g_ptr[g_nbChars] + toUp);
270*27162e4eSAndroid Build Coastguard Worker     }
271*27162e4eSAndroid Build Coastguard Worker     g_nbChars += wordLen;
272*27162e4eSAndroid Build Coastguard Worker     assert(sepLen <= 2);
273*27162e4eSAndroid Build Coastguard Worker     memcpy(g_ptr + g_nbChars, separator, 2);
274*27162e4eSAndroid Build Coastguard Worker     g_nbChars += sepLen;
275*27162e4eSAndroid Build Coastguard Worker }
276*27162e4eSAndroid Build Coastguard Worker 
about(unsigned target)277*27162e4eSAndroid Build Coastguard Worker static int about(unsigned target)
278*27162e4eSAndroid Build Coastguard Worker {
279*27162e4eSAndroid Build Coastguard Worker     return (int)(LOREM_rand(target) + LOREM_rand(target) + 1);
280*27162e4eSAndroid Build Coastguard Worker }
281*27162e4eSAndroid Build Coastguard Worker 
282*27162e4eSAndroid Build Coastguard Worker /* Function to generate a random sentence */
generateSentence(int nbWords)283*27162e4eSAndroid Build Coastguard Worker static void generateSentence(int nbWords)
284*27162e4eSAndroid Build Coastguard Worker {
285*27162e4eSAndroid Build Coastguard Worker     int commaPos       = about(9);
286*27162e4eSAndroid Build Coastguard Worker     int comma2         = commaPos + about(7);
287*27162e4eSAndroid Build Coastguard Worker     int qmark          = (LOREM_rand(11) == 7);
288*27162e4eSAndroid Build Coastguard Worker     const char* endSep = qmark ? "? " : ". ";
289*27162e4eSAndroid Build Coastguard Worker     int i;
290*27162e4eSAndroid Build Coastguard Worker     for (i = 0; i < nbWords; i++) {
291*27162e4eSAndroid Build Coastguard Worker         int const wordID       = g_distrib[LOREM_rand(g_distribCount)];
292*27162e4eSAndroid Build Coastguard Worker         const char* sep        = " ";
293*27162e4eSAndroid Build Coastguard Worker         size_t sepLen = 1;
294*27162e4eSAndroid Build Coastguard Worker         if (i == commaPos)
295*27162e4eSAndroid Build Coastguard Worker             sep = ", ", sepLen=2;
296*27162e4eSAndroid Build Coastguard Worker         if (i == comma2)
297*27162e4eSAndroid Build Coastguard Worker             sep = ", ", sepLen=2;
298*27162e4eSAndroid Build Coastguard Worker         if (i == nbWords - 1)
299*27162e4eSAndroid Build Coastguard Worker             sep = endSep, sepLen=2;
300*27162e4eSAndroid Build Coastguard Worker         generateWord(g_words[wordID], g_wordLen[wordID], sep, sepLen, i == 0);
301*27162e4eSAndroid Build Coastguard Worker     }
302*27162e4eSAndroid Build Coastguard Worker }
303*27162e4eSAndroid Build Coastguard Worker 
generateParagraph(int nbSentences)304*27162e4eSAndroid Build Coastguard Worker static void generateParagraph(int nbSentences)
305*27162e4eSAndroid Build Coastguard Worker {
306*27162e4eSAndroid Build Coastguard Worker     int i;
307*27162e4eSAndroid Build Coastguard Worker     for (i = 0; i < nbSentences; i++) {
308*27162e4eSAndroid Build Coastguard Worker         int wordsPerSentence = about(11);
309*27162e4eSAndroid Build Coastguard Worker         generateSentence(wordsPerSentence);
310*27162e4eSAndroid Build Coastguard Worker     }
311*27162e4eSAndroid Build Coastguard Worker     if (g_nbChars < g_maxChars) {
312*27162e4eSAndroid Build Coastguard Worker         g_ptr[g_nbChars++] = '\n';
313*27162e4eSAndroid Build Coastguard Worker     }
314*27162e4eSAndroid Build Coastguard Worker     if (g_nbChars < g_maxChars) {
315*27162e4eSAndroid Build Coastguard Worker         g_ptr[g_nbChars++] = '\n';
316*27162e4eSAndroid Build Coastguard Worker     }
317*27162e4eSAndroid Build Coastguard Worker }
318*27162e4eSAndroid Build Coastguard Worker 
319*27162e4eSAndroid Build Coastguard Worker /* It's "common" for lorem ipsum generators to start with the same first
320*27162e4eSAndroid Build Coastguard Worker  * pre-defined sentence */
generateFirstSentence(void)321*27162e4eSAndroid Build Coastguard Worker static void generateFirstSentence(void)
322*27162e4eSAndroid Build Coastguard Worker {
323*27162e4eSAndroid Build Coastguard Worker     int i;
324*27162e4eSAndroid Build Coastguard Worker     for (i = 0; i < 18; i++) {
325*27162e4eSAndroid Build Coastguard Worker         const char* separator = " ";
326*27162e4eSAndroid Build Coastguard Worker         size_t sepLen = 1;
327*27162e4eSAndroid Build Coastguard Worker         if (i == 4)
328*27162e4eSAndroid Build Coastguard Worker             separator = ", ", sepLen=2;
329*27162e4eSAndroid Build Coastguard Worker         if (i == 7)
330*27162e4eSAndroid Build Coastguard Worker             separator = ", ", sepLen=2;
331*27162e4eSAndroid Build Coastguard Worker         generateWord(g_words[i], g_wordLen[i], separator, sepLen, i == 0);
332*27162e4eSAndroid Build Coastguard Worker     }
333*27162e4eSAndroid Build Coastguard Worker     generateWord(g_words[18], g_wordLen[18], ". ", 2, 0);
334*27162e4eSAndroid Build Coastguard Worker }
335*27162e4eSAndroid Build Coastguard Worker 
336*27162e4eSAndroid Build Coastguard Worker size_t
LOREM_genBlock(void * buffer,size_t size,unsigned seed,int first,int fill)337*27162e4eSAndroid Build Coastguard Worker LOREM_genBlock(void* buffer, size_t size, unsigned seed, int first, int fill)
338*27162e4eSAndroid Build Coastguard Worker {
339*27162e4eSAndroid Build Coastguard Worker     g_ptr = (char*)buffer;
340*27162e4eSAndroid Build Coastguard Worker     assert(size < INT_MAX);
341*27162e4eSAndroid Build Coastguard Worker     g_maxChars = size;
342*27162e4eSAndroid Build Coastguard Worker     g_nbChars  = 0;
343*27162e4eSAndroid Build Coastguard Worker     g_randRoot = seed;
344*27162e4eSAndroid Build Coastguard Worker     if (g_distribCount == 0) {
345*27162e4eSAndroid Build Coastguard Worker         init_word_len(kWords, kNbWords);
346*27162e4eSAndroid Build Coastguard Worker         init_word_buffer();
347*27162e4eSAndroid Build Coastguard Worker         init_word_distrib(g_wordLen, kNbWords, kWeights, kNbWeights);
348*27162e4eSAndroid Build Coastguard Worker     }
349*27162e4eSAndroid Build Coastguard Worker 
350*27162e4eSAndroid Build Coastguard Worker     if (first) {
351*27162e4eSAndroid Build Coastguard Worker         generateFirstSentence();
352*27162e4eSAndroid Build Coastguard Worker     }
353*27162e4eSAndroid Build Coastguard Worker     while (g_nbChars < g_maxChars) {
354*27162e4eSAndroid Build Coastguard Worker         int sentencePerParagraph = about(7);
355*27162e4eSAndroid Build Coastguard Worker         generateParagraph(sentencePerParagraph);
356*27162e4eSAndroid Build Coastguard Worker         if (!fill)
357*27162e4eSAndroid Build Coastguard Worker             break; /* only generate one paragraph in not-fill mode */
358*27162e4eSAndroid Build Coastguard Worker     }
359*27162e4eSAndroid Build Coastguard Worker     g_ptr = NULL;
360*27162e4eSAndroid Build Coastguard Worker     return g_nbChars;
361*27162e4eSAndroid Build Coastguard Worker }
362*27162e4eSAndroid Build Coastguard Worker 
LOREM_genBuffer(void * buffer,size_t size,unsigned seed)363*27162e4eSAndroid Build Coastguard Worker void LOREM_genBuffer(void* buffer, size_t size, unsigned seed)
364*27162e4eSAndroid Build Coastguard Worker {
365*27162e4eSAndroid Build Coastguard Worker     LOREM_genBlock(buffer, size, seed, 1, 1);
366*27162e4eSAndroid Build Coastguard Worker }
367