--- /dev/null
+/*
+ * string_table.cpp -- part of ZilUtils/ZilAsm
+ *
+ * Copyright (C) 2019 Jason Self <j@jxself.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "header.h"
+#include "string_table.h"
+#include <string.h>
+extern "C"
+{
+#include <strings.h>
+}
+
+unsigned
+String_table::add_string_to_string_table (const char *str, ZMemblock * zmb)
+{
+ encrypt_string (str, zmb);
+ return 0;
+}
+
+
+ZMemblock *
+String_table::encrypt_string (const char *str, ZMemblock * zmb)
+{
+ if (!zmb)
+ zmb = zmem_init (strlen (str) * 3);
+
+ int currentCharSet = 0;
+ Byte currentByte = 0;
+ int index = 0;
+ Word w = 0;
+ int numberOfSymbolsInWord = 0;
+ while (index < (int) strlen (str))
+ {
+ char c = str[index];
+ if (c >= 'a' && c <= 'z')
+ {
+ switch (currentCharSet)
+ {
+ case 0:
+ break;
+ case 1:
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 5); // permanently changes to the zero charset
+ currentCharSet = 0;
+ break;
+ case 2:
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 4); // permanently changes to the zero charset
+ currentCharSet = 0;
+ break;
+ }
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord,
+ c - 'a' + 6);
+ }
+ else if (c >= 'A' && c <= 'Z')
+ {
+ switch (currentCharSet)
+ {
+ case 0:
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 4); // temporarily changes to the zero charset
+ break;
+ case 1:
+ break;
+ case 2:
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 4); // permanently changes to the zero charset
+ currentCharSet = 0;
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 4); // temporarily changes to the first charset
+ break;
+ }
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord,
+ c - 'A' + 6);
+
+ }
+ else if (c == ' ')
+ {
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 0);
+ }
+ else
+ {
+ char ar[] = "*0123456789.,!?_#'\"/\\-:()";
+ for (int i = 0; i < (int) strlen (ar); ++i)
+ {
+ if (ar[i] == c)
+ {
+ c = i + 7;
+ break;
+ }
+ }
+
+ switch (currentCharSet)
+ {
+ case 0:
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 5); // temporarily changes to the second charset
+ break;
+ case 1:
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 5); // permanently changes to the zero charset
+ currentCharSet = 0;
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, 5); // temporarily changes to the second charset
+ break;
+ case 2:
+ break;
+ }
+ write_one_word_to_string_table (zmb, &w, &numberOfSymbolsInWord, c);
+ }
+
+ ++index;
+ }
+
+ if (numberOfSymbolsInWord != 0)
+ {
+ zmem_putbyte (zmb, (w >> 8) & 255);
+ zmem_putbyte (zmb, w & 255);
+ numberOfSymbolsInWord = 0;
+ w = 0;
+ }
+ zmb->contents[zmb->used_size - 2] |= 0x80;
+
+ return zmb;
+}
+
+void
+String_table::write_one_word_to_string_table (ZMemblock * zmb, Word * w,
+ int *numberOfSymbolsInWord,
+ Byte symbol)
+{
+ int shift = ((2 - *numberOfSymbolsInWord) * 5);
+ *w |= (symbol << shift);
+
+ (*numberOfSymbolsInWord)++;
+
+ if (*numberOfSymbolsInWord == 3)
+ {
+ zmem_putbyte (zmb, (*w >> 8) & 255);
+ zmem_putbyte (zmb, (*w) & 255);
+ *numberOfSymbolsInWord = 0;
+ (*w) = 0;
+ }
+}