Advertisement
Guest User

Untitled

a guest
Feb 26th, 2020
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.47 KB | None | 0 0
  1. #define boolean int
  2. #define false 0
  3. #define true 1
  4.  
  5. #include <stdio.h>
  6. #include <mm_malloc.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9.  
  10. // Exit codes
  11. typedef enum {
  12.     SUCCESS,
  13.     OUT_OF_MEMORY,
  14.     WRONG_INPUT,
  15.     WRONG_OPTIONS,
  16.     UNKNOWN_SYMBOL
  17. } ExitCodes;
  18.  
  19. const char* exitMessages[] = {
  20.         "success",
  21.         "out of memory",
  22.         "wrong input",
  23.         "wrong options",
  24.         "unknown symbol"
  25. };
  26.  
  27. //Options
  28. typedef enum {
  29.     ENCODING,
  30.     DECODING,
  31.     IGNORE,
  32.     ENTERS
  33. } Options;
  34.  
  35. const char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  36.  
  37. ExitCodes getOptions(int argc, char* argv[], boolean* options, int* enters) {
  38.     for (int i = 1; i < argc; i++) {
  39.         if (argv[i][0] != '-' || strlen(argv[i]) != 2) {
  40.             return WRONG_INPUT;
  41.         }
  42.  
  43.         switch (argv[i][1]) {
  44.             case 'd':
  45.                 if (options[DECODING]) {
  46.                     return WRONG_INPUT;
  47.                 }
  48.                 options[DECODING] = true;
  49.                 break;
  50.             case 'e':
  51.                 if (options[ENCODING]) {
  52.                     return WRONG_INPUT;
  53.                 }
  54.                 options[ENCODING] = true;
  55.                 break;
  56.             case 'f':
  57.                 if (options[ENTERS]) {
  58.                     return WRONG_INPUT;
  59.                 }
  60.                 options[ENTERS] = true;
  61.                 i++;
  62.                 *enters = 0;
  63.                 for (int j = 0; j < strlen(argv[i]); j++) {
  64.                     char currentSymbol = argv[i][j];
  65.                     if (!isdigit(currentSymbol)) {
  66.                         return WRONG_INPUT;
  67.                     }
  68.                     *enters = *enters * 10 + currentSymbol - '0';
  69.                 }
  70.                 break;
  71.             case 'i':
  72.                 if (options[IGNORE]) {
  73.                     return WRONG_INPUT;
  74.                 }
  75.                 options[IGNORE] = true;
  76.                 break;
  77.             default:
  78.                 return WRONG_INPUT;
  79.         }
  80.     }
  81.  
  82.     return SUCCESS;
  83. }
  84.  
  85. boolean checkOptions(const boolean* array) {
  86.     if (!(array[DECODING] ^ array[ENCODING])) {
  87.         return false;
  88.     }
  89.     if (array[ENCODING] && array[IGNORE]) {
  90.         return false;
  91.     }
  92.     if (array[DECODING] && array[ENTERS]) {
  93.         return false;
  94.     }
  95.  
  96.     return true;
  97. }
  98.  
  99. ExitCodes startEncoding(boolean enters, int charsInSingleLine) {
  100.     size_t currentIndex = 0,
  101.            currentB64Index = 0;
  102.     unsigned char currentB64Symbol = 0,
  103.                   currentRemainder = 0;
  104.     unsigned char currentSymbol;
  105.  
  106.  
  107.     while ((currentSymbol = (unsigned char)getchar()) != '\n') {
  108.         switch (currentIndex % 3) {
  109.             case 0:
  110.                 currentB64Symbol = currentSymbol >> 2;
  111.                 currentRemainder = (unsigned char)(currentSymbol % 4);
  112.  
  113.                 printf("%c", base64chars[currentB64Symbol]);
  114.                 currentB64Index++;
  115.                 break;
  116.             case 1:
  117.                 currentB64Symbol = currentRemainder << 4;
  118.                 currentB64Symbol += currentSymbol >> 4;
  119.  
  120.                 printf("%c", base64chars[currentB64Symbol]);
  121.                 currentB64Index++;
  122.  
  123.                 currentRemainder = (unsigned char)(currentSymbol % 16);
  124.                 break;
  125.             case 2:
  126.                 currentB64Symbol = currentRemainder << 2;
  127.                 currentRemainder = currentSymbol >> 6;
  128.                 currentB64Symbol += currentRemainder;
  129.                 currentRemainder = (unsigned char)(currentSymbol % 64);
  130.  
  131.                 printf("%c", base64chars[currentB64Symbol]);
  132.                 currentB64Index++;
  133.                 if (currentB64Index % charsInSingleLine == 0) {
  134.                     printf("\n");
  135.                 }
  136.  
  137.                 printf("%c", base64chars[currentRemainder]);
  138.                 currentB64Index++;
  139.                 break;
  140.             default:
  141.                 continue;
  142.         }
  143.  
  144.         currentIndex++;
  145.         if (currentB64Index % charsInSingleLine == 0) {
  146.             printf("\n");
  147.         }
  148.     }
  149.  
  150.     if (currentIndex % 3 != 0) {
  151.         int moveByRemainder = currentIndex % 3 == 1 ? 4 : 2;
  152.         printf("%c", base64chars[currentRemainder << moveByRemainder]);
  153.         if (currentB64Index % charsInSingleLine == 0) {
  154.             printf("\n");
  155.         }
  156.         for (int i = 3 - ((int)currentIndex % 3); i > 0; i--) {
  157.             printf("=");
  158.         }
  159.     }
  160.  
  161.     return SUCCESS;
  162. }
  163.  
  164. boolean isValidChar(unsigned char c) {
  165.     if ('0' <= c && c <= '9')
  166.         return true;
  167.     if ('a' <= c && c <= 'z')
  168.         return true;
  169.     if ('A' <= c && c <= 'Z')
  170.         return true;
  171.     if (c == '+' || c == '/' || c == '=')
  172.         return true;
  173.     return false;
  174. }
  175.  
  176. void getHashTable(int* table) {
  177.     memset(table, -1, 256);
  178.     for (int i = 0; i < 64; i++) {
  179.         table[base64chars[i]] = i;
  180.     }
  181. }
  182.  
  183. ExitCodes startDecoding(boolean ignore) {
  184.     size_t currentB64Index = 0;
  185.     unsigned char currentB64Symbol,
  186.                   currentSymbol = 0,
  187.                   currentRemainder = 0;
  188.  
  189.     int* hashTable = (int*)calloc(256, sizeof(unsigned char));
  190.     if (!hashTable) {
  191.         return OUT_OF_MEMORY;
  192.     }
  193.  
  194.     getHashTable(hashTable);
  195.  
  196.     if (!ignore) {
  197.         while ((currentB64Symbol = (unsigned char)getchar()) != '\n') {
  198.             if (!isValidChar(currentB64Symbol)) {
  199.                 return UNKNOWN_SYMBOL;
  200.             }
  201.         }
  202.     }
  203.  
  204.     fseek(stdin, sizeof(unsigned char), SEEK_SET);
  205.  
  206.     size_t countOfEndSymbols = 0;
  207.     while ((currentB64Symbol = (unsigned char)getchar()) != '\n') {
  208.         if (currentB64Symbol == '=') {
  209.             while (currentB64Symbol == '=') {
  210.                 countOfEndSymbols++;
  211.                 currentB64Symbol = (unsigned char)getchar();
  212.             }
  213.             break;
  214.         }
  215.  
  216.         switch (currentB64Index % 4) {
  217.             case 0:
  218.                 currentSymbol = (unsigned char)(hashTable[currentB64Symbol] << 2);
  219.                 break;
  220.             case 1:
  221.                 currentSymbol += (unsigned char)(hashTable[currentB64Symbol] >> 4);
  222.                 currentRemainder = (unsigned char)(hashTable[currentB64Symbol] % 16);
  223.  
  224.                 printf("%c", currentSymbol);
  225.                 break;
  226.             case 2:
  227.                 currentSymbol = currentRemainder << 4;
  228.                 currentSymbol += (unsigned char)(hashTable[currentB64Symbol] >> 2);
  229.                 currentRemainder = (unsigned char)(hashTable[currentB64Symbol] % 4);
  230.  
  231.                 printf("%c", currentSymbol);
  232.                 break;
  233.             case 3:
  234.                 currentSymbol = currentRemainder << 6;
  235.                 currentSymbol += hashTable[currentB64Symbol];
  236.  
  237.                 printf("%c", currentSymbol);
  238.                 break;
  239.             default:
  240.                 continue;
  241.         }
  242.  
  243.         currentB64Index++;
  244.     }
  245.     switch (countOfEndSymbols) {
  246.         case 1:
  247.             printf("%c", currentRemainder << 4);
  248.             break;
  249.         case 2:
  250.             printf("%c", currentRemainder << 6);
  251.             break;
  252.         default:
  253.             break;
  254.     }
  255.  
  256.     return SUCCESS;
  257. }
  258.  
  259. ExitCodes startAlgorithm(int argc, char* argv[]) {
  260.     //Allocating array for options
  261.     boolean* includedOptions = (boolean*)calloc(4, sizeof(boolean));
  262.     if (!includedOptions) {
  263.         return OUT_OF_MEMORY;
  264.     }
  265.  
  266.     //Get options and check
  267.     ExitCodes getArrayOfOptions;
  268.     int enters = -1;
  269.     if ((getArrayOfOptions = getOptions(argc, argv, includedOptions, &enters)) != SUCCESS) {
  270.         return getArrayOfOptions;
  271.     }
  272.  
  273.     if (!checkOptions(includedOptions)) {
  274.         return WRONG_OPTIONS;
  275.     }
  276.  
  277.     //Start process
  278.     ExitCodes transforming;
  279.     boolean encoding = includedOptions[ENCODING] ? true : false;
  280.     if (encoding) {
  281.         boolean includeEnters = includedOptions[ENTERS] ? true : false;
  282.         if ((transforming = includeEnters ? startEncoding(true, enters) : startEncoding(false, -1)) != SUCCESS) {
  283.             return transforming;
  284.         }
  285.     } else {
  286.         boolean ignore = includedOptions[IGNORE] ? true : false;
  287.         if ((transforming = ignore ? startDecoding(true) : startDecoding(false)) != SUCCESS) {
  288.             return transforming;
  289.         }
  290.     }
  291.  
  292.     return SUCCESS;
  293. }
  294.  
  295. int main(int argc, char* argv[]) {
  296.     ExitCodes executing;
  297.     if ((executing = startAlgorithm(argc, argv)) != SUCCESS) {
  298.         printf("%s\n", exitMessages[executing]);
  299.     }
  300. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement