diff --git a/tools/.gitignore b/tools/.gitignore index 247a16f6..13e60142 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1 +1,2 @@ /bitread +/segmatch diff --git a/tools/Makefile b/tools/Makefile index 1d1420af..18d4ad20 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -2,13 +2,16 @@ # CXXFLAGS = -Wall -Wextra -O0 -ggdb CXXFLAGS = -Wall -Wextra -O3 -all: bitread +all: bitread segmatch bitread: bitread.cc clang $(CXXFLAGS) -static -std=c++11 -o $@ $< -lstdc++ +segmatch: segmatch.cc + clang $(CXXFLAGS) -static -std=c++11 -o $@ $< -lstdc++ + clean: - rm -f bitread + rm -f bitread segmatch .PHONY: all clean diff --git a/tools/segmatch.cc b/tools/segmatch.cc new file mode 100644 index 00000000..d4645698 --- /dev/null +++ b/tools/segmatch.cc @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::map; +using std::tuple; +using std::vector; +using std::string; + +int num_bits = 0, num_tags = 0; +map bit_ids, tag_ids; +vector bit_ids_r, tag_ids_r; + +// segname -> bits, tags_on, tags_off +typedef tuple, vector, vector> segdata_t; +map segdata; + +static inline vector &segdata_bits(segdata_t &sd) { return std::get<0>(sd); } +static inline vector &segdata_tags1(segdata_t &sd) { return std::get<1>(sd); } +static inline vector &segdata_tags0(segdata_t &sd) { return std::get<2>(sd); } + +void read_input() +{ + string token; + segdata_t *segptr = nullptr; + + while (std::cin >> token) + { + if (token == "seg") + { + std::cin >> token; + assert(segdata.count(token) == 0); + segptr = &segdata[token]; + continue; + } + + if (token == "bit") + { + assert(segptr != nullptr); + + std::cin >> token; + if (bit_ids.count(token) == 0) { + bit_ids[token] = num_bits++; + bit_ids_r.push_back(token); + } + + int bit_idx = bit_ids.at(token); + auto &bits = segdata_bits(*segptr); + + if (int(bits.size()) <= bit_idx) + bits.resize(bit_idx+1); + + bits[bit_idx] = true; + continue; + } + + if (token == "tag") + { + assert(segptr != nullptr); + + std::cin >> token; + if (tag_ids.count(token) == 0) { + tag_ids[token] = num_tags++; + tag_ids_r.push_back(token); + } + + int tag_idx = tag_ids.at(token); + + std::cin >> token; + assert(token == "0" || token == "1"); + + auto &tags = token == "1" ? segdata_tags1(*segptr) : segdata_tags0(*segptr); + + if (int(tags.size()) <= tag_idx) + tags.resize(tag_idx+1); + + tags[tag_idx] = true; + continue; + } + + abort(); + } + + // printf("Number of segments: %d\n", int(segdata.size())); + // printf("Number of bits: %d\n", num_bits); + // printf("Number of tags: %d\n", num_tags); + + for (auto &segdat : segdata) { + segdata_bits(segdat.second).resize(num_bits); + segdata_tags1(segdat.second).resize(num_tags); + segdata_tags0(segdat.second).resize(num_tags); + } +} + +void and_masks(vector &dst_mask, const vector &src_mask) +{ + assert(dst_mask.size() == src_mask.size()); + for (int i = 0; i < int(dst_mask.size()); i++) + dst_mask[i] = dst_mask[i] && src_mask[i]; +} + +void andc_masks(vector &dst_mask, const vector &src_mask) +{ + assert(dst_mask.size() == src_mask.size()); + for (int i = 0; i < int(dst_mask.size()); i++) + dst_mask[i] = dst_mask[i] && !src_mask[i]; +} + +int main(int argc, char **argv) +{ + int opt; + while ((opt = getopt(argc, argv, "")) != -1) + switch (opt) + { + // case 'c': + // mode_c = true; + // break; + // case 'r': + // mode_r = true; + // break; + // case 'm': + // mode_m = true; + // break; + // case 'x': + // mode_x = true; + // break; + // case 'y': + // mode_y = true; + // break; + // case 'z': + // mode_z = true; + // break; + // case 'C': + // chksum = true; + // break; + // case 'f': + // frames.insert(strtol(optarg, nullptr, 0)); + // break; + // case 'o': + // outfile = optarg; + // break; + default: + goto help; + } + + if (optind != argc) { +help: + fprintf(stderr, "\n"); + fprintf(stderr, "Usage: %s [options] < segdata.txt\n", argv[0]); + fprintf(stderr, "\n"); + // fprintf(stderr, " -c\n"); + // fprintf(stderr, " continuation mode. output '*' for repeating patterns\n"); + fprintf(stderr, "\n"); + return 1; + } + + read_input(); + + for (int tag_idx = 0; tag_idx < num_tags; tag_idx++) + { + vector mask(num_bits, true); + + for (auto &segdat : segdata) + { + auto &sd = segdat.second; + + if (segdata_tags1(sd).at(tag_idx)) { + and_masks(mask, segdata_bits(sd)); + continue; + } + + if (segdata_tags0(sd).at(tag_idx)) { + andc_masks(mask, segdata_bits(sd)); + continue; + } + } + + int num_candidates = std::accumulate(mask.begin(), mask.end(), 0); + + printf("%s", tag_ids_r.at(tag_idx).c_str()); + + if (0 < num_candidates && num_candidates <= 4) { + for (int bit_idx = 0; bit_idx < num_bits; bit_idx++) + if (mask.at(bit_idx)) + printf(" %s", bit_ids_r.at(bit_idx).c_str()); + printf("\n"); + } else { + printf(" <%d candidates>\n", num_candidates); + } + + assert(num_candidates != 0); + } + + return 0; +} +