|
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
|
|