Updating to reflect the latest work
[zilutils.git] / zilasm / string_table.cpp
diff --git a/zilasm/string_table.cpp b/zilasm/string_table.cpp
new file mode 100644 (file)
index 0000000..a086b87
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * 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;
+    }
+}