Fossil SCM

fossil-scm / src / mnemonic.c
Blame History Raw 550 lines
1
/*
2
** Copyright (c) 2008 D. Richard Hipp
3
**
4
** This program is free software; you can redistribute it and/or
5
** modify it under the terms of the Simplified BSD License (also
6
** known as the "2-Clause License" or "FreeBSD License".)
7
** This program is distributed in the hope that it will be useful,
8
** but without any warranty; without even the implied warranty of
9
** merchantability or fitness for a particular purpose.
10
**
11
** Author contact information:
12
** [email protected]
13
** http://www.hwaci.com/drh/
14
**
15
*******************************************************************************
16
**
17
** This file contains the code to do mnemonic encoding of commit IDs. The
18
** wordlist and algorithm were originally taken from:
19
**
20
** https://github.com/singpolyma/mnemonicode
21
**
22
** ...which is BSD licensed. However, the algorithm has since been heavily
23
** modified to more fit Fossil's special needs.
24
**
25
** The new algorithm works by reading hex characters one at a time and
26
** accumulating bits into a ring buffer. When available, 10 bits are consumed
27
** and used as a word index. This only uses 1024 of the available 1626 words
28
** but preserves the property that encoded strings may be truncated at any
29
** point and the resulting hex string, when decoded, is a truncated form of
30
** the original hex string. It is, unfortunately, slightly less efficient, and
31
** three words can only encode seven hex digits.
32
*/
33
34
#include "config.h"
35
#include "mnemonic.h"
36
37
#define MN_BASE 1626
38
39
/* Number of bits to encode as a word. 10 is the maximum. */
40
#define CHUNK_SIZE 10
41
42
static const char* basewordlist[MN_BASE] =
43
{
44
"ACADEMY", "ACROBAT", "ACTIVE", "ACTOR", "ADAM", "ADMIRAL",
45
"ADRIAN", "AFRICA", "AGENDA", "AGENT", "AIRLINE", "AIRPORT",
46
"ALADDIN", "ALARM", "ALASKA", "ALBERT", "ALBINO", "ALBUM",
47
"ALCOHOL", "ALEX", "ALGEBRA", "ALIBI", "ALICE", "ALIEN",
48
"ALPHA", "ALPINE", "AMADEUS", "AMANDA", "AMAZON", "AMBER",
49
"AMERICA", "AMIGO", "ANALOG", "ANATOMY", "ANGEL", "ANIMAL",
50
"ANTENNA", "ANTONIO", "APOLLO", "APRIL", "ARCHIVE", "ARCTIC",
51
"ARIZONA", "ARNOLD", "AROMA", "ARTHUR", "ARTIST", "ASIA",
52
"ASPECT", "ASPIRIN", "ATHENA", "ATHLETE", "ATLAS", "AUDIO",
53
"AUGUST", "AUSTRIA", "AXIOM", "AZTEC", "BALANCE", "BALLAD",
54
"BANANA", "BANDIT", "BANJO", "BARCODE", "BARON", "BASIC",
55
"BATTERY", "BELGIUM", "BERLIN", "BERMUDA", "BERNARD", "BIKINI",
56
"BINARY", "BINGO", "BIOLOGY", "BLOCK", "BLONDE", "BONUS",
57
"BORIS", "BOSTON", "BOXER", "BRANDY", "BRAVO", "BRAZIL",
58
"BRONZE", "BROWN", "BRUCE", "BRUNO", "BURGER", "BURMA",
59
"CABINET", "CACTUS", "CAFE", "CAIRO", "CAKE", "CALYPSO",
60
"CAMEL", "CAMERA", "CAMPUS", "CANADA", "CANAL", "CANNON",
61
"CANOE", "CANTINA", "CANVAS", "CANYON", "CAPITAL", "CARAMEL",
62
"CARAVAN", "CARBON", "CARGO", "CARLO", "CAROL", "CARPET",
63
"CARTEL", "CASINO", "CASTLE", "CASTRO", "CATALOG", "CAVIAR",
64
"CECILIA", "CEMENT", "CENTER", "CENTURY", "CERAMIC", "CHAMBER",
65
"CHANCE", "CHANGE", "CHAOS", "CHARLIE", "CHARM", "CHARTER",
66
"CHEF", "CHEMIST", "CHERRY", "CHESS", "CHICAGO", "CHICKEN",
67
"CHIEF", "CHINA", "CIGAR", "CINEMA", "CIRCUS", "CITIZEN",
68
"CITY", "CLARA", "CLASSIC", "CLAUDIA", "CLEAN", "CLIENT",
69
"CLIMAX", "CLINIC", "CLOCK", "CLUB", "COBRA", "COCONUT",
70
"COLA", "COLLECT", "COLOMBO", "COLONY", "COLOR", "COMBAT",
71
"COMEDY", "COMET", "COMMAND", "COMPACT", "COMPANY", "COMPLEX",
72
"CONCEPT", "CONCERT", "CONNECT", "CONSUL", "CONTACT", "CONTEXT",
73
"CONTOUR", "CONTROL", "CONVERT", "COPY", "CORNER", "CORONA",
74
"CORRECT", "COSMOS", "COUPLE", "COURAGE", "COWBOY", "CRAFT",
75
"CRASH", "CREDIT", "CRICKET", "CRITIC", "CROWN", "CRYSTAL",
76
"CUBA", "CULTURE", "DALLAS", "DANCE", "DANIEL", "DAVID",
77
"DECADE", "DECIMAL", "DELIVER", "DELTA", "DELUXE", "DEMAND",
78
"DEMO", "DENMARK", "DERBY", "DESIGN", "DETECT", "DEVELOP",
79
"DIAGRAM", "DIALOG", "DIAMOND", "DIANA", "DIEGO", "DIESEL",
80
"DIET", "DIGITAL", "DILEMMA", "DIPLOMA", "DIRECT", "DISCO",
81
"DISNEY", "DISTANT", "DOCTOR", "DOLLAR", "DOMINIC", "DOMINO",
82
"DONALD", "DRAGON", "DRAMA", "DUBLIN", "DUET", "DYNAMIC",
83
"EAST", "ECOLOGY", "ECONOMY", "EDGAR", "EGYPT", "ELASTIC",
84
"ELEGANT", "ELEMENT", "ELITE", "ELVIS", "EMAIL", "ENERGY",
85
"ENGINE", "ENGLISH", "EPISODE", "EQUATOR", "ESCORT", "ETHNIC",
86
"EUROPE", "EVEREST", "EVIDENT", "EXACT", "EXAMPLE", "EXIT",
87
"EXOTIC", "EXPORT", "EXPRESS", "EXTRA", "FABRIC", "FACTOR",
88
"FALCON", "FAMILY", "FANTASY", "FASHION", "FIBER", "FICTION",
89
"FIDEL", "FIESTA", "FIGURE", "FILM", "FILTER", "FINAL",
90
"FINANCE", "FINISH", "FINLAND", "FLASH", "FLORIDA", "FLOWER",
91
"FLUID", "FLUTE", "FOCUS", "FORD", "FOREST", "FORMAL",
92
"FORMAT", "FORMULA", "FORTUNE", "FORUM", "FRAGILE", "FRANCE",
93
"FRANK", "FRIEND", "FROZEN", "FUTURE", "GABRIEL", "GALAXY",
94
"GALLERY", "GAMMA", "GARAGE", "GARDEN", "GARLIC", "GEMINI",
95
"GENERAL", "GENETIC", "GENIUS", "GERMANY", "GLOBAL", "GLORIA",
96
"GOLF", "GONDOLA", "GONG", "GOOD", "GORDON", "GORILLA",
97
"GRAND", "GRANITE", "GRAPH", "GREEN", "GROUP", "GUIDE",
98
"GUITAR", "GURU", "HAND", "HAPPY", "HARBOR", "HARMONY",
99
"HARVARD", "HAVANA", "HAWAII", "HELENA", "HELLO", "HENRY",
100
"HILTON", "HISTORY", "HORIZON", "HOTEL", "HUMAN", "HUMOR",
101
"ICON", "IDEA", "IGLOO", "IGOR", "IMAGE", "IMPACT",
102
"IMPORT", "INDEX", "INDIA", "INDIGO", "INPUT", "INSECT",
103
"INSTANT", "IRIS", "ITALIAN", "JACKET", "JACOB", "JAGUAR",
104
"JANET", "JAPAN", "JARGON", "JAZZ", "JEEP", "JOHN",
105
"JOKER", "JORDAN", "JUMBO", "JUNE", "JUNGLE", "JUNIOR",
106
"JUPITER", "KARATE", "KARMA", "KAYAK", "KERMIT", "KILO",
107
"KING", "KOALA", "KOREA", "LABOR", "LADY", "LAGOON",
108
"LAPTOP", "LASER", "LATIN", "LAVA", "LECTURE", "LEFT",
109
"LEGAL", "LEMON", "LEVEL", "LEXICON", "LIBERAL", "LIBRA",
110
"LIMBO", "LIMIT", "LINDA", "LINEAR", "LION", "LIQUID",
111
"LITER", "LITTLE", "LLAMA", "LOBBY", "LOBSTER", "LOCAL",
112
"LOGIC", "LOGO", "LOLA", "LONDON", "LOTUS", "LUCAS",
113
"LUNAR", "MACHINE", "MACRO", "MADAM", "MADONNA", "MADRID",
114
"MAESTRO", "MAGIC", "MAGNET", "MAGNUM", "MAJOR", "MAMA",
115
"MAMBO", "MANAGER", "MANGO", "MANILA", "MARCO", "MARINA",
116
"MARKET", "MARS", "MARTIN", "MARVIN", "MASTER", "MATRIX",
117
"MAXIMUM", "MEDIA", "MEDICAL", "MEGA", "MELODY", "MELON",
118
"MEMO", "MENTAL", "MENTOR", "MENU", "MERCURY", "MESSAGE",
119
"METAL", "METEOR", "METER", "METHOD", "METRO", "MEXICO",
120
"MIAMI", "MICRO", "MILLION", "MINERAL", "MINIMUM", "MINUS",
121
"MINUTE", "MIRACLE", "MIRAGE", "MIRANDA", "MISTER", "MIXER",
122
"MOBILE", "MODEL", "MODEM", "MODERN", "MODULAR", "MOMENT",
123
"MONACO", "MONICA", "MONITOR", "MONO", "MONSTER", "MONTANA",
124
"MORGAN", "MOTEL", "MOTIF", "MOTOR", "MOZART", "MULTI",
125
"MUSEUM", "MUSIC", "MUSTANG", "NATURAL", "NEON", "NEPAL",
126
"NEPTUNE", "NERVE", "NEUTRAL", "NEVADA", "NEWS", "NINJA",
127
"NIRVANA", "NORMAL", "NOVA", "NOVEL", "NUCLEAR", "NUMERIC",
128
"NYLON", "OASIS", "OBJECT", "OBSERVE", "OCEAN", "OCTOPUS",
129
"OLIVIA", "OLYMPIC", "OMEGA", "OPERA", "OPTIC", "OPTIMAL",
130
"ORANGE", "ORBIT", "ORGANIC", "ORIENT", "ORIGIN", "ORLANDO",
131
"OSCAR", "OXFORD", "OXYGEN", "OZONE", "PABLO", "PACIFIC",
132
"PAGODA", "PALACE", "PAMELA", "PANAMA", "PANDA", "PANEL",
133
"PANIC", "PARADOX", "PARDON", "PARIS", "PARKER", "PARKING",
134
"PARODY", "PARTNER", "PASSAGE", "PASSIVE", "PASTA", "PASTEL",
135
"PATENT", "PATRIOT", "PATROL", "PATRON", "PEGASUS", "PELICAN",
136
"PENGUIN", "PEPPER", "PERCENT", "PERFECT", "PERFUME", "PERIOD",
137
"PERMIT", "PERSON", "PERU", "PHONE", "PHOTO", "PIANO",
138
"PICASSO", "PICNIC", "PICTURE", "PIGMENT", "PILGRIM", "PILOT",
139
"PIRATE", "PIXEL", "PIZZA", "PLANET", "PLASMA", "PLASTER",
140
"PLASTIC", "PLAZA", "POCKET", "POEM", "POETIC", "POKER",
141
"POLARIS", "POLICE", "POLITIC", "POLO", "POLYGON", "PONY",
142
"POPCORN", "POPULAR", "POSTAGE", "POSTAL", "PRECISE", "PREFIX",
143
"PREMIUM", "PRESENT", "PRICE", "PRINCE", "PRINTER", "PRISM",
144
"PRIVATE", "PRODUCT", "PROFILE", "PROGRAM", "PROJECT", "PROTECT",
145
"PROTON", "PUBLIC", "PULSE", "PUMA", "PYRAMID", "QUEEN",
146
"RADAR", "RADIO", "RANDOM", "RAPID", "REBEL", "RECORD",
147
"RECYCLE", "REFLEX", "REFORM", "REGARD", "REGULAR", "RELAX",
148
"REPORT", "REPTILE", "REVERSE", "RICARDO", "RINGO", "RITUAL",
149
"ROBERT", "ROBOT", "ROCKET", "RODEO", "ROMEO", "ROYAL",
150
"RUSSIAN", "SAFARI", "SALAD", "SALAMI", "SALMON", "SALON",
151
"SALUTE", "SAMBA", "SANDRA", "SANTANA", "SARDINE", "SCHOOL",
152
"SCREEN", "SCRIPT", "SECOND", "SECRET", "SECTION", "SEGMENT",
153
"SELECT", "SEMINAR", "SENATOR", "SENIOR", "SENSOR", "SERIAL",
154
"SERVICE", "SHERIFF", "SHOCK", "SIERRA", "SIGNAL", "SILICON",
155
"SILVER", "SIMILAR", "SIMON", "SINGLE", "SIREN", "SLOGAN",
156
"SOCIAL", "SODA", "SOLAR", "SOLID", "SOLO", "SONIC",
157
"SOVIET", "SPECIAL", "SPEED", "SPIRAL", "SPIRIT", "SPORT",
158
"STATIC", "STATION", "STATUS", "STEREO", "STONE", "STOP",
159
"STREET", "STRONG", "STUDENT", "STUDIO", "STYLE", "SUBJECT",
160
"SULTAN", "SUPER", "SUSAN", "SUSHI", "SUZUKI", "SWITCH",
161
"SYMBOL", "SYSTEM", "TACTIC", "TAHITI", "TALENT", "TANGO",
162
"TARZAN", "TAXI", "TELEX", "TEMPO", "TENNIS", "TEXAS",
163
"TEXTILE", "THEORY", "THERMOS", "TIGER", "TITANIC", "TOKYO",
164
"TOMATO", "TOPIC", "TORNADO", "TORONTO", "TORPEDO", "TOTAL",
165
"TOTEM", "TOURIST", "TRACTOR", "TRAFFIC", "TRANSIT", "TRAPEZE",
166
"TRAVEL", "TRIBAL", "TRICK", "TRIDENT", "TRILOGY", "TRIPOD",
167
"TROPIC", "TRUMPET", "TULIP", "TUNA", "TURBO", "TWIST",
168
"ULTRA", "UNIFORM", "UNION", "URANIUM", "VACUUM", "VALID",
169
"VAMPIRE", "VANILLA", "VATICAN", "VELVET", "VENTURA", "VENUS",
170
"VERTIGO", "VETERAN", "VICTOR", "VIDEO", "VIENNA", "VIKING",
171
"VILLAGE", "VINCENT", "VIOLET", "VIOLIN", "VIRTUAL", "VIRUS",
172
"VISA", "VISION", "VISITOR", "VISUAL", "VITAMIN", "VIVA",
173
"VOCAL", "VODKA", "VOLCANO", "VOLTAGE", "VOLUME", "VOYAGE",
174
"WATER", "WEEKEND", "WELCOME", "WESTERN", "WINDOW", "WINTER",
175
"WIZARD", "WOLF", "WORLD", "XRAY", "YANKEE", "YOGA",
176
"YOGURT", "YOYO", "ZEBRA", "ZERO", "ZIGZAG", "ZIPPER",
177
"ZODIAC", "ZOOM", "ABRAHAM", "ACTION", "ADDRESS", "ALABAMA",
178
"ALFRED", "ALMOND", "AMMONIA", "ANALYZE", "ANNUAL", "ANSWER",
179
"APPLE", "ARENA", "ARMADA", "ARSENAL", "ATLANTA", "ATOMIC",
180
"AVENUE", "AVERAGE", "BAGEL", "BAKER", "BALLET", "BAMBINO",
181
"BAMBOO", "BARBARA", "BASKET", "BAZAAR", "BENEFIT", "BICYCLE",
182
"BISHOP", "BLITZ", "BONJOUR", "BOTTLE", "BRIDGE", "BRITISH",
183
"BROTHER", "BRUSH", "BUDGET", "CABARET", "CADET", "CANDLE",
184
"CAPITAN", "CAPSULE", "CAREER", "CARTOON", "CHANNEL", "CHAPTER",
185
"CHEESE", "CIRCLE", "COBALT", "COCKPIT", "COLLEGE", "COMPASS",
186
"COMRADE", "CONDOR", "CRIMSON", "CYCLONE", "DARWIN", "DECLARE",
187
"DEGREE", "DELETE", "DELPHI", "DENVER", "DESERT", "DIVIDE",
188
"DOLBY", "DOMAIN", "DOMINGO", "DOUBLE", "DRINK", "DRIVER",
189
"EAGLE", "EARTH", "ECHO", "ECLIPSE", "EDITOR", "EDUCATE",
190
"EDWARD", "EFFECT", "ELECTRA", "EMERALD", "EMOTION", "EMPIRE",
191
"EMPTY", "ESCAPE", "ETERNAL", "EVENING", "EXHIBIT", "EXPAND",
192
"EXPLORE", "EXTREME", "FERRARI", "FIRST", "FLAG", "FOLIO",
193
"FORGET", "FORWARD", "FREEDOM", "FRESH", "FRIDAY", "FUJI",
194
"GALILEO", "GARCIA", "GENESIS", "GOLD", "GRAVITY", "HABITAT",
195
"HAMLET", "HARLEM", "HELIUM", "HOLIDAY", "HOUSE", "HUNTER",
196
"IBIZA", "ICEBERG", "IMAGINE", "INFANT", "ISOTOPE", "JACKSON",
197
"JAMAICA", "JASMINE", "JAVA", "JESSICA", "JUDO", "KITCHEN",
198
"LAZARUS", "LETTER", "LICENSE", "LITHIUM", "LOYAL", "LUCKY",
199
"MAGENTA", "MAILBOX", "MANUAL", "MARBLE", "MARY", "MAXWELL",
200
"MAYOR", "MILK", "MONARCH", "MONDAY", "MONEY", "MORNING",
201
"MOTHER", "MYSTERY", "NATIVE", "NECTAR", "NELSON", "NETWORK",
202
"NEXT", "NIKITA", "NOBEL", "NOBODY", "NOMINAL", "NORWAY",
203
"NOTHING", "NUMBER", "OCTOBER", "OFFICE", "OLIVER", "OPINION",
204
"OPTION", "ORDER", "OUTSIDE", "PACKAGE", "PANCAKE", "PANDORA",
205
"PANTHER", "PAPA", "PATIENT", "PATTERN", "PEDRO", "PENCIL",
206
"PEOPLE", "PHANTOM", "PHILIPS", "PIONEER", "PLUTO", "PODIUM",
207
"PORTAL", "POTATO", "PRIZE", "PROCESS", "PROTEIN", "PROXY",
208
"PUMP", "PUPIL", "PYTHON", "QUALITY", "QUARTER", "QUIET",
209
"RABBIT", "RADICAL", "RADIUS", "RAINBOW", "RALPH", "RAMIREZ",
210
"RAVIOLI", "RAYMOND", "RESPECT", "RESPOND", "RESULT", "RESUME",
211
"RETRO", "RICHARD", "RIGHT", "RISK", "RIVER", "ROGER",
212
"ROMAN", "RONDO", "SABRINA", "SALARY", "SALSA", "SAMPLE",
213
"SAMUEL", "SATURN", "SAVAGE", "SCARLET", "SCOOP", "SCORPIO",
214
"SCRATCH", "SCROLL", "SECTOR", "SERPENT", "SHADOW", "SHAMPOO",
215
"SHARON", "SHARP", "SHORT", "SHRINK", "SILENCE", "SILK",
216
"SIMPLE", "SLANG", "SMART", "SMOKE", "SNAKE", "SOCIETY",
217
"SONAR", "SONATA", "SOPRANO", "SOURCE", "SPARTA", "SPHERE",
218
"SPIDER", "SPONSOR", "SPRING", "ACID", "ADIOS", "AGATHA",
219
"ALAMO", "ALERT", "ALMANAC", "ALOHA", "ANDREA", "ANITA",
220
"ARCADE", "AURORA", "AVALON", "BABY", "BAGGAGE", "BALLOON",
221
"BANK", "BASIL", "BEGIN", "BISCUIT", "BLUE", "BOMBAY",
222
"BRAIN", "BRENDA", "BRIGADE", "CABLE", "CARMEN", "CELLO",
223
"CELTIC", "CHARIOT", "CHROME", "CITRUS", "CIVIL", "CLOUD",
224
"COMMON", "COMPARE", "COOL", "COPPER", "CORAL", "CRATER",
225
"CUBIC", "CUPID", "CYCLE", "DEPEND", "DOOR", "DREAM",
226
"DYNASTY", "EDISON", "EDITION", "ENIGMA", "EQUAL", "ERIC",
227
"EVENT", "EVITA", "EXODUS", "EXTEND", "FAMOUS", "FARMER",
228
"FOOD", "FOSSIL", "FROG", "FRUIT", "GENEVA", "GENTLE",
229
"GEORGE", "GIANT", "GILBERT", "GOSSIP", "GRAM", "GREEK",
230
"GRILLE", "HAMMER", "HARVEST", "HAZARD", "HEAVEN", "HERBERT",
231
"HEROIC", "HEXAGON", "HUSBAND", "IMMUNE", "INCA", "INCH",
232
"INITIAL", "ISABEL", "IVORY", "JASON", "JEROME", "JOEL",
233
"JOSHUA", "JOURNAL", "JUDGE", "JULIET", "JUMP", "JUSTICE",
234
"KIMONO", "KINETIC", "LEONID", "LIMA", "MAZE", "MEDUSA",
235
"MEMBER", "MEMPHIS", "MICHAEL", "MIGUEL", "MILAN", "MILE",
236
"MILLER", "MIMIC", "MIMOSA", "MISSION", "MONKEY", "MORAL",
237
"MOSES", "MOUSE", "NANCY", "NATASHA", "NEBULA", "NICKEL",
238
"NINA", "NOISE", "ORCHID", "OREGANO", "ORIGAMI", "ORINOCO",
239
"ORION", "OTHELLO", "PAPER", "PAPRIKA", "PRELUDE", "PREPARE",
240
"PRETEND", "PROFIT", "PROMISE", "PROVIDE", "PUZZLE", "REMOTE",
241
"REPAIR", "REPLY", "RIVAL", "RIVIERA", "ROBIN", "ROSE",
242
"ROVER", "RUDOLF", "SAGA", "SAHARA", "SCHOLAR", "SHELTER",
243
"SHIP", "SHOE", "SIGMA", "SISTER", "SLEEP", "SMILE",
244
"SPAIN", "SPARK", "SPLIT", "SPRAY", "SQUARE", "STADIUM",
245
"STAR", "STORM", "STORY", "STRANGE", "STRETCH", "STUART",
246
"SUBWAY", "SUGAR", "SULFUR", "SUMMER", "SURVIVE", "SWEET",
247
"SWIM", "TABLE", "TABOO", "TARGET", "TEACHER", "TELECOM",
248
"TEMPLE", "TIBET", "TICKET", "TINA", "TODAY", "TOGA",
249
"TOMMY", "TOWER", "TRIVIAL", "TUNNEL", "TURTLE", "TWIN",
250
"UNCLE", "UNICORN", "UNIQUE", "UPDATE", "VALERY", "VEGA",
251
"VERSION", "VOODOO", "WARNING", "WILLIAM", "WONDER", "YEAR",
252
"YELLOW", "YOUNG", "ABSENT", "ABSORB", "ACCENT", "ALFONSO",
253
"ALIAS", "AMBIENT", "ANDY", "ANVIL", "APPEAR", "APROPOS",
254
"ARCHER", "ARIEL", "ARMOR", "ARROW", "AUSTIN", "AVATAR",
255
"AXIS", "BABOON", "BAHAMA", "BALI", "BALSA", "BAZOOKA",
256
"BEACH", "BEAST", "BEATLES", "BEAUTY", "BEFORE", "BENNY",
257
"BETTY", "BETWEEN", "BEYOND", "BILLY", "BISON", "BLAST",
258
"BLESS", "BOGART", "BONANZA", "BOOK", "BORDER", "BRAVE",
259
"BREAD", "BREAK", "BROKEN", "BUCKET", "BUENOS", "BUFFALO",
260
"BUNDLE", "BUTTON", "BUZZER", "BYTE", "CAESAR", "CAMILLA",
261
"CANARY", "CANDID", "CARROT", "CAVE", "CHANT", "CHILD",
262
"CHOICE", "CHRIS", "CIPHER", "CLARION", "CLARK", "CLEVER",
263
"CLIFF", "CLONE", "CONAN", "CONDUCT", "CONGO", "CONTENT",
264
"COSTUME", "COTTON", "COVER", "CRACK", "CURRENT", "DANUBE",
265
"DATA", "DECIDE", "DESIRE", "DETAIL", "DEXTER", "DINNER",
266
"DISPUTE", "DONOR", "DRUID", "DRUM", "EASY", "EDDIE",
267
"ENJOY", "ENRICO", "EPOXY", "EROSION", "EXCEPT", "EXILE",
268
"EXPLAIN", "FAME", "FAST", "FATHER", "FELIX", "FIELD",
269
"FIONA", "FIRE", "FISH", "FLAME", "FLEX", "FLIPPER",
270
"FLOAT", "FLOOD", "FLOOR", "FORBID", "FOREVER", "FRACTAL",
271
"FRAME", "FREDDIE", "FRONT", "FUEL", "GALLOP", "GAME",
272
"GARBO", "GATE", "GIBSON", "GINGER", "GIRAFFE", "GIZMO",
273
"GLASS", "GOBLIN", "GOPHER", "GRACE", "GRAY", "GREGORY",
274
"GRID", "GRIFFIN", "GROUND", "GUEST", "GUSTAV", "GYRO",
275
"HAIR", "HALT", "HARRIS", "HEART", "HEAVY", "HERMAN",
276
"HIPPIE", "HOBBY", "HONEY", "HOPE", "HORSE", "HOSTEL",
277
"HYDRO", "IMITATE", "INFO", "INGRID", "INSIDE", "INVENT",
278
"INVEST", "INVITE", "IRON", "IVAN", "JAMES", "JESTER",
279
"JIMMY", "JOIN", "JOSEPH", "JUICE", "JULIUS", "JULY",
280
"JUSTIN", "KANSAS", "KARL", "KEVIN", "KIWI", "LADDER",
281
"LAKE", "LAURA", "LEARN", "LEGACY", "LEGEND", "LESSON",
282
"LIFE", "LIGHT", "LIST", "LOCATE", "LOPEZ", "LORENZO",
283
"LOVE", "LUNCH", "MALTA", "MAMMAL", "MARGO", "MARION",
284
"MASK", "MATCH", "MAYDAY", "MEANING", "MERCY", "MIDDLE",
285
"MIKE", "MIRROR", "MODEST", "MORPH", "MORRIS", "NADIA",
286
"NATO", "NAVY", "NEEDLE", "NEURON", "NEVER", "NEWTON",
287
"NICE", "NIGHT", "NISSAN", "NITRO", "NIXON", "NORTH",
288
"OBERON", "OCTAVIA", "OHIO", "OLGA", "OPEN", "OPUS",
289
"ORCA", "OVAL", "OWNER", "PAGE", "PAINT", "PALMA",
290
"PARADE", "PARENT", "PAROLE", "PAUL", "PEACE", "PEARL",
291
"PERFORM", "PHOENIX", "PHRASE", "PIERRE", "PINBALL", "PLACE",
292
"PLATE", "PLATO", "PLUME", "POGO", "POINT", "POLITE",
293
"POLKA", "PONCHO", "POWDER", "PRAGUE", "PRESS", "PRESTO",
294
"PRETTY", "PRIME", "PROMO", "QUASI", "QUEST", "QUICK",
295
"QUIZ", "QUOTA", "RACE", "RACHEL", "RAJA", "RANGER",
296
"REGION", "REMARK", "RENT", "REWARD", "RHINO", "RIBBON",
297
"RIDER", "ROAD", "RODENT", "ROUND", "RUBBER", "RUBY",
298
"RUFUS", "SABINE", "SADDLE", "SAILOR", "SAINT", "SALT",
299
"SATIRE", "SCALE", "SCUBA", "SEASON", "SECURE", "SHAKE",
300
"SHALLOW", "SHANNON", "SHAVE", "SHELF", "SHERMAN", "SHINE",
301
"SHIRT", "SIDE", "SINATRA", "SINCERE", "SIZE", "SLALOM",
302
"SLOW", "SMALL", "SNOW", "SOFIA", "SONG", "SOUND",
303
"SOUTH", "SPEECH", "SPELL", "SPEND", "SPOON", "STAGE",
304
"STAMP", "STAND", "STATE", "STELLA", "STICK", "STING",
305
"STOCK", "STORE", "SUNDAY", "SUNSET", "SUPPORT", "SWEDEN",
306
"SWING", "TAPE", "THINK", "THOMAS", "TICTAC", "TIME",
307
"TOAST", "TOBACCO", "TONIGHT", "TORCH", "TORSO", "TOUCH",
308
"TOYOTA", "TRADE", "TRIBUNE", "TRINITY", "TRITON", "TRUCK",
309
"TRUST", "TYPE", "UNDER", "UNIT", "URBAN", "URGENT",
310
"USER", "VALUE", "VENDOR", "VENICE", "VERONA", "VIBRATE",
311
"VIRGO", "VISIBLE", "VISTA", "VITAL", "VOICE", "VORTEX",
312
"WAITER", "WATCH", "WAVE", "WEATHER", "WEDDING", "WHEEL",
313
"WHISKEY", "WISDOM", "DEAL", "NULL", "NURSE", "QUEBEC",
314
"RESERVE", "REUNION", "ROOF", "SINGER", "VERBAL", "AMEN"
315
};
316
317
/*
318
** Special string comparator.
319
*/
320
321
static int strspecialcmp(const char* s1, const char* s2)
322
{
323
int c1, c2;
324
325
do
326
{
327
c1 = toupper(*s1++);
328
c2 = toupper(*s2++);
329
if ((c1 == ' ') || (c1 == '-') || (c1 == '_'))
330
c1 = 0;
331
if ((c2 == ' ') || (c2 == '-') || (c2 == '_'))
332
c2 = 0;
333
if (!c1 || !c2)
334
break;
335
}
336
while (c1 == c2);
337
338
return c1 - c2;
339
}
340
341
/*
342
** Look up a word in the base dictionary and return its index; -1 if the word
343
** is not in the dictionary.
344
*/
345
346
static int baseword_to_index(const char* word)
347
{
348
int i;
349
350
for (i=0; i<sizeof(basewordlist)/sizeof(*basewordlist); i++)
351
if (strspecialcmp(basewordlist[i], word) == 0)
352
return i;
353
354
return -1;
355
}
356
357
/*
358
** Look up a word by index in the base dictionary and return the string.
359
*/
360
361
static const char* index_to_baseword(int index)
362
{
363
return basewordlist[index];
364
}
365
366
/*
367
** Encode a hex-character string using mnemonic encoding, writing the
368
** result into the supplied blob.
369
*/
370
371
int mnemonic_encode(const char* zString, Blob* xBlob)
372
{
373
unsigned int buffer = 0;
374
int buflen = 0;
375
int first = 1;
376
int value;
377
378
for (;;)
379
{
380
/* Read hex characters into the buffer until we have at least CHUNK_SIZE
381
* bits. */
382
383
while (buflen < CHUNK_SIZE)
384
{
385
int i = sscanf(zString, "%1x", &value);
386
if (i == 0) /* Parse error? */
387
return 0;
388
if (i == EOF) /* End of line */
389
break;
390
buffer <<= 4;
391
buffer |= value;
392
buflen += 4;
393
zString++;
394
}
395
396
if (buflen < CHUNK_SIZE)
397
{
398
/* Run out of available characters --- give up. */
399
break;
400
}
401
402
/* Extract ten bits of data. */
403
404
value = (buffer >> (buflen-CHUNK_SIZE)) & ((1<<CHUNK_SIZE)-1);
405
buflen -= CHUNK_SIZE;
406
407
/* Insert a leading space, if necessary. */
408
409
if (!first)
410
blob_appendf(xBlob, " ");
411
first = 0;
412
413
/* Actually encode a word. */
414
415
blob_appendf(xBlob, "%s", index_to_baseword(value));
416
}
417
418
return 1;
419
}
420
421
/*
422
** Decode a a mnemonic encoded string, writing the resulting hex-character
423
** string into the supplied blob.
424
*/
425
426
int mnemonic_decode(const char* zString, Blob* xBlob)
427
{
428
unsigned int buffer = 0;
429
int buflen = 0;
430
int first = 1;
431
int value;
432
433
while (zString)
434
{
435
/* Consume a word, if necessary. */
436
437
while (buflen < 4)
438
{
439
/* Find the end of the current word. */
440
441
const char* end = strchr(zString, ' ');
442
if (!end)
443
end = strchr(zString, '-');
444
if (!end)
445
end = strchr(zString, '_');
446
447
/* Parse. */
448
449
value = baseword_to_index(zString);
450
if (value == -1) /* Parse error? */
451
return 0;
452
buffer <<= CHUNK_SIZE;
453
buffer |= value;
454
buflen += CHUNK_SIZE;
455
456
/* Advance the pointer to the next word. */
457
458
zString = end;
459
if (zString)
460
zString++;
461
}
462
463
/* Now consume nibbles and produce hex bytes. */
464
465
while (buflen >= 4)
466
{
467
value = (buffer >> (buflen-4)) & 0xf;
468
buflen -= 4;
469
470
blob_appendf(xBlob, "%x", value);
471
}
472
}
473
474
return 1;
475
}
476
477
/*
478
** Implementation of the "mnemonic_encode(X)" SQL function. The argument X
479
** is an artifact ID prefix (hex characters). It will be mnemonic encoded
480
** and returned as a string.
481
*/
482
static void sqlcmd_mnemonic_encode(
483
sqlite3_context *context,
484
int argc,
485
sqlite3_value **argv
486
){
487
Blob x;
488
const char *zName;
489
int rc;
490
assert( argc==1 );
491
492
zName = (const char*)sqlite3_value_text(argv[0]);
493
if( zName==0 ) return;
494
495
blob_zero(&x);
496
rc = mnemonic_encode(zName, &x);
497
if ((rc==0) || (blob_size(&x) == 0))
498
sqlite3_result_error(context, "could not mnemonic encode value", -1);
499
else
500
sqlite3_result_text(context, blob_buffer(&x), blob_size(&x),
501
SQLITE_TRANSIENT);
502
blob_reset(&x);
503
}
504
505
/*
506
** Implementation of the "mnemonic_decode(X)" SQL function. The argument X
507
** is an mnemonic encoded artifact ID prefix (a string of words). It will be
508
** decoded and returned as a string of hex characters.
509
**
510
** If the string is not a valid mnemonic encoded value, it is returned
511
** unchanged.
512
*/
513
static void sqlcmd_mnemonic_decode(
514
sqlite3_context *context,
515
int argc,
516
sqlite3_value **argv
517
){
518
Blob x;
519
const char *zName;
520
int rc;
521
assert( argc==1 );
522
523
zName = (const char*)sqlite3_value_text(argv[0]);
524
if( zName==0 ) return;
525
526
blob_zero(&x);
527
rc = mnemonic_decode(zName, &x);
528
if ((rc==0) || (blob_size(&x)==0))
529
sqlite3_result_text(context, zName, -1, SQLITE_TRANSIENT);
530
else
531
sqlite3_result_text(context, blob_buffer(&x), blob_size(&x),
532
SQLITE_TRANSIENT);
533
blob_reset(&x);
534
}
535
536
/*
537
** Add the SQL functions that wrap mnemonic_encode() and mnemonic_decode().
538
*/
539
540
void mnemonic_add_sql_func(sqlite3 *db)
541
{
542
sqlite3_create_function(db, "mnemonic_encode", 1, SQLITE_ANY, 0,
543
sqlcmd_mnemonic_encode, 0, 0);
544
sqlite3_create_function(db, "mnemonic_decode", 1, SQLITE_ANY, 0,
545
sqlcmd_mnemonic_decode, 0, 0);
546
}
547
548
/* vi: set ts=2:sw=2:expandtab: */
549
550

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button