示例#1
0
// Reads given number of bits (rounded up to next byte) into a bitset.
// Used for reading region information which can be represented by some
// number of bits.
Bitset readBits(std::ifstream& in, const std::size_t bits)
{
    using block_t = Bitset::block_type;
    std::size_t const bytes = static_cast<std::size_t>(std::ceil(bits / 8.));
    std::size_t const blocks =
        bytes + 1 < sizeof(block_t) ? 1 : (bytes + 1) / sizeof(block_t);

    std::vector<block_t> data;
    data.resize(blocks);
    std::fill_n(data.data(), blocks, 0);
    in.read(reinterpret_cast<char*>(data.data()), bytes);

    return Bitset(data.begin(), data.end());
}
示例#2
0
void HuffmanCompressor::compress(int size, const INT16 *data, Bitset &transmitData)
{
  // Find frequency of each value
  for (UINT i = 0; i < size; ++i)
    ++dataFrequency[data[i]];
  dataFrequency[INT16_MAX] = 1; // use max value as the pseudo EOF

  // Store each frequency as a (leaf) node in minimum heap
  for (auto it = dataFrequency.begin(); it != dataFrequency.end(); ++it) {
    Node *node = new Node(it->first, it->second);
    minHeap.push(node);
  }

  // Generate Huffman tree
  while (minHeap.size() != 1) {
    Node *right = minHeap.top();
    minHeap.pop();
    Node *left = minHeap.top();
    minHeap.pop();
    minHeap.push(new Node(left->frequency + right->frequency, left, right)); // Create internal node
  }
  Node *huffmanTree = minHeap.top();

  // Get Huffman codes for each value and generate encoded Huffman tree
  std::string code("");
  std::string encodedHuffmanTree("");
  getHuffmanCode(huffmanTree, code, encodedHuffmanTree);
  std::reverse(encodedHuffmanTree.begin(), encodedHuffmanTree.end()); // TODO: try encodedHuffmanTree = bit + encodedHuffmanTree to see if performance is better

  // Encode data values
  std::string encodedData("");
  for (UINT i = 0; i < size; ++i) {
    encodedData += huffmanCodes[data[i]];
  }
  encodedData += huffmanCodes[INT16_MAX]; // add pseudo EOF
  std::reverse(encodedData.begin(), encodedData.end());

  // Convert data to bit array
  transmitData = Bitset(encodedData + encodedHuffmanTree);

  // Deallocate memory
  deallocateTree(huffmanTree);
  minHeap.pop();
  dataFrequency.clear();
  huffmanCodes.clear();
}
int parse_year_range(bitset *years, char **s) {
	u_int range[2] = {1900, 2923};

	while (**s == ' ') ++*s;

	if (strstr(*s, ",") == *s) {
		printf("Invalid syntax: empty element at list of ranges. Expected value before coma.\n");
		return (ERROR);
	}

	*years = Bitset(1024);
	do {
		if (match(*s, "^[0-9]{4}([^0-9]|$)")) {
			if (match(*s + 4, "^ *- *[0-9]{4}([^0-9]|$)")) {
				range[0] = atoi(*s);
				while (isdigit(**s)) ++*s;
				while (**s == ' ') ++*s;
				++*s;
				while (**s == ' ') ++*s;
				range[1] = atoi(*s);
				while (isdigit(**s)) ++*s;
				set_subset(*years, range[0] - 1900, range[1] - 1900, true);
			} else {
				range[1] = range[0] = atoi(*s);
				if (range[1] < 1900) {
					printf("Invalid range: year must be greater than or equal to 1900\n");
					return (ERROR);
				} else if (range[1] > 2923) {
					printf("Invalid range: are you sure somebody still could use your opening hours in %d?\n", range[1]);
					return (ERROR);
				}
				*s += 4;
				SET_BIT(*years, range[0] - 1900, true);
			}
		} else {
			set_subset(*years, range[0] - 1900, range[1] - 1900, true);
			return (EMPTY);
		}
	} while (strstr(*s, ",") == *s && *(++*s));
	return (SUCCESS);
}
int parse_week_selector(bitset *weeks, char **s) {
	int weeknum;

	while (**s == ' ') ++*s;

	*weeks = Bitset(54);
	if (strstr(*s, "week ") != *s) {
		set_subset(*weeks, 0, 52, true);
		return (EMPTY);
	}
	*s += sizeof("week");
	do {
		while (**s == ' ') ++*s;
		if ((weeknum = atoi(*s)) < 1 || weeknum > 54) {
			printf("Invalid syntax: week %d doesn't exist.\n", weeknum);
			return (ERROR);
		}
		SET_BIT(*weeks, weeknum - 1, true);
		while (isdigit(**s)) ++*s;
	} while (strstr(*s, ",") == *s && *(++*s));
	return (SUCCESS);
}
int parse_monthday_range(monthday_range *monthday, char **s) {
	int month_id, month_to,
	    daynum = 0, dayto = 0;

	while (**s == ' ') ++*s;

	monthday->days = Bitset(12 * 32);
	if (get_month_id(*s) == 12) {
		set_subset(monthday->days, 0, 12 * 32, true);
		return (EMPTY);
	}
	do {
		while (**s == ' ') ++*s;
		if (strstr(*s, "easter ") == *s) {
			*s += sizeof("easter");
			while (**s == ' ') ++*s;
			monthday->easter = true;
			if (**s == '-') {
				printf("Unsupported syntax: ranges including easter aren't allowed here, aborting.\n");
				return (ERROR);
			}
			continue;
		}
		month_id = get_month_id(*s);
		if (month_id == 12) {
			printf("Invalid syntax: expected month in the monthday_range.\n");
			return (ERROR);
		}
		*s += 3;
		while (**s == ' ') ++*s;
		if ((dayto = daynum = atoi(*s))) {
			if (daynum > NB_DAYS[month_id]) {
				printf("Invalid range: day %d doesn't exist for %s.\n", daynum, MONTHS_FULLSTR[month_id]);
				return (ERROR);
			}
			while (isdigit(**s)) ++*s;
		}
		while (**s == ' ') ++*s;
		if (**s == '-') {
			++*s;
			while (**s == ' ') ++*s;
			if (strstr(*s, "easter") == *s) {
				printf("Unsupported syntax: ranges including easter aren't allowed here, aborting.\n");
				return (ERROR);
			}
			if ((month_to = get_month_id(*s)) == 12) {
				printf("Invalid syntax: month range enclosed without new month. Aborting.\n");
				return (ERROR);
			}
			*s += 3;
			while (**s == ' ') ++*s;
			if ((dayto = atoi(*s))) {
				if (dayto > NB_DAYS[month_to]) {
					printf("Invalid range: day %d doesn't exist for %s.\n", dayto, MONTHS_FULLSTR[month_id]);
					return (ERROR);
				}
				while (isdigit(**s)) ++*s;
			} else {
				dayto = 32;
			}
			daynum = !daynum ? 1 : daynum;
			if (month_to > month_id || (month_to == month_id && dayto >= daynum)) {
				set_subset(monthday->days, month_id * 32 + daynum - 1, month_to * 32 + dayto - 2, true);
			} else {
				set_subset(monthday->days, month_id * 32 + daynum - 1, 12 * 32, true);
				set_subset(monthday->days, 0, month_to * 32 + dayto - 1, true);
			}
			while (isdigit(**s)) ++*s;
		} else {
			if (!daynum)
				set_subset(monthday->days, month_id * 32, month_id * 32 + 31, true);
			else
				SET_BIT(monthday->days, month_id * 32 + daynum - 1, true);
		}
	} while (strstr(*s, ",") == *s && *(++*s));
	return (SUCCESS);
}
int parse_time_selector(time_selector *selector, char **s) {
	int hours_from = 0, hours_to = 0,
		mins_from = 0, mins_to = 0,
		extended_hour;
	char hourmin_sep;

	selector->time_range = Bitset(60 * 24);
	selector->extended_time_range = Bitset(60 * 24);

	do {
		while (**s == ' ') ++*s;
		if (!isdigit(**s)) {
			if (!(hours_from | hours_to | mins_from | mins_to)) {
				set_subset(selector->time_range, 0, 24 * 60, true);
				return (EMPTY);
			}
			printf("Invalid syntax: unexpected token.\n");
			return (ERROR);
		}
		if ((hours_from = atoi(*s)) > 23) {
			printf("Invalid range: are you really sure that such an hour does exist?\n");
			return (ERROR);
		}
		while (isdigit(**s)) ++*s;
		if ((hourmin_sep = **s) != ':' && **s != 'h') {
			printf("Invalid syntax: unexpected token '%c'.\n                Only ':' and 'h' are allowed to separate hours from their minutes.\n", **s);
			return (ERROR);
		}
		++*s;
		while (**s == ' ') ++*s;
		if (!isdigit(**s) && hourmin_sep != 'h') {
			printf("Invalid syntax: expected number of minutes.\n");
			return (ERROR);
		}
		if ((mins_from = atoi(*s)) > 59) {
			printf("Invalid range: are you really sure that such a minute does exist in an hour?\n");
			return (ERROR);
		}
		while (isdigit(**s)) ++*s;
		while (**s == ' ') ++*s;
		if (**s == '+') {
			++*s;
			hours_to = 24;
			mins_to = 0;
		} else {
			if (**s != '-') {
				printf("Invalid syntax: expected range, separated by '-' token.\n");
				return (ERROR);
			}
			++*s;
			while (**s == ' ') ++*s;
			if (!isdigit(**s)) {
				printf("Invalid syntax: expected enclosing range hour.\n");
				return (ERROR);
			}
			if ((hours_to = atoi(*s)) > 47) {
				printf("Invalid range: the enclosing range hour need to be less than 48 (extended time).\n");
				return (ERROR);
			}
			while (isdigit(**s)) ++*s;
			if ((hourmin_sep = **s) != ':' && **s != 'h') {
				printf("Invalid syntax: unexpected token '%c'.\n                Only ':' and 'h' are allowed to separate hours from their minutes.", **s);
				return (ERROR);
			}
			++*s;
			while (**s == ' ') ++*s;
			if (!isdigit(**s) && hourmin_sep != 'h') {
				printf("Invalid syntax: expected number of minutes.\n");
				return (ERROR);
			}
			if ((mins_to = atoi(*s)) > 59) {
				printf("Invalid range: are you really sure that such a minute does exist in an hour?\n");
				return (ERROR);
			}
		}
		if (hours_to < hours_from || (hours_to == hours_from && mins_to <= mins_from)) {
			printf("Invalid range: the enclosing range hour needs to be greater than the opening hour.\n               If you want to mean the tomorrow's hour, please use the extended time syntax.\n               For this purpose, you can specify an enclosing range hour greater than 23.\n");
			while (**s != '-') --*s;
			while (!isdigit(**s)) ++*s;
			return (ERROR);
		}
		set_subset(selector->time_range, hours_from * 60 + mins_from, hours_to * 60 + mins_to - 1, true);
		if ((extended_hour = hours_to * 60 + mins_to - 24 * 60) > 0)
			set_subset(selector->extended_time_range, 0, extended_hour, true);
		while (isdigit(**s)) ++*s;
		while (**s == ' ') ++*s;
	} while (**s == ',' && *(++*s));
	return (SUCCESS);
}
int parse_weekday_selector(weekday_selector *selector, char **s) {
	char sep_char = 0,
		 weekday_id, weekday_to;

	selector->range = Bitset(7);

	do {
		while (**s == ' ') ++*s;
		if (strstr(*s, "SH ") == *s) {
			*s += sizeof("SH");
			if (**s != ' ' && **s != ',' && **s) {
				printf("Invalid syntax: if you want to select a single day holiday, you need\n                to put a space or a coma.\n");
				return (ERROR);
			}
			if ((sep_char = **s))
				++*s;
			selector->single_day_holiday = true;
		}
		while (**s == ' ') ++*s;
		if (strstr(*s, "PH ") == *s) {
			*s += sizeof("PH");
			if (**s != ' ' && **s != ',' && **s) {
				printf("Invalid syntax: if you want to select a plural day holiday, you need\n                to put a space or a coma.\n");
				return (ERROR);
			}
			if ((sep_char = **s))
				++*s;
			selector->plural_day_holiday = true;
		}
		if ((weekday_id = get_weekday_id(*s)) == 7) {
			if (sep_char == ',') {
				--*s;
				printf("Invalid selector: expected weekday.\n");
				return (ERROR);
			}
			set_subset(selector->range, 0, 6, true);
			return (EMPTY);
		}
		while (**s == ' ') ++*s;
		*s += 2;
		while (**s == ' ') ++*s;
		if (**s == '-') {
			++*s;
			while (**s == ' ') ++*s;
			if ((weekday_to = get_weekday_id(*s)) == 7) {
				printf("Invalid range: weekday range not enclosed by another weekday.\n");
				return (ERROR);
			}
			if (weekday_id < weekday_to)
				set_subset(selector->range, weekday_id, weekday_to, true);
			else {
				set_subset(selector->range, 0, 6, true);
				set_subset(selector->range, weekday_to + 1, weekday_id - 1, false);
			}
			*s += 2;
		} else {
			SET_BIT(selector->day, weekday_id, true);
			while (**s == ' ') ++*s;
			if (**s == '[') {
				while (**s == ' ') ++*s;
				if (**s < '1' || **s > '5') {
					printf("Invalid syntax: expected value between 1 and 5 included.\n               Expected nth of month selector.\n");
					return (ERROR);
				}
				selector->type = WD_NTH_OF_MONTH;
				selector->nth_of_month = **s - '0';
				++*s;
				while (**s == ' ') ++*s;
				if (**s != ']') {
					printf("Invalid syntax: unenclosed bracket. Expected ']' to enclose nth of month selector.\n");
					return (ERROR);
				}
			}
			while (**s == ' ') ++*s;
			if (**s == '-') {
				printf("Invalid syntax: unexpected token '-'. Cannot set a range involving nth of month.\n");
				return (ERROR);
			}
		}
		while (**s == ' ') ++*s;
	} while (**s == ',' && *(++*s));
	return (SUCCESS);
}