Name: Anonymous 2012-10-15 19:30
/*
* File: prog-utils/quote-optimizer.cxx
*
* Purpose: Optimizes quotes for you
*
* Usage: At this point, you may only pass unoptimized quotes
* (i.e., >>24>>28\n>>2 ...)
* Text file input (-i) is supported
*
* Build instructions:
* g++ quote-optimizer.cxx -o quote-optimizer -std=c++0x -O2
*
* Contributors:
* Anonymous-san
*
*/
/*
prog-utils/quote-optimizer
Copyright (C) 2012 Anonymous-san
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>;.
*/
#include <vector>
#include <list>
#include <string>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <utility>
#include <algorithm>
#include <assert.h>
using namespace std;
vector<uint16_t> parse_quotes(const char *);
vector<string> optimize(vector<uint16_t> *);
int custom_itoa(int val, char * buf);
void get_from_stdin(char *, uint32_t, char **, FILE *);
void get_from_args(char *, uint32_t, char **, FILE *);
void get_from_file(char *, uint32_t, char **, FILE *);
static char * input = NULL;
int main(int argc, char ** argv)
{
void (*get_from)(char *, uint32_t, char **, FILE *) = get_from_stdin;
FILE * file = NULL;
while(*argv != NULL)
{
if(!strcmp("--help", *argv)
|| !strcmp("-h", *argv))
{
puts("Usage: optimize-quotes [options] [string]"
"\nOptions: --help [-h], --stdin [-s], --args [-a], --input [-i]");
exit(1);
}
else if(!strcmp("--stdin", *argv)
|| !strcmp("-s", *argv))
{
get_from = get_from_stdin;
}
else if(!strcmp("--args", *argv)
|| !strcmp("-a", *argv))
{
get_from = get_from_args;
assert(*++argv);
input = *argv;
}
else if(!strcmp("--input", *argv)
|| !strcmp("-i", *argv))
{
get_from = get_from_file;
assert(*++argv);
file = fopen(*argv, "r");
}
++argv;
}
//const char test[] = ">>1\n>>2\n>>7\n>>3\n>>20\n>>4\n>>45>>1>>7>>99";
char * buf = new char [1024];
get_from(buf, 1024, argv, file);
if(file != NULL)
fclose(file);
input = input == NULL ? buf : input;
vector<uint16_t> parsed = parse_quotes(input);
delete [] buf;
auto output = optimize(&parsed);
auto i = begin(output);
char c = 0;
for( ; i != end(output); ++i)
{
c = ((i + 1) == end(output)) ? '\n' : ',';
printf("%s%c", i->c_str(), c);
}
return 0;
}
void get_from_stdin
(
char * dest,
uint32_t n,
char **,
FILE *
)
{
puts("--stdin (default) selected; enter unoptimized quotes");
fgets(dest, n, stdin);
}
void get_from_args
(
char * dest,
uint32_t,
char ** argv,
FILE *
)
/*
* TODO concatenate all arguments instead
*
* dummy function for the moment
*/
{
}
void get_from_file
(
char * dest,
uint32_t n,
char **,
FILE * file
)
{
uint32_t actually_read = 0;
static const uint32_t should_read = 128;
//static const uint32_t max_file_size = 4096;
do
{
actually_read = fread(dest, sizeof(char), should_read, file);
dest += actually_read;
} while(actually_read == should_read);
}
vector<uint16_t> parse_quotes
(
const char * src
)
{
vector<uint16_t> ret;
char * buf = new char [20];
char * pbuf = buf;
uint8_t read = 0;
static const uint8_t first_arrow = 0x01;
static const uint8_t second_arrow = 0x02;
static const uint8_t number = 0x04;
while(*src != 0)
{
switch(*src)
{
case '>':
{
if(read ^ first_arrow
&& read ^ second_arrow
&& pbuf != buf)
{
*pbuf = 0;
ret.push_back(atoi(buf));
pbuf = buf;
}
if(read ^ first_arrow)
read |= first_arrow;
else if(read ^ second_arrow)
read |= second_arrow;
else if(read & first_arrow
&& read & second_arrow)
{
puts("Syntax error");
}
break;
}
case '0': case '1': case '2':
case '3': case '4': case '5':
case '6': case '7': case '8':
case '9':
{
if(read ^ number)
read |= number;
if(read & second_arrow)
*(pbuf++) = *src;
break;
}
default:
{
/*
if(read & first_arrow)
read -= first_arrow;
if(read & second_arrow)
read -= second_arrow;
*/
break;
}
}
++src;
}
*pbuf = 0;
ret.push_back(atoi(buf));
pbuf = buf;
delete [] buf;
return ret;
}
vector<string> optimize
(
vector<uint16_t> * src
)
{
vector<string> ret;
char * const buf = new char[20];
//sort
sort(src->begin(), src->end());
//set up for reading
uint8_t read = 0;
static const uint8_t range = 0x01;
static const uint8_t item = 0x02;
uint16_t first_in_range = 0;
uint16_t last_in_range = 0;
uint16_t last_number_read = 1;
//reading
for(auto& i : *src)
{
if(i == last_number_read)
continue;
if(i == last_number_read + 1)
{
if(read ^ range)
{
first_in_range = last_number_read;
read |= range;
}
}
else
{
if(read & range)
{
last_in_range = last_number_read;
uint16_t l = custom_itoa(first_in_range, buf);
buf[l] = '-';
uint16_t m = custom_itoa(last_in_range, buf + l + 1);
buf[l + m + 1] = 0;
ret.push_back(buf);
read -= range;
}
if(read ^ item)
read |= item;
uint16_t l = custom_itoa(i, buf);
ret.push_back(buf);
}
last_number_read = i;
}
delete [] buf;
return ret;
}
int custom_itoa(int val, char * buf)
//stolen code
{
const unsigned int radix = 10;
char* p;
unsigned int a; //every digit
int len;
char* b; //start of the digit char
char temp;
unsigned int u;
p = buf;
if (val < 0)
{
*p++ = '-';
val = 0 - val;
}
u = (unsigned int)val;
b = p;
do
{
a = u % radix;
u /= radix;
*p++ = a + '0';
} while (u > 0);
len = (int)(p - buf);
*p-- = 0;
//swap
do
{
temp = *p;
*p = *b;
*b = temp;
--p;
++b;
} while (b < p);
return len;
}