final new version
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ccc
|
||||||
1
build.sh
Executable file
1
build.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
g++ ccc.cpp -o ccc -ltree-sitter -ltree-sitter-c -llzma -Ofast -march=native
|
||||||
740
ccc.cpp
Normal file
740
ccc.cpp
Normal file
@@ -0,0 +1,740 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <iterator>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <tree_sitter/api.h>
|
||||||
|
#include <tree_sitter/tree-sitter-c.h>
|
||||||
|
#include <lzma.h>
|
||||||
|
#include <xxh3.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
using namespace std;
|
||||||
|
namespace fs=filesystem;
|
||||||
|
const vector<bool> CCC_DELIMITER_0_HEAD={0};
|
||||||
|
const vector<bool> CCC_DELIMITER_1_HEAD={1,0};
|
||||||
|
const vector<bool> CCC_C_KEYWORD_HEAD={1,1,0,0};
|
||||||
|
const vector<bool> CCC_MISCELANEOUS_HEAD={1,1,0,1};
|
||||||
|
const vector<bool> CCC_STRING_INLINE_HEAD={1,1,1,0};
|
||||||
|
const vector<bool> CCC_REC_TABLE_REF_HEAD={1,1,1,1};
|
||||||
|
const vector<bool> CCC_STRING_INLINE_END={0,0,0,0,0,0,0,0};
|
||||||
|
#define CCC_ADD_COMPONENT(vec,tail) \
|
||||||
|
do { \
|
||||||
|
auto tmp=tail; \
|
||||||
|
vec.insert(vec.end(),tmp.begin(),tmp.end()); \
|
||||||
|
} while (0)
|
||||||
|
#define CCC_ADD_COMPONENT_ALIGNED(vec,tail) \
|
||||||
|
do { \
|
||||||
|
static_assert(is_same_v<decltype(vec),vector<bool>>,"vec must be vector<bool>"); \
|
||||||
|
static_assert(is_same_v<decltype(tail),vector<bool>>,"tail must be vector<bool>"); \
|
||||||
|
vec.reserve(vec.size()+tail.size()+8); \
|
||||||
|
for (auto b:tail) vec.push_back(b); \
|
||||||
|
size_t rem=vec.size()%8; \
|
||||||
|
if (rem!=0) { \
|
||||||
|
vec.insert(vec.end(),8-rem,false); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
struct XXH3HasherString {
|
||||||
|
size_t operator()(const std::string& s) const {
|
||||||
|
return static_cast<size_t>(XXH3_64bits(s.data(),s.size()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const vector<string> delimiter0={
|
||||||
|
"{",
|
||||||
|
"}",
|
||||||
|
"(",
|
||||||
|
")",
|
||||||
|
"[",
|
||||||
|
"]",
|
||||||
|
",",
|
||||||
|
"."
|
||||||
|
};
|
||||||
|
const vector<string> delimiter1={
|
||||||
|
"{}",
|
||||||
|
"()",
|
||||||
|
"[]",
|
||||||
|
";"
|
||||||
|
};
|
||||||
|
const vector<string> miscellaneous={
|
||||||
|
"!",
|
||||||
|
"%",
|
||||||
|
"'",
|
||||||
|
"*",
|
||||||
|
"+",
|
||||||
|
"-",
|
||||||
|
"/",
|
||||||
|
":",
|
||||||
|
"<",
|
||||||
|
">",
|
||||||
|
"=",
|
||||||
|
"?",
|
||||||
|
"^",
|
||||||
|
"|",
|
||||||
|
"&",
|
||||||
|
"~",
|
||||||
|
"+=",
|
||||||
|
"-=",
|
||||||
|
"*=",
|
||||||
|
"/=",
|
||||||
|
"%=",
|
||||||
|
"&=",
|
||||||
|
"|=",
|
||||||
|
"^=",
|
||||||
|
"<<=",
|
||||||
|
">>=",
|
||||||
|
"++",
|
||||||
|
"--",
|
||||||
|
"<<",
|
||||||
|
">>",
|
||||||
|
"==",
|
||||||
|
"!=",
|
||||||
|
"<=",
|
||||||
|
">=",
|
||||||
|
"->",
|
||||||
|
"...",
|
||||||
|
"||",
|
||||||
|
"&&",
|
||||||
|
"NULL",
|
||||||
|
"size_t",
|
||||||
|
"uint8_t",
|
||||||
|
"uint16_t",
|
||||||
|
"uint32_t",
|
||||||
|
"uint64_t",
|
||||||
|
"int8_t",
|
||||||
|
"int16_t",
|
||||||
|
"int32_t",
|
||||||
|
"int64_t"
|
||||||
|
};
|
||||||
|
const vector<string> c_keywords={
|
||||||
|
"#if",
|
||||||
|
"#ifdef",
|
||||||
|
"#ifndef",
|
||||||
|
"#else",
|
||||||
|
"#elif",
|
||||||
|
"#elifdef",
|
||||||
|
"#elifndef",
|
||||||
|
"#endif",
|
||||||
|
"#define",
|
||||||
|
"#undef",
|
||||||
|
"#include",
|
||||||
|
"#error",
|
||||||
|
"#warning",
|
||||||
|
"#pragma",
|
||||||
|
"#line",
|
||||||
|
"alignas",
|
||||||
|
"alignof",
|
||||||
|
"auto",
|
||||||
|
"bool",
|
||||||
|
"break",
|
||||||
|
"case",
|
||||||
|
"char",
|
||||||
|
"const",
|
||||||
|
"constexpr",
|
||||||
|
"continue",
|
||||||
|
"default",
|
||||||
|
"do",
|
||||||
|
"double",
|
||||||
|
"else",
|
||||||
|
"enum",
|
||||||
|
"extern",
|
||||||
|
"false",
|
||||||
|
"float",
|
||||||
|
"for",
|
||||||
|
"goto",
|
||||||
|
"if",
|
||||||
|
"inline",
|
||||||
|
"int",
|
||||||
|
"long",
|
||||||
|
"nullptr",
|
||||||
|
"register",
|
||||||
|
"restrict",
|
||||||
|
"return",
|
||||||
|
"short",
|
||||||
|
"signed",
|
||||||
|
"sizeof",
|
||||||
|
"static",
|
||||||
|
"static_assert",
|
||||||
|
"struct",
|
||||||
|
"switch",
|
||||||
|
"thread_local",
|
||||||
|
"true",
|
||||||
|
"typedef",
|
||||||
|
"typeof",
|
||||||
|
"typeof_unequal",
|
||||||
|
"union",
|
||||||
|
"unsigned",
|
||||||
|
"void",
|
||||||
|
"volatile",
|
||||||
|
"while",
|
||||||
|
"__asm__",
|
||||||
|
"__attribute__",
|
||||||
|
"defined",
|
||||||
|
};
|
||||||
|
struct symbol {
|
||||||
|
string name;
|
||||||
|
int score;
|
||||||
|
};
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct header {
|
||||||
|
uint8_t sig[3];
|
||||||
|
uint8_t flags;
|
||||||
|
size_t size_rec_table;
|
||||||
|
size_t entry_count;
|
||||||
|
size_t size_payload;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
struct node {
|
||||||
|
uint16_t type;
|
||||||
|
uint32_t start;
|
||||||
|
uint32_t end;
|
||||||
|
};
|
||||||
|
unordered_map<string,uint16_t,XXH3HasherString> optimized_type_u16_list;
|
||||||
|
unordered_map<uint16_t,string> type_map;
|
||||||
|
vector<vector<node>> all_tokens;
|
||||||
|
map<string,int> rec_map;
|
||||||
|
vector<string> rec_list;
|
||||||
|
unordered_map<string,size_t,XXH3HasherString> rec_lookup;
|
||||||
|
unordered_map<string,size_t,XXH3HasherString> c_keyword_lookup;
|
||||||
|
unordered_map<string,size_t,XXH3HasherString> miscelaneous_lookup;
|
||||||
|
unordered_map<string,size_t,XXH3HasherString> delimiter0_lookup;
|
||||||
|
unordered_map<string,size_t,XXH3HasherString> delimiter1_lookup;
|
||||||
|
bool debug=false;
|
||||||
|
bool fail_on_warning=false;
|
||||||
|
static uint16_t next_type_id;
|
||||||
|
void get_all_nodes(TSNode node,const string &source_code,map<string,int> &rec_map,size_t index) {
|
||||||
|
if (ts_node_child_count(node)==0) {
|
||||||
|
string text=source_code.substr(ts_node_start_byte(node),ts_node_end_byte(node)-ts_node_start_byte(node));
|
||||||
|
string type=string(ts_node_type(node));
|
||||||
|
if (optimized_type_u16_list.find(type)==optimized_type_u16_list.end()) {
|
||||||
|
optimized_type_u16_list[type]=next_type_id;
|
||||||
|
type_map[optimized_type_u16_list.at(type)]=type;
|
||||||
|
next_type_id++;
|
||||||
|
}
|
||||||
|
all_tokens[index].push_back({.type=optimized_type_u16_list[type],.start=ts_node_start_byte(node),.end=ts_node_end_byte(node)});
|
||||||
|
if (type=="string_content" || type=="system_lib_string" || type=="identifier" || type=="number_literal" || type=="type_identifier" || type=="field_identifier" || type=="escape_sequence" || type=="statement_identifier") {
|
||||||
|
rec_map[text]++;
|
||||||
|
}
|
||||||
|
if (type=="primitive_type" && find(c_keywords.begin(),c_keywords.end(),text)==c_keywords.end()) {
|
||||||
|
rec_map[text]++;
|
||||||
|
}
|
||||||
|
if (type=="comment") {
|
||||||
|
rec_map[text]=2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint32_t child_count=ts_node_child_count(node);
|
||||||
|
for (uint32_t i=0;i<child_count;++i) {
|
||||||
|
TSNode child=ts_node_child(node,i);
|
||||||
|
get_all_nodes(child,source_code,rec_map,index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<bool> byte_to_bits(unsigned char c) {
|
||||||
|
vector<bool> out;
|
||||||
|
for (int i=7;i>=0;i--) {
|
||||||
|
bool enabled=(c>>i)&0x01;
|
||||||
|
out.push_back(enabled);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
vector<bool> generate_c_keyword(size_t index) {
|
||||||
|
vector<bool> out;
|
||||||
|
CCC_ADD_COMPONENT(out,CCC_C_KEYWORD_HEAD);
|
||||||
|
for (int i=5;i>=0;i--) {
|
||||||
|
bool enabled=(index>>i)&0x01;
|
||||||
|
out.push_back(enabled);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
vector<bool> generate_rec(size_t index,size_t total_recs) {
|
||||||
|
vector<bool> out;
|
||||||
|
size_t bits=0;
|
||||||
|
while (total_recs) {
|
||||||
|
total_recs>>=1;
|
||||||
|
++bits;
|
||||||
|
}
|
||||||
|
CCC_ADD_COMPONENT(out,CCC_REC_TABLE_REF_HEAD);
|
||||||
|
for (int i=bits;i>=0;i--) {
|
||||||
|
bool enabled=(index>>i)&0x01;
|
||||||
|
out.push_back(enabled);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
vector<bool> generate_delimiter0(size_t index) {
|
||||||
|
vector<bool> out;
|
||||||
|
CCC_ADD_COMPONENT(out,CCC_DELIMITER_0_HEAD);
|
||||||
|
for (int i=2;i>=0;i--) {
|
||||||
|
bool enabled=(index>>i)&0x01;
|
||||||
|
out.push_back(enabled);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
vector<bool> generate_delimiter1(size_t index) {
|
||||||
|
vector<bool> out;
|
||||||
|
CCC_ADD_COMPONENT(out,CCC_DELIMITER_1_HEAD);
|
||||||
|
for (int i=1;i>=0;i--) {
|
||||||
|
bool enabled=(index>>i)&0x01;
|
||||||
|
out.push_back(enabled);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
vector<bool> generate_miscellaneous(size_t index) {
|
||||||
|
vector<bool> out;
|
||||||
|
CCC_ADD_COMPONENT(out,CCC_MISCELANEOUS_HEAD);
|
||||||
|
for (int i=5;i>=0;i--) {
|
||||||
|
bool enabled=(index>>i)&0x01;
|
||||||
|
out.push_back(enabled);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
vector<bool> generate_string_content(string str) {
|
||||||
|
vector<bool> out;
|
||||||
|
CCC_ADD_COMPONENT(out,CCC_STRING_INLINE_HEAD);
|
||||||
|
for (auto c:str) {
|
||||||
|
CCC_ADD_COMPONENT(out,byte_to_bits(c));
|
||||||
|
}
|
||||||
|
CCC_ADD_COMPONENT(out,CCC_STRING_INLINE_END);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
void print_debug(string text) {
|
||||||
|
if (debug==true) {
|
||||||
|
cout<<text<<endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void fail_if_warning() {
|
||||||
|
if (fail_on_warning) {
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<unsigned char> process_file_nodes(vector<node> *nodes,string code) {
|
||||||
|
vector<bool> out;
|
||||||
|
for (int i=0;i<nodes->size();i++) {
|
||||||
|
node n=nodes->at(i);
|
||||||
|
string type=type_map[n.type];
|
||||||
|
string text=code.substr(n.start,n.end-n.start);
|
||||||
|
if (type=="string_content" || type=="system_lib_string" || type=="identifier" || type=="number_literal" || type=="field_identifier" || type=="preproc_arg" || type=="escape_sequence" || type=="character" || type=="statement_identifier") {
|
||||||
|
auto it=rec_lookup.find(text);
|
||||||
|
if (it==rec_lookup.end()) {
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_string_content(text));
|
||||||
|
print_debug("string ("+type+"): "+text);
|
||||||
|
} else {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_rec(index,rec_list.size()));
|
||||||
|
print_debug("rec_table for string ("+type+"): "+text);
|
||||||
|
}
|
||||||
|
} else if (type=="primitive_type" || type=="type_identifier") {
|
||||||
|
auto it=c_keyword_lookup.find(text);
|
||||||
|
if (it!=c_keyword_lookup.end()) {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_c_keyword(index));
|
||||||
|
print_debug("type found in c keyword: "+text);
|
||||||
|
} else {
|
||||||
|
auto it=rec_lookup.find(text);
|
||||||
|
if (it==rec_lookup.end()) {
|
||||||
|
if (!text.empty()) {
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_string_content(text));
|
||||||
|
print_debug("string for type ("+type+"): "+text);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: type node is empty: "<<text<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_rec(index,rec_list.size()));
|
||||||
|
print_debug("rec_table for string for type ("+type+"): "+text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (delimiter0_lookup.find(type)!=delimiter0_lookup.end() || delimiter1_lookup.find(type)!=delimiter1_lookup.end() || type=="\"") {
|
||||||
|
string insert;
|
||||||
|
if (type=="(" && i+1<nodes->size()) {
|
||||||
|
if (type_map[nodes->at(i+1).type]==")") {
|
||||||
|
insert="()";
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
insert="(";
|
||||||
|
}
|
||||||
|
} else if (type=="[" && i+1<nodes->size()) {
|
||||||
|
if (type_map[nodes->at(i+1).type]=="]") {
|
||||||
|
insert="[]";
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
insert="[";
|
||||||
|
}
|
||||||
|
} else if (type=="{" && i+1<nodes->size()) {
|
||||||
|
if (type_map[nodes->at(i+1).type]=="}") {
|
||||||
|
insert="{}";
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
insert="{";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
insert=type;
|
||||||
|
}
|
||||||
|
auto it=delimiter0_lookup.find(insert);
|
||||||
|
if (it!=delimiter0_lookup.end()) {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_delimiter0(index));
|
||||||
|
print_debug("delimiter 0: "+insert);
|
||||||
|
} else {
|
||||||
|
if (insert!="{}" && insert!="\"") {
|
||||||
|
auto it=delimiter1_lookup.find(insert);
|
||||||
|
if (it!=delimiter1_lookup.end()) {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_delimiter1(index));
|
||||||
|
print_debug("delimiter 1: "+insert);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: unknow delimiter, that shouldn't happen: "<<insert<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (insert=="{}") {
|
||||||
|
auto it=delimiter1_lookup.find("{}");
|
||||||
|
if (it!=delimiter1_lookup.end()) {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT(out,generate_delimiter1(index));
|
||||||
|
vector<bool> temp={0};
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,temp);
|
||||||
|
print_debug("delimiter 1: "+insert);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: unknow delimiter, that shouldn't happen: "<<insert<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else if (insert=="\"") {
|
||||||
|
auto it=delimiter1_lookup.find("{}");
|
||||||
|
if (it!=delimiter1_lookup.end()) {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT(out,generate_delimiter1(index));
|
||||||
|
vector<bool> temp={1};
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,temp);
|
||||||
|
print_debug("delimiter 1: "+insert);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: unknow delimiter, that shouldn't happen: "<<insert<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: unknow delimiter, that shouldn't happen: "<<insert<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (c_keyword_lookup.find(type)!=c_keyword_lookup.end() || type=="preproc_directive") {
|
||||||
|
if (type!="preproc_directive") {
|
||||||
|
auto it=c_keyword_lookup.find(type);
|
||||||
|
if (it!=c_keyword_lookup.end()) {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_c_keyword(index));
|
||||||
|
print_debug("c keyword: "+type);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: unknow C keyword, that shouldn't happen: "<<type<<" "<<text<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto it=c_keyword_lookup.find(text);
|
||||||
|
if (it!=c_keyword_lookup.end()) {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_c_keyword(index));
|
||||||
|
print_debug("c keyword: "+type);
|
||||||
|
} else {
|
||||||
|
auto it=rec_lookup.find(text);
|
||||||
|
if (it==rec_lookup.end()) {
|
||||||
|
if (!text.empty()) {
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_string_content(text));
|
||||||
|
print_debug("string for c keyword ("+type+"): "+text);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: C keyword is empty: "<<text<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_rec(index,rec_list.size()));
|
||||||
|
print_debug("rec_table for string for c keyword ("+type+"): "+text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (miscelaneous_lookup.find(type)!=miscelaneous_lookup.end()) {
|
||||||
|
auto it=miscelaneous_lookup.find(type);
|
||||||
|
if (it!=miscelaneous_lookup.end()) {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_miscellaneous(index));
|
||||||
|
print_debug("miscellaneous: "+type);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: unknow miscellaneous, that shouldn't happen: "<<type<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else if (type=="comment") {
|
||||||
|
auto it=rec_lookup.find(text);
|
||||||
|
if (it==rec_lookup.end()) {
|
||||||
|
if (!text.empty()) {
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_string_content(text));
|
||||||
|
print_debug("string for comment("+type+"): "+text);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: comment is empty: "<<text<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_rec(index,rec_list.size()));
|
||||||
|
print_debug("rec_table for comment");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto it=rec_lookup.find(type);
|
||||||
|
if (it==rec_lookup.end()) {
|
||||||
|
if (!text.empty()) {
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_string_content(text));
|
||||||
|
print_debug("string for unknow node ("+type+"): "+text);
|
||||||
|
} else {
|
||||||
|
cout<<"Warning: unknow node is empty: "<<text<<endl;
|
||||||
|
fail_if_warning();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t index=it->second;
|
||||||
|
CCC_ADD_COMPONENT_ALIGNED(out,generate_rec(index,rec_list.size()));
|
||||||
|
print_debug("rec_table for string for unknow node ("+type+"): "+text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<unsigned char> payload_bytes;
|
||||||
|
unsigned char current=0;
|
||||||
|
size_t bit_index=0;
|
||||||
|
for (bool b:out) {
|
||||||
|
current|=(b<<(7-bit_index));
|
||||||
|
bit_index++;
|
||||||
|
if (bit_index==8) {
|
||||||
|
payload_bytes.push_back(current);
|
||||||
|
current=0;
|
||||||
|
bit_index=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bit_index!=0) {
|
||||||
|
payload_bytes.push_back(current);
|
||||||
|
}
|
||||||
|
return payload_bytes;
|
||||||
|
}
|
||||||
|
void construct_rec_table(vector<string> &files_content,vector<string> files_names) {
|
||||||
|
for (int i=0;i<files_content.size();i++) {
|
||||||
|
TSParser *parser=ts_parser_new();
|
||||||
|
ts_parser_set_language(parser,tree_sitter_c());
|
||||||
|
TSTree *tree=ts_parser_parse_string(parser,nullptr,files_content[i].c_str(),files_content[i].size());
|
||||||
|
TSNode root=ts_tree_root_node(tree);
|
||||||
|
get_all_nodes(root,files_content[i],rec_map,i);
|
||||||
|
ts_tree_delete(tree);
|
||||||
|
ts_parser_delete(parser);
|
||||||
|
cout<<i+1<<" file(s) parsed on "<<files_names.size()<<": "<<files_names[i]<<endl;
|
||||||
|
}
|
||||||
|
for (auto s:rec_map) {
|
||||||
|
if (s.second>=2 and s.first.size()>=3) {
|
||||||
|
rec_list.push_back(s.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i=0;i<rec_list.size();i++) {
|
||||||
|
rec_lookup[rec_list[i]]=i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int main(int argc,char **argv) {
|
||||||
|
for (int i=0;i<c_keywords.size();i++) {
|
||||||
|
c_keyword_lookup[c_keywords[i]]=i;
|
||||||
|
}
|
||||||
|
for (int i=0;i<miscellaneous.size();i++) {
|
||||||
|
miscelaneous_lookup[miscellaneous[i]]=i;
|
||||||
|
}
|
||||||
|
for (int i=0;i<delimiter0.size();i++) {
|
||||||
|
delimiter0_lookup[delimiter0[i]]=i;
|
||||||
|
}
|
||||||
|
for (int i=0;i<delimiter1.size();i++) {
|
||||||
|
delimiter1_lookup[delimiter1[i]]=i;
|
||||||
|
}
|
||||||
|
if (argc<2) {
|
||||||
|
cout<<"Usage: ccc [FILES]"<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
vector<string> files;
|
||||||
|
for (int i=1;i<argc;i++) {
|
||||||
|
string file=string(argv[i]);
|
||||||
|
if (file=="-v") {
|
||||||
|
debug=true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (file=="-w") {
|
||||||
|
fail_on_warning=true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!fs::exists(file)) {
|
||||||
|
cout<<"Error: file doesn't exist: "<<file<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
files.push_back(file);
|
||||||
|
}
|
||||||
|
vector<string> files_content;
|
||||||
|
for (int i=0;i<files.size();i++) {
|
||||||
|
ifstream file(files[i],ios::binary);
|
||||||
|
if (!file) {
|
||||||
|
cout<<"Error: couldn't open provided file."<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
string code((istreambuf_iterator<char>(file)),istreambuf_iterator<char>());
|
||||||
|
files_content.push_back(code);
|
||||||
|
cout<<i+1<<" file(s) readed on "<<files.size()<<": "<<files[i]<<endl;
|
||||||
|
}
|
||||||
|
all_tokens.resize(files_content.size());
|
||||||
|
construct_rec_table(files_content,files);
|
||||||
|
vector<unsigned char> files_archive;
|
||||||
|
vector<size_t> payloads_size;
|
||||||
|
vector<size_t> payloads_start;
|
||||||
|
for (int i=0;i<files_content.size();i++) {
|
||||||
|
auto payload_bytes=process_file_nodes(&(all_tokens[i]),files_content[i]);
|
||||||
|
payloads_size.push_back(payload_bytes.size());
|
||||||
|
payloads_start.push_back(files_archive.size());
|
||||||
|
CCC_ADD_COMPONENT(files_archive,payload_bytes);
|
||||||
|
cout<<i+1<<" file(s) encoded on "<<files.size()<<": "<<files[i]<<endl;
|
||||||
|
}
|
||||||
|
vector<unsigned char> payload_compressed;
|
||||||
|
payload_compressed.resize(files_archive.size()+files_archive.size()/3+128);
|
||||||
|
lzma_stream strm=LZMA_STREAM_INIT;
|
||||||
|
if (lzma_easy_encoder(&strm,9,LZMA_CHECK_CRC64)!=LZMA_OK) {
|
||||||
|
cout<<"Error: couldn't initialize LZMA compressor for file archive."<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strm.next_in=files_archive.data();
|
||||||
|
strm.avail_in=files_archive.size();
|
||||||
|
strm.next_out=payload_compressed.data();
|
||||||
|
strm.avail_out=payload_compressed.size();
|
||||||
|
auto ret=lzma_code(&strm,LZMA_FINISH);
|
||||||
|
if (ret!=LZMA_STREAM_END) {
|
||||||
|
cout<<"Error: couldn't compress file archive."<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cout<<"Compressed payloads."<<endl;
|
||||||
|
size_t payload_total_size;
|
||||||
|
size_t compressed_size=payload_compressed.size()-strm.avail_out;
|
||||||
|
payload_compressed.resize(compressed_size);
|
||||||
|
size_t original_size=files_archive.size();
|
||||||
|
lzma_end(&strm);
|
||||||
|
uint8_t flags=0;
|
||||||
|
if (compressed_size>=original_size) {
|
||||||
|
flags&= ~(0b00000001);
|
||||||
|
payload_total_size=original_size;
|
||||||
|
} else {
|
||||||
|
flags|=0b00000001;
|
||||||
|
payload_total_size=compressed_size;
|
||||||
|
}
|
||||||
|
vector<unsigned char> rec_table;
|
||||||
|
for (int i=0;i<rec_list.size();i++) {
|
||||||
|
for (auto c:rec_list[i]) {
|
||||||
|
rec_table.push_back(c);
|
||||||
|
}
|
||||||
|
rec_table.push_back('\0');
|
||||||
|
}
|
||||||
|
vector<unsigned char> rec_table_compressed;
|
||||||
|
rec_table_compressed.resize(rec_table.size()+rec_table.size()/3+128);
|
||||||
|
strm=LZMA_STREAM_INIT;
|
||||||
|
if (lzma_easy_encoder(&strm,9,LZMA_CHECK_CRC64)!=LZMA_OK) {
|
||||||
|
cout<<"Error: couldn't initialize LZMA compressor for reccurences table."<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strm.next_in=rec_table.data();
|
||||||
|
strm.avail_in=rec_table.size();
|
||||||
|
strm.next_out=rec_table_compressed.data();
|
||||||
|
strm.avail_out=rec_table_compressed.size();
|
||||||
|
ret=lzma_code(&strm,LZMA_FINISH);
|
||||||
|
if (ret!=LZMA_STREAM_END) {
|
||||||
|
cout<<"Error: couldn't compress reccurences table."<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cout<<"Compressed reccurences table."<<endl;
|
||||||
|
size_t rec_table_total_size;
|
||||||
|
compressed_size=rec_table_compressed.size()-strm.avail_out;
|
||||||
|
rec_table_compressed.resize(compressed_size);
|
||||||
|
original_size=rec_table.size();
|
||||||
|
lzma_end(&strm);
|
||||||
|
if (compressed_size>=original_size) {
|
||||||
|
flags&= ~(0b00000010);
|
||||||
|
rec_table_total_size=original_size;
|
||||||
|
} else {
|
||||||
|
flags|=0b00000010;
|
||||||
|
rec_table_total_size=compressed_size;
|
||||||
|
}
|
||||||
|
vector<unsigned char> files_table;
|
||||||
|
for (int i=0;i<files.size();i++) {
|
||||||
|
for (auto c:files[i]) {
|
||||||
|
files_table.push_back(c);
|
||||||
|
}
|
||||||
|
files_table.push_back('\0');
|
||||||
|
auto file_start=payloads_start[i];
|
||||||
|
for (int i=0;i<sizeof(size_t);++i) {
|
||||||
|
files_table.push_back(((uint8_t*)&file_start)[i]);
|
||||||
|
}
|
||||||
|
auto file_size=payloads_size[i];
|
||||||
|
for (int i=0;i<sizeof(size_t);++i) {
|
||||||
|
files_table.push_back(((uint8_t*)&file_size)[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<unsigned char> files_table_compressed;
|
||||||
|
files_table_compressed.resize(files_table.size()+files_table.size()/3+128);
|
||||||
|
strm=LZMA_STREAM_INIT;
|
||||||
|
if (lzma_easy_encoder(&strm,9,LZMA_CHECK_CRC64)!=LZMA_OK) {
|
||||||
|
cout<<"Error: couldn't initialize LZMA compressor for files table."<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strm.next_in=files_table.data();
|
||||||
|
strm.avail_in=files_table.size();
|
||||||
|
strm.next_out=files_table_compressed.data();
|
||||||
|
strm.avail_out=files_table_compressed.size();
|
||||||
|
ret=lzma_code(&strm,LZMA_FINISH);
|
||||||
|
if (ret!=LZMA_STREAM_END) {
|
||||||
|
cout<<"Error: couldn't compress files table."<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cout<<"Compressed files table."<<endl;
|
||||||
|
size_t files_table_total_size;
|
||||||
|
compressed_size=files_table_compressed.size()-strm.avail_out;
|
||||||
|
files_table_compressed.resize(compressed_size);
|
||||||
|
original_size=files_table.size();
|
||||||
|
lzma_end(&strm);
|
||||||
|
if (compressed_size>=original_size) {
|
||||||
|
flags&= ~(0b00000100);
|
||||||
|
files_table_total_size=original_size;
|
||||||
|
} else {
|
||||||
|
flags|=0b00000100;
|
||||||
|
files_table_total_size=compressed_size;
|
||||||
|
}
|
||||||
|
header head;
|
||||||
|
head.sig[0]='C';
|
||||||
|
head.sig[1]='C';
|
||||||
|
head.sig[2]='C';
|
||||||
|
head.flags=flags;
|
||||||
|
head.size_payload=payload_total_size;
|
||||||
|
head.size_rec_table=rec_table_total_size;
|
||||||
|
head.entry_count=files.size();
|
||||||
|
vector<unsigned char> out;
|
||||||
|
for (int i=0;i<sizeof(header);i++) {
|
||||||
|
out.push_back(((uint8_t*)&head)[i]);
|
||||||
|
}
|
||||||
|
if (flags & 0b00000010) {
|
||||||
|
CCC_ADD_COMPONENT(out,rec_table_compressed);
|
||||||
|
} else {
|
||||||
|
CCC_ADD_COMPONENT(out,rec_table);
|
||||||
|
}
|
||||||
|
if (flags & 0b00000100) {
|
||||||
|
CCC_ADD_COMPONENT(out,files_table_compressed);
|
||||||
|
} else {
|
||||||
|
CCC_ADD_COMPONENT(out,files_table);
|
||||||
|
}
|
||||||
|
if (flags & 0b00000001) {
|
||||||
|
CCC_ADD_COMPONENT(out,payload_compressed);
|
||||||
|
} else {
|
||||||
|
CCC_ADD_COMPONENT(out,files_archive);
|
||||||
|
}
|
||||||
|
ofstream fileout("test.ccc",ios::binary);
|
||||||
|
if (!fileout) {
|
||||||
|
cout<<"Error: couldn't open output file."<<endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fileout.write(reinterpret_cast<const char*>(out.data()),out.size());
|
||||||
|
fileout.close();
|
||||||
|
cout<<"Finished !"<<endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user