// ConsoleApplication1.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
//

#include <iostream>
#include <string.h>
#include <chrono>

void TrimRight(char* s) {

   size_t len = strlen(s);

   char* iter = s + len - 1;

   if (*iter != ' ') {
      // Если последний символ не пробел, 
      // то и обрезать нечего
      return;
   }

   while (*iter == ' ' /*&& iter != s*/) {
      // Идти от конца к началу, 
      // пока не кончатся пробелы либо строка
      iter--;
   }
   
   if (iter == s) {
      // Если строка пройдена
      // и полностью состоит из пробелов
      // то результатом будет пустая строка
      *iter = '\0';
   }
   else {
      // Если пройдены все пробелы 
      // и поиск дошел до первого не пробела,
      // то заменить первый пробел на конец строки.
      *(iter + 1) = '\0';
   }
   
}

void TrimRight2(char* s)
{
   char *spc = 0, *p = s;

   while (*p)
      if (*p == ' ')
         for (spc = p; *(++p) == ' ';);
      else
         ++p;

   if (spc && p != s && p[-1] == ' ') *spc = 0;
   //return s;
}

void TrimRight3(char* s) {

   char* space = nullptr;
   char* p = s;

   while (*p) {
      if (*p == ' ') {
         if (space == nullptr) {
            space = p;
         }
         p++;
      }
      else {
         space == nullptr;
         p++;
      }
   }

   if (space != nullptr) {
      *space = '\0';
   }

}

void TrimRight4 (char * s) {
   size_t len = strlen (s);
   char * it = s + len - 1;

   while (it >= s && *it == ' ') {
     *(it--) = '\0';
   }
}

double testTrimRight (char * str) {
   auto start = std::chrono::high_resolution_clock::now();
   TrimRight(str);
   auto finish = std::chrono::high_resolution_clock::now();
   return (double)(finish - start).count ();
}

double testTrimRight2 (char * str) {
   auto start = std::chrono::high_resolution_clock::now();
   TrimRight2(str);
   auto finish = std::chrono::high_resolution_clock::now();
   return (double)(finish - start).count ();
}

double testTrimRight3 (char * str) {
   auto start = std::chrono::high_resolution_clock::now();
   TrimRight3(str);
   auto finish = std::chrono::high_resolution_clock::now();
   return (double)(finish - start).count ();
}

double testTrimRight4 (char * str) {
   auto start = std::chrono::high_resolution_clock::now();
   TrimRight4 (str);
   auto finish = std::chrono::high_resolution_clock::now();
   return (double)(finish - start).count ();
}

const size_t LENGTH = 1000000;
char * LETTERS;
char * testData;
char * sourceData;

void createLetters () {
   LETTERS = (char *) malloc (sizeof (char) * 22);
   for (size_t j = 0; j < 22; j++) {
      if (j % 7)
         LETTERS[j] = 'A' + j;
      else
         LETTERS[j] = ' ';
   }
}

void createTestData () {
   testData = (char *) malloc (sizeof (char) * LENGTH);
}

void createSourceData () {
   sourceData = (char *) malloc (sizeof (char) * LENGTH);
}

char * fillSourceData (size_t len_chars, size_t len_string) {
   for (size_t i = 0; i < len_chars; i++) {
      sourceData[i] = LETTERS[rand () % 22];
   }

   for (size_t i = len_chars; i < len_string; i++) {
      sourceData[i] = ' ';
   }

   sourceData[len_string - 1] = '\0';

   return sourceData;
}

char * fillTestData (int len) {
   memcpy (testData, sourceData, sizeof (char) * len);
   return testData;
}

double average (double t0, double t1) {
   return ((9.0 * t0 + t1) / 10.0);
}

int main()
{
   const int PROBES = 1000 / 3;
   int i = 0, char_length = 0, full_length = 0;
   double e0 = 0.0, e1 = 0.0, e2 = 0.0, e3 = 0.0, second = 1000000;

   createLetters ();
   createSourceData ();
   createTestData ();

   while (i++ < PROBES) {
      full_length = LENGTH /*- LENGTH / 100 * (rand () % 66)*/;
      char_length = full_length - full_length / 100 * (rand () % 66);
      fillSourceData (char_length, full_length);
      e0 = average (e0, testTrimRight (fillTestData (full_length)));
      e1 = average (e1, testTrimRight2 (fillTestData (full_length)));
      e2 = average (e2, testTrimRight3 (fillTestData (full_length)));
      e3 = average (e3, testTrimRight4 (fillTestData (full_length)));
   }

   std::cout << "Elapsed time testTrimRight:  " << e0/second << " Ms\n";
   std::cout << "Elapsed time testTrimRight2: " << e1/second << " Ms\n";
   std::cout << "Elapsed time testTrimRight3: " << e2/second << " Ms\n";
   std::cout << "Elapsed time testTrimRight4: " << e3/second << " Ms\n";
}

