diff --git a/.github/workflows/main_tests_on_raspberry_pi_os_arm64.yml b/.github/workflows/main_tests_on_raspberry_pi_os_arm64.yml index a7e08853..479f7b6e 100755 --- a/.github/workflows/main_tests_on_raspberry_pi_os_arm64.yml +++ b/.github/workflows/main_tests_on_raspberry_pi_os_arm64.yml @@ -8,14 +8,15 @@ on: jobs: Build-and-Test: - runs-on: ubuntu-24.04 +# runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-arm steps: - name: checkout repository uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 +# - name: Set up QEMU +# uses: docker/setup-qemu-action@v3 - name: Install build tools run: | diff --git a/sstd/src/file/yaml.cpp b/sstd/src/file/yaml.cpp index 994a8f7f..bd042d28 100644 --- a/sstd/src/file/yaml.cpp +++ b/sstd/src/file/yaml.cpp @@ -32,6 +32,7 @@ printf("command:\n"); \ printf(" type: %d\n", rhs.type); \ printf(" format: %d\n", rhs.format); \ + printf(" ref_type: %d\n", rhs.ref_type); \ printf(" list_type_cnt: %d\n", rhs.list_type_cnt); \ printf(" hsc_lx: %d\n", rhs.hsc_lx); \ printf(" hsc_hx: %d\n", rhs.hsc_hx); \ @@ -43,14 +44,12 @@ printf(" mult_line_val: %s\n", (rhs.mult_line_val?"ture":"false")); \ printf(" key: `%s`\n", rhs.key.c_str()); \ printf(" val: `%s`\n", rhs.val.c_str()); \ + printf("anchor and alias:\n"); \ + printf(" ref_type: %d\n", rhs.ref_type); \ + printf(" aa_val: `%s`\n", rhs.aa_val.c_str()); \ printf(",\n"); -void sstd::print(const sstd_yaml::token& rhs){ - sstd_print_token_base(rhs); - printf("\n"); -} -void sstd::for_printn(const sstd_yaml::token& rhs){ printf(" = "); sstd::print(rhs); } -void sstd::print_for_vT(const sstd_yaml::token& rhs){ +void sstd::print_base(const sstd_yaml::token& rhs){ sstd_print_token_base(rhs); } @@ -70,16 +69,15 @@ void sstd::print_for_vT(const sstd_yaml::token& rhs){ printf(" type: %d\n", rhs.type); \ printf(" format: %d\n", rhs.format); \ printf(" val: `%s`\n", rhs.val.c_str()); \ + printf("anchor and alias:\n"); \ + printf(" ref_type: %d\n", rhs.ref_type); \ + printf(" aa_val: `%s`\n", rhs.aa_val.c_str()); \ printf(",\n"); -void sstd::print(const sstd_yaml::command& rhs){ +void sstd::print_base(const sstd_yaml::command& rhs){ sstd_print_command_v2_base(rhs); printf("\n"); } -void sstd::for_printn(const sstd_yaml::command& rhs){ printf(" = "); sstd::print(rhs); } -void sstd::print_for_vT(const sstd_yaml::command& rhs){ - sstd_print_command_v2_base(rhs); -} #undef sstd_print_command_v2_base @@ -146,7 +144,8 @@ std::string _rm_comment(const std::string& s){ return sstd::rstrip(v[0]); } -//--- +//----------------------------------------------------------------------------------------------------------------------------------------------- +// _format_mult_line_str() section std::string _join_mult_line(const std::vector& v, const bool ret_pipeSymbol, const bool ret_greaterThanSymbol){ std::string ret; @@ -313,7 +312,7 @@ bool sstd_yaml::_format_mult_line_str(std::string& ret_str, const std::string& s v_tmp.push_back(tmp); } - + if((!ret_plusSymbol) && (!ret_minusSymbol)){ // "|N" or ">N" @@ -343,6 +342,9 @@ bool sstd_yaml::_format_mult_line_str(std::string& ret_str, const std::string& s return true; } +//----------------------------------------------------------------------------------------------------------------------------------------------- +// _token2cmd() section + bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, const std::vector& v_token){ for(uint i=0; i& ret_vCmd, con // Construct alloc() or assign() command struct sstd_yaml::command c; switch(t.type){ - case sstd_yaml::num_str: { + case sstd_yaml::type_str: { // --- debug info --- c.line_num_begin = t.line_num_begin; c.line_num_end = t.line_num_end; @@ -359,12 +361,12 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_assign; c.hsc = t.hsc_hx; // t.hsc_lx - c.type = sstd_yaml::num_str; + c.type = sstd_yaml::type_str; c.format = t.format; c.val = t.val; // t.key; ret_vCmd.push_back(c); } break; - case sstd_yaml::num_list: { + case sstd_yaml::type_list: { { // --- debug info --- c.line_num_begin = t.line_num_begin; @@ -373,12 +375,20 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_alloc; c.hsc = t.hsc_lx; // t.hsc_hx - c.type = sstd_yaml::num_list; + c.type = sstd_yaml::type_list; //c.format = t.format; //c.val = t.val; // t.key; + // --- anchor and alias --- + if(t.ref_type==sstd_yaml::ref_type_anchor){ + c.ref_type = t.ref_type; + c.aa_val = t.aa_val; + }else if(t.ref_type==sstd_yaml::ref_type_alias){ + c.ref_type = t.ref_type; + c.aa_val = t.aa_val; + } ret_vCmd.push_back(c); } - + if(t.hasValue){ // check the value is NOT NULL // --- debug info --- c.line_num_begin = t.line_num_begin; @@ -387,13 +397,16 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_assign; c.hsc = t.hsc_hx; // t.hsc_lx; - c.type = sstd_yaml::num_str; + c.type = sstd_yaml::type_str; c.format = t.format; c.val = t.val; // t.key; + // --- anchor and alias --- + c.ref_type = sstd_yaml::ref_type_null; + c.aa_val = ""; ret_vCmd.push_back(c); } } break; - case sstd_yaml::num_hash: { + case sstd_yaml::type_hash: { // --- debug info --- c.line_num_begin = t.line_num_begin; c.line_num_end = t.line_num_end; @@ -401,9 +414,17 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_alloc; c.hsc = t.hsc_hx; // t.hsc_lx - c.type = sstd_yaml::num_hash; + c.type = sstd_yaml::type_hash; //c.format = t.format; c.val = t.key; // t.val; // key + // --- anchor and alias --- + if(t.ref_type==sstd_yaml::ref_type_anchor){ + c.ref_type = t.ref_type; + c.aa_val = t.aa_val; + }else if(t.ref_type==sstd_yaml::ref_type_alias){ + c.ref_type = t.ref_type; + c.aa_val = t.aa_val; + } ret_vCmd.push_back(c); if(t.hasValue){ // check the value is NOT NULL @@ -414,13 +435,16 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_assign; c.hsc = t.hsc_hx + 2; // t.hsc_lx; - c.type = sstd_yaml::num_str; + c.type = sstd_yaml::type_str; c.format = t.format; c.val = t.val; // t.key; // value + // --- anchor and alias --- + c.ref_type = sstd_yaml::ref_type_null; + c.aa_val = ""; ret_vCmd.push_back(c); } } break; - case sstd_yaml::num_list_and_hash:{ + case sstd_yaml::type_list_and_hash:{ { // --- debug info --- c.line_num_begin = t.line_num_begin; @@ -429,10 +453,18 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_alloc; c.hsc = t.hsc_lx; // t.hsc_hx + 2*ti - c.type = sstd_yaml::num_list; + c.type = sstd_yaml::type_list; //c.format = t.format; //c.val = t.val; // t.key; ret_vCmd.push_back(c); + // --- anchor and alias --- + if(t.ref_type==sstd_yaml::ref_type_anchor){ + c.ref_type = t.ref_type; + c.aa_val = t.aa_val; + }else if(t.ref_type==sstd_yaml::ref_type_alias){ + c.ref_type = t.ref_type; + c.aa_val = t.aa_val; + } } { @@ -456,7 +488,7 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_alloc; c.hsc = t.hsc_hx; // hsc_lx - c.type = sstd_yaml::num_hash; + c.type = sstd_yaml::type_hash; //c.format = t.format; c.val = t.key; // t.val; // key ret_vCmd.push_back(c); @@ -469,7 +501,7 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_assign; c.hsc = t.hsc_hx + 2; // t.hsc_lx; - c.type = sstd_yaml::num_str; + c.type = sstd_yaml::type_str; c.format = t.format; c.val = t.val; // t.key; // value ret_vCmd.push_back(c); @@ -480,7 +512,7 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // construction of stack() command - if( !t.hasValue && (t.type==sstd_yaml::num_list || t.type==sstd_yaml::num_hash || t.type==sstd_yaml::num_list_and_hash )){ + if( !t.hasValue && (t.type==sstd_yaml::type_list || t.type==sstd_yaml::type_hash || t.type==sstd_yaml::type_list_and_hash )){ uint hsc_curr = c.hsc; uint hsc_next = 0; @@ -495,11 +527,11 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con const sstd_yaml::token& t_nx = v_token[i+1]; // _nx: next switch(t_nx.type){ - //case sstd_yaml::num_str: { hsc_next = t_nx.hsc_hx; } break; - case sstd_yaml::num_str: { continue; } break; - case sstd_yaml::num_list: { hsc_next = t_nx.hsc_lx + 2*(t_nx.list_type_cnt-1); } break; - case sstd_yaml::num_hash: { hsc_next = t_nx.hsc_hx; } break; - case sstd_yaml::num_list_and_hash: { hsc_next = t_nx.hsc_lx + 2*(t_nx.list_type_cnt-1); } break; // works as a list + //case sstd_yaml::type_str: { hsc_next = t_nx.hsc_hx; } break; + case sstd_yaml::type_str: { continue; } break; + case sstd_yaml::type_list: { hsc_next = t_nx.hsc_lx + 2*(t_nx.list_type_cnt-1); } break; + case sstd_yaml::type_hash: { hsc_next = t_nx.hsc_hx; } break; + case sstd_yaml::type_list_and_hash: { hsc_next = t_nx.hsc_lx + 2*(t_nx.list_type_cnt-1); } break; // works as a list default: { sstd::pdbg_err("Unexpected data type\n"); return false; } break; }; @@ -521,8 +553,8 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // │ t │ │ │ │ │ // └───┴───────────────────┴───────────────────┴───────────────────┴───────────────────┘ // - bool isGr = t.type==sstd_yaml::num_list || t_nx.type==sstd_yaml::num_hash; // check '>' case - bool isGrOrEq = !isGr; // check '>=' case + bool isGr = t.type==sstd_yaml::type_list || t_nx.type==sstd_yaml::type_hash; // check '>' case + bool isGrOrEq = !isGr; // check '>=' case if((isGr && hsc_next> hsc_curr) || (isGrOrEq && hsc_next>=hsc_curr) ) { @@ -533,6 +565,9 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con // --- construct info --- c.ope = sstd_yaml::ope_stack; c.hsc = hsc_next; + // --- anchor and alias --- + c.ref_type = sstd_yaml::ref_type_null; + c.aa_val = ""; ret_vCmd.push_back(c); } @@ -542,225 +577,46 @@ bool sstd_yaml::_token2cmd(std::vector& ret_vCmd, con return true; } -bool _is_control_chars(const char c){ - return (c=='[' || c==']' || c=='{' || c=='}' || c==':' || c==','); +//----------------------------------------------------------------------------------------------------------------------------------------------- +// str2token section + +bool _is_end_marker(const std::string& s){ + return s.starts_with("..."); } -bool sstd_yaml::_split_quotes_by_control_chars(std::vector& ret, const char* str, const uint str_len){ - bool is_escaped=false; - bool in_d_quate=false; // double quate - bool in_s_quate=false; // single quate - std::string buf; - uint i=0; - while(i=str_len){break;} } - - if(!is_escaped && !in_s_quate && str[i]=='"' ){ in_d_quate = !in_d_quate; } - if(!is_escaped && !in_d_quate && str[i]=='\''){ in_s_quate = !in_s_quate; } - - if(!in_d_quate && !in_s_quate && (_is_control_chars(str[i]))){ - buf = sstd::strip(buf); - if(buf.size()!=0){ - ret.push_back(buf); - buf.clear(); - } - ret.push_back(std::string(1, str[i])); // append a control char - ++i; - }else{ - buf += str[i]; - ++i; - } - - is_escaped=false; - } - if(in_d_quate){ ret.clear(); return false; } - if(in_s_quate){ ret.clear(); return false; } - buf = sstd::strip(buf); - if(buf.size()!=0){ ret.push_back(buf); } - - return true; +bool _is_separator(const std::string& s){ + return s.starts_with("---"); } -bool _get_hash_value(bool& is_null, std::string& ret_value, const std::vector& v_cs, uint& i){ - - if(i+3 v_cs; // vector of commands and string - if(!sstd_yaml::_split_quotes_by_control_chars(v_cs, s_in.c_str(), s_in.size())){ sstd::pdbg_err("_split_quotes_by_control_chars() is failed. Un-cloused quate.\n"); return false; } - - std::vector v_dst; - v_dst.push_back( &var_out ); +bool _is_alias(const std::string& s){ + return s.starts_with("*"); +} +bool _is_flow(const std::string& s_in){ + std::string s = sstd::lstrip(s_in); // " [a, b, c]" -> "[a, b, c]" - for(uint i=0; i v_s = sstd::split(s); // "&ref [a, b, c]" -> ["&ref" "[a," "b," "c]"] + if(v_s.size()>=2){ s = v_s[1]; } } - if(v_dst.size()!=0){ sstd::pdbg_err("'[' or '{' is not closed.\n"); return false; } - return true; + return (s.starts_with('[') || s.starts_with('{')); } -bool _construct_var(sstd::terp::var& ret_yml, const std::vector& v_cmd){ - std::vector v_dst; // v: vector, _dst: destination. An address stack for sstd_yaml::ope_alloc (follows the YAML indent) - std::vector v_dst_cr; // v: vector, _dst: destination address, _cr: current. An address stack for sstd_yaml::ope_stack or sstd_yaml::ope_assign. - std::vector v_hsc; // v: vector, hsc: head space count - v_dst.push_back(&ret_yml); - v_dst_cr.push_back(&ret_yml); - v_hsc.push_back(0); - - for(uint i=0; i v_tmp = sstd::split(in, 1); + if(v_tmp.size()==1){ + std::string tmp; + std::swap(out_aa_val, v_tmp[0]); + std::swap(out_val, tmp ); + }else if(v_tmp.size()==2){ + std::swap(out_aa_val, v_tmp[0]); + std::swap(out_val, v_tmp[1]); + }else{ + sstd::pdbg_err("Unexpected data size\n"); } - return true; + return; } - -//----------------------------------------------------------------------------------------------------------------------------------------------- -// str2token section - -bool _is_flow(const std::string& subt){ - return (subt.starts_with('[') || subt.starts_with('{')); -} -bool _is_end_marker(const std::string& subt){ - return subt.starts_with("..."); -} -bool _is_separator(const std::string& subt){ - return subt.starts_with("---"); -} - bool sstd_yaml::_str2token_except_multilines(std::vector& ret, const std::string& str){ // Parse rule of YAML string // @@ -827,7 +683,7 @@ bool sstd_yaml::_str2token_except_multilines(std::vector& ret, if(!is_escaped && !in_s_quate && str[r]=='"' ){ in_d_quate = !in_d_quate; dqed=true; } if(!is_escaped && !in_d_quate && str[r]=='\''){ in_s_quate = !in_s_quate; sqed=true; } - + if(!in_d_quate && !in_s_quate){ if((subt.size()==0 && str[r]=='#') || (str[r]==' ' && str[r+1]=='#')){ tmp.rawStr+=str[r]; ++r; @@ -880,24 +736,29 @@ bool sstd_yaml::_str2token_except_multilines(std::vector& ret, tmp.val=std::move(sstd::strip(subt)); tmp.val_is_dqed=dqed; tmp.val_is_sqed=sqed; + bool is_anchor = _is_anchor(tmp.val); // for the '&' (anchor) + bool is_alias = _is_alias (tmp.val); // for the '*' (alias) + + if(is_list){ tmp.type += sstd_yaml::type_list; tmp.hsc_hx+=2; } + if(is_hash){ tmp.type += sstd_yaml::type_hash; } - if(is_list){ tmp.type += sstd_yaml::num_list; tmp.hsc_hx+=2; } - if(is_hash){ tmp.type += sstd_yaml::num_hash; } - if(is_flow){ tmp.format = sstd_yaml::num_flow_style_base; } + if(is_flow ){ tmp.format = sstd_yaml::format_flow_style; } + if(is_anchor){ tmp.ref_type = sstd_yaml::ref_type_anchor; tmp.val.erase(0,1); _split_aa_val_and_val(tmp.aa_val, tmp.val, tmp.val); } // 1) set format type, 2) remove '&' in the head of the string + if(is_alias ){ tmp.ref_type = sstd_yaml::ref_type_alias; tmp.val.erase(0,1); _split_aa_val_and_val(tmp.aa_val, tmp.val, tmp.val); } // 1) set format type, 2) remove '*' in the head of the string // Skip empty tokens until the first non-empty token occurs. (Empty token is treated as a line-break related with to other token in a context of multi-line YAML) if(ret.size()==0 && tmp.key.size()==0 && tmp.val.size()==0 && - tmp.type==sstd_yaml::num_str){ continue; } + tmp.type==sstd_yaml::type_str){ continue; } // set hasValue tmp.hasValue=false; switch(tmp.type){ - case sstd_yaml::num_str: { if(tmp.val_is_dqed||tmp.val_is_sqed||tmp.val.size()>=1){tmp.hasValue=true;} } break; - case sstd_yaml::num_list: { if(tmp.val_is_dqed||tmp.val_is_sqed||tmp.val.size()>=1){tmp.hasValue=true;} } break; // check the value is NOT NULL - case sstd_yaml::num_list_and_hash: - case sstd_yaml::num_hash: { if(tmp.val_is_dqed||tmp.val_is_sqed||tmp.val.size()>=1){tmp.hasValue=true;} } break; // check the value is NOT NULL + case sstd_yaml::type_str: + case sstd_yaml::type_list: + case sstd_yaml::type_list_and_hash: + case sstd_yaml::type_hash: { if(tmp.val_is_dqed||tmp.val_is_sqed||tmp.val.size()>=1){tmp.hasValue=true;} } break; // check the value is NOT NULL default: { sstd::pdbg_err("Unexpected data type\n"); return false; } break; } @@ -914,13 +775,13 @@ bool sstd_yaml::_str2token_except_multilines(std::vector& ret, } bool _is_all_the_data_str_type(const std::vector& v){ for(uint i=0; i& v){ for(uint i=0; i& ret, const std::vector& io){ + // Example: + // + // in: + // > - - - a + // + // out: + // > - + // > - + // > - a + std::vector ret; for(uint i=0; i& io){ std::vector ret; + std::vector ref_type_stack; + std::vector aa_val_stack; bool is_all_the_data_flowStyle = _is_all_the_data_flowStyle(io); if(is_all_the_data_flowStyle){ @@ -1035,7 +909,11 @@ bool sstd_yaml::_token2token_merge_multilines(std::vector& io) // Check criteria values (Defining criteria value as a base token like list, hash or list_and_hash type to merge) bool start_with_string = (*pT).val.size()>=1; - uint criteria_hsc = _get_criteria_hsc((*pT)); + uint criteria_hsc = _get_criteria_hsc((*pT)); // criteria_hsc: criteria head space count + if((*pT).ref_type!=sstd_yaml::ref_type_null){ + ref_type_stack.push_back((*pT).ref_type); + aa_val_stack.push_back((*pT).aa_val); + } for(uint merge_cnt=1;; ++merge_cnt){ // Update @@ -1046,7 +924,7 @@ bool sstd_yaml::_token2token_merge_multilines(std::vector& io) bool is_control_types = _is_control_types((*pT).type); // Check break - uint curr_hsc = _get_current_hsc((*pT)); + uint curr_hsc = _get_current_hsc((*pT)); // curr_hsc: current head space count if( merge_cnt==1 && is_control_types && (!start_with_string||(curr_hsc<=criteria_hsc)) ){ break; } // - `!start_with_string` is for: // │ k0: @@ -1056,14 +934,16 @@ bool sstd_yaml::_token2token_merge_multilines(std::vector& io) // │ - k2: v2 // Update `start_with_string` to the current token - start_with_string |= (*pT).type==sstd_yaml::num_str; // for "k:\n l1\n l2" + start_with_string |= (*pT).type==sstd_yaml::type_str; // for "k:\n l1\n l2" // Check the needs of breaking the merge process // Under the following situation, the parser needs to break the process of multi-line merging. // - `start_with_string`: The string start with non-control charactor // - `(*pT).key.size()!=0||(*pT).val.size()!=0`: The line is NOT Empty. (If the line is empty, the parser needs to treat as a line break of multi-line string). // - `curr_hsc<=criteria_hsc`: The line is out of scope. if( start_with_string && (((*pT).key.size()!=0||(*pT).val.size()!=0||(*pT).key_is_dqed||(*pT).key_is_sqed||(*pT).val_is_dqed||(*pT).val_is_sqed) && curr_hsc<=criteria_hsc) ){ break; } - + if( start_with_string && (*pT).type==sstd_yaml::type_hash ){ break; } + if( start_with_string && (*pT).type==sstd_yaml::type_list && aa_val_stack.size()!=0){ break; } + if( _is_separator((*pT).rawStr) ){ break; } // Copy values @@ -1071,6 +951,21 @@ bool sstd_yaml::_token2token_merge_multilines(std::vector& io) tmp.val += '\n' + (*pT).rawStr; // Needs to copy as row string in order to treat multi-line string as a raw data. Ex1: "k:\n x\n - a" is interpreted as `{k: "x - a"}`. Ex2: "k: |\n x # comment" is interpreted as `{k: "x # comment"}`. tmp.line_num_end = (*pT).line_num_end; tmp.mult_line_val = true; + + tmp.hasValue |= (*pT).hasValue; + tmp.line_num_end = (*pT).line_num_end; + if((*pT).hasValue){ tmp.format = (*pT).format; } + + if((*pT).ref_type!=sstd_yaml::ref_type_null){ + ref_type_stack.push_back((*pT).ref_type); + aa_val_stack.push_back((*pT).aa_val); + } + } + + if(aa_val_stack.size()>=2){ sstd::pdbg_err("Duplicated anchor (&) definition. Troubled definition names: "); sstd::print_base(aa_val_stack); printf(".\n"); return false; } + if(aa_val_stack.size()==1){ + tmp.ref_type = ref_type_stack[0]; ref_type_stack.clear(); + tmp.aa_val = aa_val_stack [0]; aa_val_stack.clear(); } ret.push_back(std::move(tmp)); @@ -1104,10 +999,10 @@ bool _escape_to_unicode_character(std::string& io){ case '0': { tmp += (uchar)0x00; break; } //case ' ': { tmp += '\\'; break; } -// case '_': { tmp += '\u00a0'; break; } // Needs to check "How UTF-8 encode" if we treats as UTF-8. -// case 'N': { tmp += '\u0085'; break; } // Needs to check "How UTF-8 encode" if we treats as UTF-8. -// case 'L': { tmp += '\u2028'; break; } // Needs to check "How UTF-8 encode" if we treats as UTF-8. -// case 'P': { tmp += '\u2029'; break; } // Needs to check "How UTF-8 encode" if we treats as UTF-8. +// case '_': { tmp += '\u00a0'; break; } // Needs to check "How UTF-8 encode" if we treats as UTF-8. (Byte order is the concern point) +// case 'N': { tmp += '\u0085'; break; } // Needs to check "How UTF-8 encode" if we treats as UTF-8. (Byte order is the concern point) +// case 'L': { tmp += '\u2028'; break; } // Needs to check "How UTF-8 encode" if we treats as UTF-8. (Byte order is the concern point) +// case 'P': { tmp += '\u2029'; break; } // Needs to check "How UTF-8 encode" if we treats as UTF-8. (Byte order is the concern point) default: { // if (sstd::startswith(&io[i+1], "x41" )){ tmp += "A"; i+=strlen("x41" ); break; // Needs to check "How UTF-8 encode" if we treats as UTF-8. // }else if(sstd::startswith(&io[i+1], "u0041" )){ tmp += "A"; i+=strlen("u0041" ); break; // Needs to check "How UTF-8 encode" if we treats as UTF-8. @@ -1163,13 +1058,276 @@ bool sstd_yaml::_str2token(std::vector& ret, const char* str_i std::string str = std::regex_replace(str_in, std::regex("\r"), ""); // "\r\n" -> "\n" if(!sstd_yaml::_str2token_except_multilines(ret, str.c_str())){ sstd::pdbg_err("sstd_yaml::_str2token_except_multilines() was failed.\n"); return false; } - if(!sstd_yaml::_token2token_split_bv_list_type_cnt(ret)){ sstd::pdbg_err("sstd_yaml::_token2token_split_bv_list_type_cnt() was failed.\n"); return false; } if(!sstd_yaml::_token2token_merge_multilines(ret)){ sstd::pdbg_err("sstd_yaml::_token2token_merge_multilines() was failed.\n"); return false; } + if(!sstd_yaml::_token2token_split_bv_list_type_cnt(ret)){ sstd::pdbg_err("sstd_yaml::_token2token_split_bv_list_type_cnt() was failed.\n"); return false; } if(!sstd_yaml::_token2token_postprocess(ret)){ sstd::pdbg_err("sstd_yaml::_token2token_postprocess() was failed.\n"); return false; } return true; } bool sstd_yaml::_str2token(std::vector& ret, const std::string& str){ return sstd_yaml::_str2token(ret, str.c_str()); } +//----------------------------------------------------------------------------------------------------------------------------------------------- +// _construct_var() section + +bool _is_control_chars(const char c){ + return (c=='[' || c==']' || c=='{' || c=='}' || c==':' || c==','); +} +bool sstd_yaml::_split_quotes_by_control_chars(std::vector& ret, const char* str, const uint str_len){ + bool is_escaped=false; + bool in_d_quate=false; // double quate + bool in_s_quate=false; // single quate + std::string buf; + uint i=0; + while(i=str_len){break;} } + + if(!is_escaped && !in_s_quate && str[i]=='"' ){ in_d_quate = !in_d_quate; } + if(!is_escaped && !in_d_quate && str[i]=='\''){ in_s_quate = !in_s_quate; } + + if(!in_d_quate && !in_s_quate && (_is_control_chars(str[i]))){ + buf = sstd::strip(buf); + if(buf.size()!=0){ + ret.push_back(buf); + buf.clear(); + } + ret.push_back(std::string(1, str[i])); // append a control char + ++i; + }else{ + buf += str[i]; + ++i; + } + + is_escaped=false; + } + if(in_d_quate){ ret.clear(); return false; } + if(in_s_quate){ ret.clear(); return false; } + buf = sstd::strip(buf); + if(buf.size()!=0){ ret.push_back(buf); } + + return true; +} +bool _get_hash_value(bool& is_null, std::string& ret_value, const std::vector& v_cs, uint& i){ + + if(i+3& tbl_anchor_to_address, const std::string& s_in){ + + out_is_alias = _is_alias(s_in); + + if(out_is_alias){ + std::string alias_name = std::string(s_in).erase(0,1); // removes '*' in the head of the string + + auto itr = tbl_anchor_to_address.find( alias_name ); + if(itr==tbl_anchor_to_address.end()){ sstd::pdbg_err("Anchor does NOT found. Anchor name: %s\n", s_in.c_str()); return false; } + + out_address = itr->second; + } + + return true; +} +bool _flow_style_str_to_obj(sstd::terp::var& var_out, const std::unordered_map& tbl_anchor_to_address, const std::string& s_in){ + + std::vector v_cs; // vector of commands and string + if(!sstd_yaml::_split_quotes_by_control_chars(v_cs, s_in.c_str(), s_in.size())){ sstd::pdbg_err("_split_quotes_by_control_chars() is failed. Un-cloused quate.\n"); return false; } + + std::vector v_dst; + v_dst.push_back( &var_out ); + + for(uint i=0; ito()); + std::string val; + bool has_object_value = _get_hash_value(is_null, val, v_cs, i); + if(has_object_value){ + bool is_value_alias; sstd::terp::var* value_address; + if(!_get_alias_address(is_value_alias, value_address, tbl_anchor_to_address, val)){ sstd::pdbg_err("_get_alias_address() failed.\n"); return false; } // for the '*' (alias) + + if(!is_null){ + if(!is_value_alias){ + var[ key.c_str() ] = _extract_quotes_value(sstd::strip_quotes(val.c_str())); + }else{ + var[ key.c_str() ] = value_address; + } + } else { + var[ key.c_str() ]; + } + }else{ + v_dst.push_back( &(var[key.c_str()]) ); + } + } break; + case sstd::num_null: {} break; + default: { sstd::pdbg_err("Unexpected data type. Type: %s\n", sstd::typeNum2str(var.typeNum()).c_str()); } break; + } + } + } + if(v_dst.size()!=0){ sstd::pdbg_err("'[' or '{' is not closed.\n"); return false; } + + return true; +} +bool _construct_var(sstd::terp::var& ret_yml, const std::vector& v_cmd){ + std::vector v_dst; // v: vector, _dst: destination address. An address stack for sstd_yaml::ope_alloc (follows the YAML indent) + std::vector v_dst_cr; // v: vector, _dst: destination address, _cr: current. An address stack for sstd_yaml::ope_stack or sstd_yaml::ope_assign. + std::vector v_hsc; // v: vector, hsc: head space count + v_dst.push_back(&ret_yml); + v_dst_cr.push_back(&ret_yml); + v_hsc.push_back(0); + + std::unordered_map tbl_anchor_to_address; + + for(uint i=0; isecond; + } + } break; + case sstd_yaml::type_hash: { + auto itr = var.find(cmd.val); + if(itr!=var.end()){ sstd::pdbg_err("Detecting the duplicated hash key.\n"); return false; } + v_dst_cr.push_back(&var[cmd.val]); + if(cmd.ref_type==sstd_yaml::ref_type_anchor){ + tbl_anchor_to_address[ cmd.aa_val ] = &var[ cmd.val ]; + }else if(cmd.ref_type==sstd_yaml::ref_type_alias){ + auto itr = tbl_anchor_to_address.find( cmd.aa_val ); + if(itr==tbl_anchor_to_address.end()){ sstd::pdbg_err("Anchor does NOT found. Anchor name: %s\n", cmd.aa_val.c_str()); break; } + var[ cmd.val ] = (sstd::terp::var*)itr->second; + } + } break; + default: { sstd::pdbg_err("Unexpected data type\n"); return false; } break; + } + }else{ + sstd::pdbg_err("Unexpected data type\n"); return false; + } + } + + return true; +} + //----------------------------------------------------------------------------------------------------------------------------------------------- // YAML load section diff --git a/sstd/src/file/yaml.hpp b/sstd/src/file/yaml.hpp index 28b546d2..9ced726e 100644 --- a/sstd/src/file/yaml.hpp +++ b/sstd/src/file/yaml.hpp @@ -14,66 +14,73 @@ namespace sstd_yaml{ //--- // operation definition - const static uint8 ope_null = 255; - const static uint8 ope_alloc = 0; // allocate - const static uint8 ope_stack = 1; // stacking a value to v_dst - const static uint8 ope_assign = 2; // assignemnt + const static uint8 ope_null = 255; + const static uint8 ope_alloc = 0; // allocate + const static uint8 ope_stack = 1; // stacking a value to v_dst + const static uint8 ope_assign = 2; // assignemnt +// const static uint8 ope_push_ref = 3; // pushing a reference address to the hash table +// const static uint8 ope_pull_ref = 4; // pulling a reference address from the hash table //--- // type definition - // TODO: num_ -> type_ に名前を置換する + const static uint8 type_null = 255; + const static uint8 type_str = 0; // for BLOCK_STYLE + const static uint8 type_list = 1; // for BLOCK_STYLE + const static uint8 type_hash = 2; // for BLOCK_STYLE + const static uint8 type_list_and_hash = 3; // for BLOCK_STYLE - const static uint8 num_null = 255; - const static uint8 num_block_style_base = 0; - const static uint8 num_str = 0; // for BLOCK_STYLE - const static uint8 num_list = 1; // for BLOCK_STYLE - const static uint8 num_hash = 2; // for BLOCK_STYLE - const static uint8 num_list_and_hash = 3; // for BLOCK_STYLE - const static uint8 num_flow_style_base = 4; - // sstd_yaml::num_flow_style_base + sstd_yaml::num_str 4 // reserved number for FLOW_STYLE - // sstd_yaml::num_flow_style_base + sstd_yaml::num_list 5 // reserved number for FLOW_STYLE - // sstd_yaml::num_flow_style_base + sstd_yaml::num_hash 6 // reserved number for FLOW_STYLE - // sstd_yaml::num_flow_style_base + sstd_yaml::num_list_and_hash 7 // reserved number for FLOW_STYLE + const static uint8 format_null = 255; + const static uint8 format_block_style = 0; // using indents to construct + const static uint8 format_flow_style = 1; // list [] or {} + + const static uint8 ref_type_null = 255; + const static uint8 ref_type_anchor = 0; // & + const static uint8 ref_type_alias = 1; // * //--- // token for proceed YAML parsing struct token { // Data for Debug YAML parsing - uint line_num_begin = 1; // beginning line number - uint line_num_end = 1; // endding line number (for multipleline) - std::string rawStr; // A raw string splitted by line concering the YAML processing units. + uint line_num_begin = 1; // beginning line number + uint line_num_end = 1; // endding line number (for multipleline) + std::string rawStr; // A raw string splitted by line concering the YAML processing units. // Data structure to load YAML - //uint type = sstd_yaml::num_null; // sstd_yaml::num_str; // A destination type number of this line - uint type = sstd_yaml::num_str; // A destination type number of this line - uint format = sstd_yaml::num_block_style_base; // If containing flow style notation - uint list_type_cnt = 0; // Number of list type. (`- - - v`) - uint hsc_lx = 0; // head space counts for list type - uint hsc_hx = 0; // head space counts for hash type + uint8 type = sstd_yaml::type_str; // A destination type number of this line + uint8 format = sstd_yaml::format_block_style; // If containing flow style notation + uint8 ref_type = sstd_yaml::ref_type_null; // If containing anchor or alias + uint list_type_cnt = 0; // Number of list type. (`- - - v`) + uint hsc_lx = 0; // head space counts for list type + uint hsc_hx = 0; // head space counts for hash type - bool hasValue = false; // If the value (val1 or val2) is vaild for each data type (list or hash). - bool key_is_dqed = false; - bool key_is_sqed = false; - bool val_is_dqed = false; - bool val_is_sqed = false; + bool hasValue = false; // If the value (val1 or val2) is vaild for each data type (list or hash) + bool key_is_dqed = false; // _dqed: double quated + bool key_is_sqed = false; // _sqed: single quated + bool val_is_dqed = false; // _dqed: double quated + bool val_is_sqed = false; // _sqed: single quated bool mult_line_val = false; std::string key; // key for "hash" std::string val; // value for "list" or "hash" + std::string aa_val; // value for anchor and alias }; struct command{ // Data for Debug YAML parsing - uint line_num_begin = 1; // beginning line number - uint line_num_end = 1; // endding line number (for multipleline) - std::string rawStr; // A raw string splitted by line concering the YAML processing units. - + uint line_num_begin = 1; // beginning line number + uint line_num_end = 1; // endding line number (for multipleline) + std::string rawStr; // A raw string splitted by line concering the YAML processing units. + // Data structure to construct YAML uint ope; // operation uint hsc; // hsc: head space count uint8 type; // data type uint8 format; // data format std::string val; // value + + // Anchor and Alias + uint8 ref_type = sstd_yaml::ref_type_null; // If containing anchor or alias + std::string aa_val; // anchor and alias value }; //--- @@ -102,13 +109,8 @@ namespace sstd_yaml{ //----------------------------------------------------------------------------------------------------------------------------------------------- namespace sstd{ - void print(const sstd_yaml::token& rhs); - void for_printn(const sstd_yaml::token& rhs); - void print_for_vT(const sstd_yaml::token& rhs); - - void print(const sstd_yaml::command& rhs); - void for_printn(const sstd_yaml::command& rhs); - void print_for_vT(const sstd_yaml::command& rhs); + void print_base(const sstd_yaml::token& rhs); + void print_base(const sstd_yaml::command& rhs); bool yaml_load ( sstd::terp::var & ret_yml, const char* s); bool yaml_load ( sstd::terp::var & ret_yml, const std::string& s); diff --git a/sstd/src/memory/terp/terp.cpp b/sstd/src/memory/terp/terp.cpp index 18fb5091..135cb7a8 100644 --- a/sstd/src/memory/terp/terp.cpp +++ b/sstd/src/memory/terp/terp.cpp @@ -19,11 +19,6 @@ void _free_val(sstd::terp::var* _pVar, void*& _p, sstd::terp::srcr_tbl* _pSRCR_t //----------------------------------------------------------------------------------------------------------------------------------------------- // for internal use -// cast -std::string* _cast2str (void* rhs){ return ( std::string*)rhs; } -std::vector* _cast2vec (void* rhs){ return (std::vector*)rhs; } -std::unordered_map* _cast2hash(void* rhs){ return (std::unordered_map*)rhs; } - #define STR (*(std::string*)src.p()) void sstd::terp::_to( bool & dst, const sstd::terp::var& src){ @@ -210,7 +205,11 @@ sstd::terp::var::var( float rhs): _type(sstd::num_str ), _is_referen sstd::terp::var::var( double rhs): _type(sstd::num_str ), _is_reference(false), _is_pSRCR_tbl_base(true), _pSRCR_tbl(new sstd::terp::srcr_tbl()), _p(new std::string(sstd::ssprintf(_format(rhs).c_str(), rhs))) {} sstd::terp::var::var(const char* rhs): _type(sstd::num_str ), _is_reference(false), _is_pSRCR_tbl_base(true), _pSRCR_tbl(new sstd::terp::srcr_tbl()), _p(new std::string(rhs)) {} sstd::terp::var::var(const std::string& rhs): _type(sstd::num_str ), _is_reference(false), _is_pSRCR_tbl_base(true), _pSRCR_tbl(new sstd::terp::srcr_tbl()), _p(new std::string(rhs)) {} -sstd::terp::var::var(const sstd::terp::srcr_tbl* rhs): _type(sstd::num_null), _is_reference(false), _is_pSRCR_tbl_base(false), _pSRCR_tbl((sstd::terp::srcr_tbl*)rhs), _p(NULL) {} + +sstd::terp::var::var(const sstd::terp::srcr_tbl* tbl ): _type(sstd::num_null), _is_reference(false), _is_pSRCR_tbl_base(false), _pSRCR_tbl((sstd::terp::srcr_tbl*)tbl), _p(NULL) {} +sstd::terp::var::var(const sstd::terp::srcr_tbl* tbl, const class var& rhs): _type(sstd::num_null), _is_reference(false), _is_pSRCR_tbl_base(false), _pSRCR_tbl((sstd::terp::srcr_tbl*)tbl), _p(NULL) { copy(rhs); } +sstd::terp::var::var(const sstd::terp::srcr_tbl* tbl, class var&& rhs): _type(sstd::num_null), _is_reference(false), _is_pSRCR_tbl_base(false), _pSRCR_tbl((sstd::terp::srcr_tbl*)tbl), _p(NULL) { free(); move(std::move(rhs)); } +sstd::terp::var::var(const sstd::terp::srcr_tbl* tbl, const char* rhs): _type(sstd::num_str ), _is_reference(false), _is_pSRCR_tbl_base(false), _pSRCR_tbl((sstd::terp::srcr_tbl*)tbl), _p(new std::string(rhs)) {} sstd::terp::var::~var(){ sstd::terp::var::free(); } @@ -574,8 +573,8 @@ sstd::terp::var& sstd::terp::var::operator=(const sstd::terp::var* pRhs_in){ template void sstd::terp::var::_overwrite(T* ptr){ _free_val(this, _p, _pSRCR_tbl, _type, _is_reference); - this->_type = sstd::type2num(T()); - this->_p = ptr; + this->_type = sstd::type2num(T()); + this->_p = ptr; } sstd::terp::var& sstd::terp::var::operator=(const char* rhs){ _overwrite(new std::string(rhs)); @@ -614,8 +613,9 @@ bool _is_equal_hash(const sstd::terp::var& lhs, const sstd::terp::var& rhs, auto itr_rhs = rhs.find(key.c_str()); if(!(itr_rhs!=rhs.end())){ return false; } - - if(!_is_equal(itr.second(), itr_rhs.second(), check_ref_flag, ref_addr_graph, check_ref_abs_addr, vStack_lhsP_and_rhsP, tbl_lhsAds_to_rhsAds)){ return false; } + + //if(!_is_equal(itr.second(), itr_rhs.second(), check_ref_flag, ref_addr_graph, check_ref_abs_addr, vStack_lhsP_and_rhsP, tbl_lhsAds_to_rhsAds)){ return false; } // This is invalid implimentation. Because the "itr.second()" makes the new temporal object and the address of `pSRCR_tbl()` changed. + if(!_is_equal(lhs[key.c_str()], rhs[key.c_str()], check_ref_flag, ref_addr_graph, check_ref_abs_addr, vStack_lhsP_and_rhsP, tbl_lhsAds_to_rhsAds)){ return false; } } return true; @@ -637,7 +637,7 @@ bool _is_equal(const sstd::terp::var& lhs, const sstd::terp::var& rhs, // ├────────────────────────────────┼───────────────────────────────────────────────┼──────────────┤ // │ sstd::terp::equal_val() │ true │ false │ false │ │ // ├────────────────────────────────┼───────────────────────────────────────────────┼──────────────┤ - // │ sstd::terp::equal_refAbsAddr() │ true │ true │ false │ │ + // │ sstd::terp::equal_refAbsAddr() │ true │ true │ false │ │ /* <- This is NOT implimented yet */ // └────────────────────────────────┴───────────────────────────────────────────────┴──────────────┘ // *1. Options: // true: sets to check the option @@ -647,26 +647,28 @@ bool _is_equal(const sstd::terp::var& lhs, const sstd::terp::var& rhs, // ref_flag: 'true' | 'false' // ref_addr_graph: 'true' | 'false' + if(lhs.type()!=rhs.type()){ return false; } + + if(ref_addr_graph){ + tbl_lhsAds_to_rhsAds[ (sstd::terp::var*)&lhs ] = (sstd::terp::var*)&rhs; + } if(check_ref_flag){ if(lhs.is_reference()!=rhs.is_reference()){ return false; } if(lhs.is_reference()){ bool is_internal_ref_lhs = _is_internal_ref(&lhs); bool is_internal_ref_rhs = _is_internal_ref(&rhs); + if(is_internal_ref_lhs != is_internal_ref_rhs){ return false; } if(is_internal_ref_lhs){ // If the reference is `internal` reference. vStack_lhsP_and_rhsP.push_back( std::make_tuple((sstd::terp::var*)&lhs, (sstd::terp::var*)&rhs) ); + return true; // Check the `vStack_lhsP_and_rhsP` later. (Just confirm the address consistency is enough.) }else{ // If the reference is `external` reference. - if(lhs.p() != rhs.p()){ sstd::printn_all("");return false; } + if(lhs.p() != rhs.p()){ return false; } } } } - if(lhs.type()!=rhs.type()){ return false; } - - if(ref_addr_graph){ - tbl_lhsAds_to_rhsAds[ (sstd::terp::var*)&lhs ] = (sstd::terp::var*)&rhs; - } switch(lhs.typeNum()){ case sstd::num_str: { return lhs.to()==rhs.to(); } break; @@ -723,9 +725,11 @@ bool sstd::terp::var::operator!=(const sstd::terp::var& rhs){ return !sstd::terp } \ return *this; #define _OPE_SUBSCRIPT_KEY_BASE(pKey) \ + void* local_p = (! this->_is_reference) ? _p : (void*)((sstd::terp::var*)_p)->_p; \ + \ switch(_type){ \ case sstd::num_hash_terp_var: { \ - sstd::terp::var** ppVal = &(_CAST2HASH(_p)[pKey]); \ + sstd::terp::var** ppVal = &(_CAST2HASH(local_p)[pKey]); \ if(*ppVal==NULL){ (*ppVal)=new sstd::terp::var(_pSRCR_tbl); } \ return **ppVal; \ } break; \ @@ -740,11 +744,13 @@ bool sstd::terp::var::operator!=(const sstd::terp::var& rhs){ return !sstd::terp } \ return *this; #define _OPE_SUBSCRIPT_KEY_BASE_CONST(pKey) \ + void* local_p = (! this->_is_reference) ? _p : (void*)((sstd::terp::var*)_p)->_p; \ + \ switch(_type){ \ case sstd::num_hash_terp_var: { \ - sstd::terp::var* pVal = _CAST2HASH(_p)[pKey]; \ - if(pVal==NULL){ sstd::pdbg_err("Ope[](char*) is failed. NULL pointer detection error. pKey: `%s` is NOT allocated.\n", pKey); return *this; } \ - return *pVal; \ + sstd::terp::var** ppVal = &(_CAST2HASH(local_p)[pKey]); \ + if(*ppVal==NULL){ sstd::pdbg_err("Ope[](char*) is failed. NULL pointer detection error. pKey: `%s` is NOT allocated.\n", pKey); return *this; } \ + return **ppVal; \ } break; \ default: { sstd::pdbg_err("Ope[](char*) is failed. Unexpedted data type. sstd::terp::var takes type number `%d`, but treat as a \"sstd::terp::hash()\".\n", _type); } break; \ } \ @@ -840,7 +846,10 @@ uint sstd::terp::var::erase(const char* pKey){ sstd::terp::iterator sstd::terp::var::find(const char* pKey) const { switch(_type){ - case sstd::num_hash_terp_var: { return sstd::terp::iterator( _CAST2HASH(_p).find(pKey) ); } break; + case sstd::num_hash_terp_var: { + void* local_p = (! this->_is_reference) ? _p : (void*)((sstd::terp::var*)_p)->_p; + return sstd::terp::iterator( _CAST2HASH(local_p).find(pKey) ); + } break; case sstd::num_null: {} break; default: { sstd::pdbg_err("ERROR\n"); } } @@ -866,22 +875,22 @@ void sstd::terp::var::pop_back(){ void sstd::terp::var::push_back(){ // push_back null NULL_CHECK(_p); if(_type!=sstd::num_vec_terp_var){ sstd::pdbg_err("push_back(char*) is failed. Unexpedted data type. This function requires sstd::num_vec_terp_var type, but takes %s type.\n", sstd::typeNum2str(this->_type).c_str()); return; } - _CAST2VEC(_p).push_back(new sstd::terp::var()); + _CAST2VEC(_p).push_back(new sstd::terp::var((sstd::terp::srcr_tbl*)this->_pSRCR_tbl)); } void sstd::terp::var::push_back(const char* pRhs){ NULL_CHECK(_p); if(_type!=sstd::num_vec_terp_var){ sstd::pdbg_err("push_back(char*) is failed. Unexpedted data type. This function requires sstd::num_vec_terp_var type, but takes %s type.\n", sstd::typeNum2str(this->_type).c_str()); return; } - _CAST2VEC(_p).push_back(new sstd::terp::var(pRhs)); + _CAST2VEC(_p).push_back(new sstd::terp::var((sstd::terp::srcr_tbl*)this->_pSRCR_tbl, pRhs)); } void sstd::terp::var::push_back(const sstd::terp::var& rhs){ NULL_CHECK(_p); if(_type!=sstd::num_vec_terp_var){ sstd::pdbg_err("push_back(var&) is failed. Unexpedted data type. This function requires sstd::num_vec_terp_var type, but takes %s type.\n", sstd::typeNum2str(this->_type).c_str()); return; } - _CAST2VEC(_p).push_back(new sstd::terp::var(rhs)); + _CAST2VEC(_p).push_back(new sstd::terp::var((sstd::terp::srcr_tbl*)this->_pSRCR_tbl, rhs)); } void sstd::terp::var::push_back( sstd::terp::var&& rhs){ NULL_CHECK(_p); if(_type!=sstd::num_vec_terp_var){ sstd::pdbg_err("push_back(var&) is failed. Unexpedted data type. This function requires sstd::num_vec_terp_var type, but takes %s type.\n", sstd::typeNum2str(this->_type).c_str()); return; } - _CAST2VEC(_p).push_back(new sstd::terp::var(std::move(rhs))); // call move constructor of "sstd::void_ptr::void_ptr()" + _CAST2VEC(_p).push_back(new sstd::terp::var((sstd::terp::srcr_tbl*)this->_pSRCR_tbl, std::move(rhs))); // call move constructor of "sstd::void_ptr::void_ptr()" } void sstd::terp::var::resize(uint len){ diff --git a/sstd/src/memory/terp/terp.hpp b/sstd/src/memory/terp/terp.hpp index bece6638..33fedeee 100644 --- a/sstd/src/memory/terp/terp.hpp +++ b/sstd/src/memory/terp/terp.hpp @@ -97,7 +97,10 @@ class sstd::terp::var{ var(const double rhs); var(const char* rhs); var(const std::string& rhs); - var(const sstd::terp::srcr_tbl* rhs); // for internal use of sstd::terp::var + var(const sstd::terp::srcr_tbl* tbl ); // for internal use of sstd::terp::var + var(const sstd::terp::srcr_tbl* tbl, const class var& rhs); // for internal use of sstd::terp::var + var(const sstd::terp::srcr_tbl* tbl, class var&& rhs); // for internal use of sstd::terp::var + var(const sstd::terp::srcr_tbl* tbl, const char* rhs); // for internal use of sstd::terp::var ~var(); //--- @@ -120,7 +123,7 @@ class sstd::terp::var{ void _fill_ref_src_null(const std::unordered_set& hash_set); void _fillout_ref_src_null(); - + bool _copy_base(const class sstd::terp::var* pRhs, const char opt_a, const char opt_i, const char opt_e); bool copy(const class sstd::terp::var& rhs); void move( class sstd::terp::var&& rhs); diff --git a/sstd/src/string/strEdit.cpp b/sstd/src/string/strEdit.cpp index 3ed6b87f..9cee7f95 100755 --- a/sstd/src/string/strEdit.cpp +++ b/sstd/src/string/strEdit.cpp @@ -111,13 +111,20 @@ bool sstd::splitByLine_quotes(std::vector& ret, const std::string& //----------------------------------------------------------------------------------------------------------------------------------------------- -std::vector _asAX_rmSpace(const char* str, const char X){ +std::vector _asAX_rmSpace(const char* str, const char X, const int maxsplit){ + if(maxsplit==0){ return std::vector({str}); } std::vector splitList; std::string buf; uint i=0; + while(str[i]!='\0'){ if(str[i]==' '){++i;}else{break;} } // skip space while(str[i]!='\0'){ + if(maxsplit>=0 && splitList.size()==(uint)maxsplit){ + buf += (const char*)&str[i]; + break; + } + if(X==str[i]){ sstd::rstrip_ow(buf); splitList.push_back(buf); buf.clear(); ++i; @@ -153,15 +160,16 @@ std::vector _asAX(const char* str, const char X){ if(i>=1 && str[i-1]==X){ splitList.push_back(std::string()); } return splitList; } -std::vector sstd::split(const char* str ){ return _asAX_rmSpace(str, ' '); } -std::vector sstd::split(const std::string& str ){ return _asAX_rmSpace(str.c_str(), ' '); } +std::vector sstd::split(const char* str ){ return _asAX_rmSpace(str, ' ', -1); } +std::vector sstd::split(const std::string& str ){ return _asAX_rmSpace(str.c_str(), ' ', -1); } +std::vector sstd::split(const char* str, int maxsplit){ return _asAX_rmSpace(str, ' ', maxsplit); } +std::vector sstd::split(const std::string& str, int maxsplit){ return _asAX_rmSpace(str.c_str(), ' ', maxsplit); } std::vector sstd::split(const char* str, const char X){ return _asAX(str, X ); } std::vector sstd::split(const std::string& str, const char X){ return _asAX(str.c_str(), X ); } std::vector _split_ss_base(const char* str, const uint str_len, const char* X, const uint X_len){ - if(str_len<=1){ return std::vector({str}); } - if(X_len ==0){ return std::vector({str}); } - if(X_len ==1){ return sstd::split(str, X[0]); } + if(X_len==0){ return std::vector({str}); } + if(X_len==1){ return sstd::split(str, X[0]); } std::vector splitList; std::string buf; @@ -184,10 +192,56 @@ std::vector sstd::split(const std::string& str, const std::string& //--- -std::vector sstd::split_rmSpace(const char* str ){ return _asAX_rmSpace(str, ' '); } -std::vector sstd::split_rmSpace(const std::string& str ){ return _asAX_rmSpace(str.c_str(), ' '); } -std::vector sstd::split_rmSpace(const char* str, const char X){ return _asAX_rmSpace(str , X ); } -std::vector sstd::split_rmSpace(const std::string& str, const char X){ return _asAX_rmSpace(str.c_str(), X ); } +std::vector _split_all_base(const char* str, const uint str_len, const char* X, const uint X_len){ + if(X_len==0){ return std::vector({str}); } + + std::vector splitList; + std::string buf; + for(uint i=0; str[i]!='\0'; ++i){ + if(!sstd::charIn(str[i], X)){ + buf += str[i]; + }else{ + splitList.push_back(buf); + buf.clear(); + } + } + if((str_len>=1 && sstd::charIn(str[str_len-1], X)) || buf.size()!=0){ splitList.push_back(buf); } + return splitList; +} +std::vector sstd::splitAll(const char* str, const char* X){ return _split_all_base(str, ::strlen(str), X, ::strlen(X)); } +std::vector sstd::splitAll(const std::string& str, const char* X){ return _split_all_base(str.c_str(), str.size(), X, ::strlen(X)); } +std::vector sstd::splitAll(const char* str, const std::string& X){ return _split_all_base(str, ::strlen(str), X.c_str(), X.size()); } +std::vector sstd::splitAll(const std::string& str, const std::string& X){ return _split_all_base(str.c_str(), str.size(), X.c_str(), X.size()); } + +//--- + +std::vector _split_all_tight_base(const char* str, const uint str_len, const char* X, const uint X_len){ + if(X_len==0){ return std::vector({str}); } + + std::vector splitList; + std::string buf; + for(uint i=0; str[i]!='\0'; ++i){ + if(!sstd::charIn(str[i], X)){ + buf += str[i]; + }else if(buf.size()!=0){ + splitList.push_back(buf); + buf.clear(); + } + } + if(buf.size()!=0){ splitList.push_back(buf); } + return splitList; +} +std::vector sstd::splitAll_tight(const char* str, const char* X){ return _split_all_tight_base(str, ::strlen(str), X, ::strlen(X)); } +std::vector sstd::splitAll_tight(const std::string& str, const char* X){ return _split_all_tight_base(str.c_str(), str.size(), X, ::strlen(X)); } +std::vector sstd::splitAll_tight(const char* str, const std::string& X){ return _split_all_tight_base(str, ::strlen(str), X.c_str(), X.size()); } +std::vector sstd::splitAll_tight(const std::string& str, const std::string& X){ return _split_all_tight_base(str.c_str(), str.size(), X.c_str(), X.size()); } + +//--- + +std::vector sstd::split_rmSpace(const char* str ){ return _asAX_rmSpace(str, ' ', -1); } +std::vector sstd::split_rmSpace(const std::string& str ){ return _asAX_rmSpace(str.c_str(), ' ', -1); } +std::vector sstd::split_rmSpace(const char* str, const char X){ return _asAX_rmSpace(str , X , -1); } +std::vector sstd::split_rmSpace(const std::string& str, const char X){ return _asAX_rmSpace(str.c_str(), X , -1); } //----------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/sstd/src/string/strEdit.hpp b/sstd/src/string/strEdit.hpp index 866f633c..665b155c 100755 --- a/sstd/src/string/strEdit.hpp +++ b/sstd/src/string/strEdit.hpp @@ -14,16 +14,32 @@ namespace sstd{ std::vector splitByLine(const char* str); std::vector splitByLine(const std::string& str); - bool splitByLine_quotes(std::vector& ret, const char* str); bool splitByLine_quotes(std::vector& ret, const std::string& str); std::vector split(const char* str); std::vector split(const std::string& str); + std::vector split(const char* str, int maxsplit); + std::vector split(const std::string& str, int maxsplit); + std::vector split(const char* str, const char X); std::vector split(const std::string& str, const char X); +// std::vector split(const char* str, const char X, int maxsplit); // TODO +// std::vector split(const std::string& str, const char X, int maxsplit); // TODO + std::vector split(const char* str, const char* X); std::vector split(const std::string& str, const std::string& X); +// std::vector split(const char* str, const char* X, int maxsplit); // TODO +// std::vector split(const std::string& str, const std::string& X, int maxsplit); // TODO + + std::vector splitAll (const char* str, const char* X); + std::vector splitAll (const std::string& str, const char* X); + std::vector splitAll (const char* str, const std::string& X); + std::vector splitAll (const std::string& str, const std::string& X); + std::vector splitAll_tight(const char* str, const char* X); + std::vector splitAll_tight(const std::string& str, const char* X); + std::vector splitAll_tight(const char* str, const std::string& X); + std::vector splitAll_tight(const std::string& str, const std::string& X); std::vector split_rmSpace(const char* str); // rm: remove std::vector split_rmSpace(const std::string& str); // rm: remove diff --git a/sstd/src/string/strmatch.hpp b/sstd/src/string/strmatch.hpp index 3eed7355..485f8942 100755 --- a/sstd/src/string/strmatch.hpp +++ b/sstd/src/string/strmatch.hpp @@ -18,11 +18,6 @@ namespace sstd{ bool strmatch(const std::string& str, const char* wildcard); bool strmatch(const std::string& str, const std::string& wildcard); - bool pathmatch(const char* str, const char* wildcard); - bool pathmatch(const char* str, const std::string& wildcard); - bool pathmatch(const std::string& str, const char* wildcard); - bool pathmatch(const std::string& str, const std::string& wildcard); - bool strmatch_getWC( const char* str, // target string to search const char* wildcard, // wild card ('*' and '?' are available.) @@ -32,6 +27,11 @@ namespace sstd{ bool strmatch_getWC(const std::string& str, const char* wildcard, std::string& retWC); bool strmatch_getWC(const std::string& str, const std::string& wildcard, std::string& retWC); + bool pathmatch(const char* str, const char* wildcard); + bool pathmatch(const char* str, const std::string& wildcard); + bool pathmatch(const std::string& str, const char* wildcard); + bool pathmatch(const std::string& str, const std::string& wildcard); + uint rcount(const char* str, char X); uint rcount(const std::string& str, char X); uint lcount(const char* str, char X); diff --git a/test/src_test/file/yaml.cpp b/test/src_test/file/yaml.cpp index 43ba34db..e5a211d5 100644 --- a/test/src_test/file/yaml.cpp +++ b/test/src_test/file/yaml.cpp @@ -80,12 +80,12 @@ TEST(yaml, _split_quotes_by_control_chars_02){ ASSERT_TRUE(ret); \ ASSERT_EQ((uint)v_ret.size(), (uint)1); \ \ - uint ans_type=sstd_yaml::num_str; \ - if(IS_LIST){ ans_type += sstd_yaml::num_list; } \ - if(IS_HASH){ ans_type += sstd_yaml::num_hash; } \ + uint ans_type=sstd_yaml::type_str; \ + if(IS_LIST){ ans_type += sstd_yaml::type_list; } \ + if(IS_HASH){ ans_type += sstd_yaml::type_hash; } \ ASSERT_EQ(v_ret[0].type, (uint)ans_type); \ \ - uint ans_flow = IS_FLOW ? sstd_yaml::num_flow_style_base : sstd_yaml::num_block_style_base; \ + uint ans_flow = IS_FLOW ? sstd_yaml::format_flow_style : sstd_yaml::format_block_style; \ ASSERT_EQ(v_ret[0].format, (uint)ans_flow); \ ASSERT_EQ(v_ret[0].list_type_cnt, (uint)LIST_TYPE_COUNT); @@ -117,13 +117,13 @@ TEST(yaml, _str2token__data_type_and_format_case06_02){ TEST_STR2TOKEN__DATA_TYP //--- // Test _str2token() of val1 and val2 -#define TEST_STR2TOKEN__KEY_VAL(KEY, VAL, S_IN) \ - std::string s = S_IN; \ - std::vector v_ret; \ - bool ret = sstd_yaml::_str2token(v_ret, s); \ - ASSERT_TRUE(ret); \ - ASSERT_EQ(v_ret.size(), (uint)1); \ - ASSERT_STREQ(v_ret[0].key.c_str(), KEY); \ +#define TEST_STR2TOKEN__KEY_VAL(KEY, VAL, S_IN) \ + std::string s = S_IN; \ + std::vector v_ret; \ + bool ret = sstd_yaml::_str2token(v_ret, s); \ + ASSERT_TRUE(ret); \ + ASSERT_EQ(v_ret.size(), (uint)1); \ + ASSERT_STREQ(v_ret[0].key.c_str(), KEY); \ ASSERT_STREQ(v_ret[0].val.c_str(), VAL); TEST(yaml, _str2token_val1_val2_list ){ TEST_STR2TOKEN__KEY_VAL("", "a", "- a"); } @@ -377,11 +377,31 @@ TEST(yaml, _str2token_multi_list_case10){ // sstd::printn(v_ret[0].val.c_str()); ASSERT_STREQ(v_ret[0].val.c_str(), "a - a"); // "a\n - a" } +TEST(yaml, _str2token_multi_list_case11){ + std::string s=R"( +- x + - - a + - b + - c +)"; + std::vector v_ret; + bool ret = sstd_yaml::_str2token(v_ret, s); + //sstd::printn(v_ret); + + ASSERT_TRUE(ret); + ASSERT_EQ(v_ret.size(), (uint)1); + ASSERT_STREQ(v_ret[0].val.c_str(), "x - - a - b - c"); // "a\n - a" +} //--- //TEST(yaml, _str2token_multi_list_except_pipe_or_inequality_sign_case01){ //} + +//--- + + + //*/ //----------------------------------------------------------------------------------------------------------------------------------------------- // Test _format_mult_line_str() @@ -669,34 +689,34 @@ TEST(yaml, _token2cmd_usual_cases){ // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)0); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // k1: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "k1"); ++idx; // v11 ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_assign); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_str); - ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::num_block_style_base); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_str); + ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::format_block_style); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "v11"); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)0); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // k2: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "k2"); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack @@ -705,161 +725,161 @@ TEST(yaml, _token2cmd_usual_cases){ // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; // v21 ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_assign); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_str); - ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::num_block_style_base); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_str); + ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::format_block_style); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "v21"); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; // v22 ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_assign); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_str); - ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::num_block_style_base); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_str); + ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::format_block_style); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "v22"); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // k23: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)4); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "k23"); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // k24: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)4); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "k24"); ++idx; // v241 ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_assign); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_str); - ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::num_block_style_base); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_str); + ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::format_block_style); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "v241"); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)0); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // k3: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "k3"); ++idx; // v31 ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_assign); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_str); - ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::num_block_style_base); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_str); + ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::format_block_style); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "v31"); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)0); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // k5: #null ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "k5"); ++idx; // k51: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "k51"); ++idx; // v511 ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_assign); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_str); - ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::num_block_style_base); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_str); + ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::format_block_style); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "v511"); ++idx; // - # null ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)0); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; // - # null ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)0); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)0); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)2); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)4); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)6); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; // v8111 ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_assign); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_str); - ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::num_block_style_base); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_str); + ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::format_block_style); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "v8111"); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); ASSERT_EQ(ret_v_cmd[idx].hsc, (uint)0); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; // v9 ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_assign); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_str); - ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::num_block_style_base); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_str); + ASSERT_EQ(ret_v_cmd[idx].format, sstd_yaml::format_block_style); ASSERT_STREQ(ret_v_cmd[idx].val.c_str(), "v9"); ++idx; } @@ -882,11 +902,11 @@ TEST(yaml, _token2cmd_null_values_case01){ uint idx=0; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; } TEST(yaml, _token2cmd_null_values_case02){ @@ -905,11 +925,11 @@ TEST(yaml, _token2cmd_null_values_case02){ uint idx=0; // k1: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ++idx; // k2: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ++idx; } TEST(yaml, _token2cmd_null_values_case03){ @@ -928,23 +948,23 @@ TEST(yaml, _token2cmd_null_values_case03){ uint idx=0; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // k1: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ++idx; // - ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_list); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_list); ++idx; ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_stack); // stack ++idx; // k2: ASSERT_EQ(ret_v_cmd[idx].ope, sstd_yaml::ope_alloc); - ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::num_hash); + ASSERT_EQ(ret_v_cmd[idx].type, sstd_yaml::type_hash); ++idx; } //*/ @@ -1435,6 +1455,55 @@ k[]{}: v[]{} # OK //--- +TEST(yaml, hash_multiple_line_01){ + std::string s = R"( +h1: + + a + + b + + c + +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = "a\nb\nc"; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, hash_multiple_line_02){ + std::string s = R"( +h1: + + k1: v1 +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = sstd::terp::hash(); + ans["h1"]["k1"] = "v1"; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} + +//--- + TEST(yaml, hash_duplicated_err){ // TODO: ここの仕様を直す std::string s=R"( k1: val1 @@ -3599,7 +3668,7 @@ TEST(yaml, multipul_list_indication_case08){ //--- //* -TEST(yaml, block_list_and_flow_list){ +TEST(yaml, block_list_and_flow_list_01){ std::string s=R"( - [a, b, c] )"; @@ -3620,6 +3689,27 @@ TEST(yaml, block_list_and_flow_list){ ASSERT_TRUE(yml==ans); } +TEST(yaml, block_list_and_flow_list_02){ + std::string s=R"( +- [a, b, c] +)"; + sstd::terp::var yml; ASSERT_TRUE(sstd::yaml_load(yml, s)); // TEST THIS LINE + //sstd::printn(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(1); + ans[0] = sstd::terp::list(3); + ans[0][0] = "a"; + ans[0][1] = "b"; + ans[0][2] = "c"; + //sstd::printn(ans); + + //--- + + ASSERT_TRUE(yml==ans); +} TEST(yaml, block_list_and_flow_hash){ std::string s=R"( - {k1:v1, k2:v2, k3:v3} @@ -4287,5 +4377,630 @@ TEST(yaml, yaml_load_all_fp){ } //*/ //----------------------------------------------------------------------------------------------------------------------------------------------- +// anchor and alias + +TEST(yaml, _str2token__multi_list__anchor_and_alias__case1){ + std::string s=R"( +- &ll + - a +- *ll +)"; + std::vector v_ret; + bool ret = sstd_yaml::_str2token(v_ret, s); +// sstd::printn_all(ret); +// sstd::printn_all(v_ret.size()); +// sstd::printn_all(v_ret); + + //--- + + ASSERT_TRUE(ret); + ASSERT_EQ(v_ret.size(), (uint)3); + + ASSERT_STREQ(v_ret[0].rawStr.c_str(), "- &ll" ); + ASSERT_STREQ(v_ret[0].key.c_str(), "" ); + ASSERT_STREQ(v_ret[0].val.c_str(), "" ); + ASSERT_STREQ(v_ret[0].aa_val.c_str(), "ll" ); + ASSERT_EQ (v_ret[0].ref_type, (uint) 0); + + ASSERT_STREQ(v_ret[1].rawStr.c_str(), " - a" ); + ASSERT_STREQ(v_ret[1].key.c_str(), "" ); + ASSERT_STREQ(v_ret[1].val.c_str(), "a" ); + ASSERT_STREQ(v_ret[1].aa_val.c_str(), "" ); + ASSERT_EQ (v_ret[1].ref_type, (uint)255); + + ASSERT_STREQ(v_ret[2].rawStr.c_str(), "- *ll" ); + ASSERT_STREQ(v_ret[2].key.c_str(), "" ); + ASSERT_STREQ(v_ret[2].val.c_str(), "" ); + ASSERT_STREQ(v_ret[2].aa_val.c_str(), "ll" ); + ASSERT_EQ (v_ret[2].ref_type, (uint) 1); +} +TEST(yaml, _str2token__multi_list__anchor_and_alias__case2){ + std::string s = R"( +- &ll + - - a + - b + - c +- *ll +)"; + std::vector v_ret; + bool ret = sstd_yaml::_str2token(v_ret, s); +// sstd::printn_all(ret); +// sstd::printn_all(v_ret.size()); +// sstd::printn_all(v_ret); + + ASSERT_TRUE(ret); + ASSERT_EQ(v_ret.size(), (uint)6); + + ASSERT_STREQ(v_ret[0].rawStr.c_str(), "- &ll" ); + ASSERT_STREQ(v_ret[0].key.c_str(), "" ); + ASSERT_STREQ(v_ret[0].val.c_str(), "" ); + ASSERT_STREQ(v_ret[0].aa_val.c_str(), "ll" ); + ASSERT_EQ (v_ret[0].ref_type, (uint) 0); + + ASSERT_STREQ(v_ret[1].rawStr.c_str(), " - - a"); + ASSERT_STREQ(v_ret[1].key.c_str(), "" ); + ASSERT_STREQ(v_ret[1].val.c_str(), "" ); + ASSERT_STREQ(v_ret[1].aa_val.c_str(), "" ); + ASSERT_EQ (v_ret[1].ref_type, (uint)255); + + ASSERT_STREQ(v_ret[2].rawStr.c_str(), " - - a"); + ASSERT_STREQ(v_ret[2].key.c_str(), "" ); + ASSERT_STREQ(v_ret[2].val.c_str(), "a" ); + ASSERT_STREQ(v_ret[2].aa_val.c_str(), "" ); + ASSERT_EQ (v_ret[2].ref_type, (uint)255); + + ASSERT_STREQ(v_ret[3].rawStr.c_str(), " - b" ); + ASSERT_STREQ(v_ret[3].key.c_str(), "" ); + ASSERT_STREQ(v_ret[3].val.c_str(), "b" ); + ASSERT_STREQ(v_ret[3].aa_val.c_str(), "" ); + ASSERT_EQ (v_ret[3].ref_type, (uint)255); + + ASSERT_STREQ(v_ret[4].rawStr.c_str(), " - c" ); + ASSERT_STREQ(v_ret[4].key.c_str(), "" ); + ASSERT_STREQ(v_ret[4].val.c_str(), "c" ); + ASSERT_STREQ(v_ret[4].aa_val.c_str(), "" ); + ASSERT_EQ (v_ret[4].ref_type, (uint)255); + + ASSERT_STREQ(v_ret[5].rawStr.c_str(), "- *ll" ); + ASSERT_STREQ(v_ret[5].key.c_str(), "" ); + ASSERT_STREQ(v_ret[5].val.c_str(), "" ); + ASSERT_STREQ(v_ret[5].aa_val.c_str(), "ll" ); + ASSERT_EQ (v_ret[5].ref_type, (uint) 1); +} + +//--- + +TEST(yaml, anchor_and_alias__case01){ + std::string s=R"( +- &ll + - a +- *ll +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + + //--- + + ASSERT_TRUE(ret); + + ASSERT_EQ(yml.size(), (uint)2); + ASSERT_EQ(yml[0].size(), (uint)1); + ASSERT_EQ(yml[1].size(), (uint)1); + + ASSERT_STREQ(yml[0][0].to().c_str(), "a"); + ASSERT_STREQ(yml[1][0].to().c_str(), "a"); + + ASSERT_EQ(yml[0].is_reference(), false); + ASSERT_EQ(yml[1].is_reference(), true ); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = sstd::terp::list(1); + ans[0][0] = "a"; + ans[1] = &ans[0]; + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case02){ + std::string s = R"( +- &rr + - - a + - b + - c +- *rr +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); +// sstd::printn_all(yml.size()); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = sstd::terp::list(3); + ans[0][0] = sstd::terp::list(1); + ans[0][0][0] = "a"; + ans[0][1] = "b"; + ans[0][2] = "c"; + ans[1] = &ans[0]; + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case03){ + std::string s = R"( +- &r a x # anchor +- *r # alias +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = "a x"; + ans[1] = &ans[0]; + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case04){ + std::string s = R"( +- &r a +- [*r] +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); + //sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = "a"; + ans[1] = sstd::terp::list(1); + ans[1][0] = &ans[0]; + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case05_hash_key){ + std::string s = R"( +- &r a +- {*r} +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = "a"; + ans[1] = sstd::terp::hash(); + ans[1]["a"]; + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case06_hash_value){ + std::string s = R"( +- &r a +- {key: *r} +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = "a"; + ans[1] = sstd::terp::hash(); + ans[1]["key"] = &ans[0]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case07a_list){ + std::string s = R"( +- &r [a, b, c] +- *r +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = sstd::terp::list(3); + ans[0][0] = "a"; + ans[0][1] = "b"; + ans[0][2] = "c"; + ans[1] = &ans[0]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case07b_list){ + std::string s = R"( +- &r + [a, b, c] +- *r +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = sstd::terp::list(3); + ans[0][0] = "a"; + ans[0][1] = "b"; + ans[0][2] = "c"; + ans[1] = &ans[0]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case08a_hash){ + std::string s = R"( +- &r {k: v} +- *r +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = sstd::terp::hash(); + ans[0]["k"] = "v"; + ans[1] = &ans[0]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case08b_hash){ + std::string s = R"( +- &r + {k: v} +- *r +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = sstd::terp::hash(); + ans[0]["k"] = "v"; + ans[1] = &ans[0]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case09_hash){ + std::string s = R"( +h1: &h1 + k1: v1 +h2: *h1 +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = sstd::terp::hash(); + ans["h1"]["k1"] = "v1"; + ans["h2"] = &ans["h1"]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case09b_hash){ + std::string s = R"( +h1: + &h1 + k1: v1 +h2: *h1 +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = sstd::terp::hash(); + ans["h1"]["k1"] = "v1"; + ans["h2"] = &ans["h1"]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case09b2_hash){ + std::string s = R"( +h1: + &h1 + k1: v1 +h2: *h1 +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = sstd::terp::hash(); + ans["h1"]["k1"] = "v1"; + ans["h2"] = &ans["h1"]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case09error01_hash){ + std::string s = R"( +h1: &h1 + &h2 + k1: v1 +h2: *h2 +)"; + sstd::terp::var yml; + + testing::internal::CaptureStdout(); + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + std::string err_msg = testing::internal::GetCapturedStdout(); + ASSERT_TRUE(sstd::strIn("Duplicated anchor (&) definition.", err_msg)); + + ASSERT_FALSE(ret); +} +TEST(yaml, anchor_and_alias__case09error02_hash){ + std::string s = R"( +h1: + &h2 + &h3 + k1: v1 +h2: *h2 +)"; + sstd::terp::var yml; + + testing::internal::CaptureStdout(); + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + std::string err_msg = testing::internal::GetCapturedStdout(); + ASSERT_TRUE(sstd::strIn("Duplicated anchor (&) definition.", err_msg)); + + ASSERT_FALSE(ret); +} +TEST(yaml, anchor_and_alias__case09error03_hash){ + std::string s = R"( +h1: &h1 + &h2 + &h3 + k1: v1 +h2: *h2 +)"; + sstd::terp::var yml; + + testing::internal::CaptureStdout(); + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + std::string err_msg = testing::internal::GetCapturedStdout(); + ASSERT_TRUE(sstd::strIn("Duplicated anchor (&) definition.", err_msg)); + + ASSERT_FALSE(ret); +} +TEST(yaml, anchor_and_alias__case09c_hash){ + std::string s = R"( +h1: + + &h1 + + k1: v1 +h2: *h1 +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = sstd::terp::hash(); + ans["h1"]["k1"] = "v1"; + ans["h2"] = &ans["h1"]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case09d_hash){ + std::string s = R"( +h1: + + &h1 + k1: v1 + +h2: *h1 +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = sstd::terp::hash(); + ans["h1"]["k1"] = "v1"; + ans["h2"] = &ans["h1"]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case09e_hash){ + std::string s = R"( +h1: &h1 + k1: v1 +h2: + *h1 +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = sstd::terp::hash(); + ans["h1"]["k1"] = "v1"; + ans["h2"] = &ans["h1"]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} + +//--- + +TEST(yaml, anchor_and_alias__case10_hash_list){ + std::string s = R"( +h1: + + &h1_val + + - v1 +h2: *h1_val +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::hash(); + ans["h1"] = sstd::terp::list(1); + ans["h1"][0] = "v1"; + ans["h2"] = &ans["h1"]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case11_list){ // For more comfirmation of the case, "TEST(yaml, _str2token_multi_list_case10)". + std::string s = R"( +- &a + - a +- *a +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = sstd::terp::list(1); + ans[0][0] = "a"; + ans[1] = &ans[0]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} +TEST(yaml, anchor_and_alias__case12_list_hash){ + std::string s = R"( +- h1: &h1 + k1: v1 + k2: v2 +- h2: *h1 +)"; + sstd::terp::var yml; + bool ret = sstd::yaml_load(yml, s); // TEST THIS LINE + ASSERT_TRUE(ret); +// sstd::printn_all(yml); + + //--- + + sstd::terp::var ans; + ans = sstd::terp::list(2); + ans[0] = sstd::terp::hash(); + ans[0]["h1"] = sstd::terp::hash(); + ans[0]["h1"]["k1"] = "v1"; + ans[0]["h1"]["k2"] = "v2"; + ans[1] = sstd::terp::hash(); + ans[1]["h2"] = &ans[0]["h1"]; +// sstd::printn_all(ans); + + ASSERT_TRUE(yml == ans); +} + +//--- +/* + std::string s = R"( +hx: &hx + k1: v1 +h2: + <<: *hx + k2: v2 +)"; +*/ + +//-- +// TODO +/* +&h1_key h1: v1 +h2: *h1_key +*/ +/* +h1: + &h1 + &k1 k1: v1 +h2: *h1 +h3: *k1 +*/ +/* +h1: &h1 + k1: v1 +h2: &h2 // よく考えると、h1 を使えばよいだけでは? + *h1 +h3: + *h2 +*/ +//----------------------------------------------------------------------------------------------------------------------------------------------- EXECUTE_TESTS(); + diff --git a/test/src_test/memory/terp/terp.cpp b/test/src_test/memory/terp/terp.cpp index 2220559c..0fc6e773 100644 --- a/test/src_test/memory/terp/terp.cpp +++ b/test/src_test/memory/terp/terp.cpp @@ -551,6 +551,26 @@ TEST(memory_terp, hash_find_false){ auto itr = a.find("k0"); // TEST THIS LINE ASSERT_FALSE( itr!=a.end() ); } +TEST(memory_terp, hash_find_ref){ + sstd::terp::var a; + a = sstd::terp::list(2); + a[0] = sstd::terp::hash(); + a[0]["k0"] = "v0"; + a[1] = &a[0]; + + auto itr0 = a[0].find("k0"); // TEST THIS LINE + ASSERT_TRUE( itr0!=a[0].end() ); + ASSERT_STREQ(itr0.first_to().c_str(), "k0"); + ASSERT_STREQ(itr0.second_to().c_str(), "v0"); + + auto itr1 = a[1].find("k0"); // TEST THIS LINE + ASSERT_TRUE( itr1!=a[1].end() ); + ASSERT_STREQ(itr1.first_to().c_str(), "k0"); + ASSERT_STREQ(itr1.second_to().c_str(), "v0"); + + auto itr2 = a[1].find("non-existing-key"); // TEST THIS LINE + ASSERT_FALSE( itr2!=a[1].end() ); +} // size() TEST(memory_terp, hash_size_arg_null){ @@ -907,6 +927,94 @@ TEST(memory_terp, var_init_list){ ASSERT_TRUE( a.pSRCR_tbl() == a[0].pSRCR_tbl() ); ASSERT_TRUE( a.pSRCR_tbl() == a[1].pSRCR_tbl() ); } +TEST(memory_terp, var_init_list_by_push_back_NULL){ + sstd::terp::var a = sstd::terp::list(); + a.push_back(); // TEST THIS LINE + a.push_back(); // TEST THIS LINE + + ASSERT_TRUE(a.is_pSRCR_tbl_base() == true ); + ASSERT_TRUE(a.pSRCR_tbl() != NULL ); + + ASSERT_TRUE(a[0].is_pSRCR_tbl_base() == false ); + ASSERT_TRUE(a[0].pSRCR_tbl() != NULL ); + + ASSERT_TRUE(a[1].is_pSRCR_tbl_base() == false ); + ASSERT_TRUE(a[1].pSRCR_tbl() != NULL ); + + ASSERT_TRUE( a.pSRCR_tbl() == a[0].pSRCR_tbl() ); + ASSERT_TRUE( a.pSRCR_tbl() == a[1].pSRCR_tbl() ); +} +TEST(memory_terp, var_init_list_by_push_back_CHAR){ + sstd::terp::var a = sstd::terp::list(); + a.push_back("a"); // TEST THIS LINE + a.push_back("b"); // TEST THIS LINE + + ASSERT_EQ(a.size(), (uint)2); + ASSERT_STREQ(a[0].to().c_str(), "a"); + ASSERT_STREQ(a[1].to().c_str(), "b"); + + ASSERT_TRUE(a.is_pSRCR_tbl_base() == true ); + ASSERT_TRUE(a.pSRCR_tbl() != NULL ); + + ASSERT_TRUE(a[0].is_pSRCR_tbl_base() == false ); + ASSERT_TRUE(a[0].pSRCR_tbl() != NULL ); + + ASSERT_TRUE(a[1].is_pSRCR_tbl_base() == false ); + ASSERT_TRUE(a[1].pSRCR_tbl() != NULL ); + + ASSERT_TRUE( a.pSRCR_tbl() == a[0].pSRCR_tbl() ); + ASSERT_TRUE( a.pSRCR_tbl() == a[1].pSRCR_tbl() ); + +} +TEST(memory_terp, var_init_list_by_push_back_VAR){ + sstd::terp::var x = "x"; + + sstd::terp::var a = sstd::terp::list(); + a.push_back(x); // TEST THIS LINE + a.push_back(x); // TEST THIS LINE + + ASSERT_EQ(a.size(), (uint)2); + ASSERT_STREQ(a[0].to().c_str(), "x"); + ASSERT_STREQ(a[1].to().c_str(), "x"); + + ASSERT_TRUE(a.is_pSRCR_tbl_base() == true ); + ASSERT_TRUE(a.pSRCR_tbl() != NULL ); + + ASSERT_TRUE(a[0].is_pSRCR_tbl_base() == false ); + ASSERT_TRUE(a[0].pSRCR_tbl() != NULL ); + + ASSERT_TRUE(a[1].is_pSRCR_tbl_base() == false ); + ASSERT_TRUE(a[1].pSRCR_tbl() != NULL ); + + ASSERT_TRUE( a.pSRCR_tbl() == a[0].pSRCR_tbl() ); + ASSERT_TRUE( a.pSRCR_tbl() == a[1].pSRCR_tbl() ); + +} +TEST(memory_terp, var_init_list_by_push_back_VAR_MOVE){ + sstd::terp::var x1 = "x1"; + sstd::terp::var x2 = "x2"; + + sstd::terp::var a = sstd::terp::list(); + a.push_back(std::move(x1)); // TEST THIS LINE + a.push_back(std::move(x2)); // TEST THIS LINE + + ASSERT_EQ(a.size(), (uint)2); + ASSERT_STREQ(a[0].to().c_str(), "x1"); + ASSERT_STREQ(a[1].to().c_str(), "x2"); + + ASSERT_TRUE(a.is_pSRCR_tbl_base() == true ); + ASSERT_TRUE(a.pSRCR_tbl() != NULL ); + + ASSERT_TRUE(a[0].is_pSRCR_tbl_base() == false ); + ASSERT_TRUE(a[0].pSRCR_tbl() != NULL ); + + ASSERT_TRUE(a[1].is_pSRCR_tbl_base() == false ); + ASSERT_TRUE(a[1].pSRCR_tbl() != NULL ); + + ASSERT_TRUE( a.pSRCR_tbl() == a[0].pSRCR_tbl() ); + ASSERT_TRUE( a.pSRCR_tbl() == a[1].pSRCR_tbl() ); + +} //----------------------------------------------------------------------------------------------------------------------------------------------- // For the Reference Type (Operator) @@ -999,7 +1107,7 @@ TEST(memory_terp, var_ope_square_brackets_list__REF){ ASSERT_EQ(x.ope_sb_c(0).is_reference(), false); // TEST Ope[] const ASSERT_EQ(x.ope_sb_c(1).is_reference(), true); // TEST Ope[] const } -TEST(memory_terp, var_ope_square_brackets_hash_REF){ +TEST(memory_terp, var_ope_square_brackets_hash_REF_01){ sstd::terp::var x; x = sstd::terp::hash(); x["key1"] = "val1"; @@ -1022,6 +1130,17 @@ TEST(memory_terp, var_ope_square_brackets_hash_REF){ ASSERT_EQ(x.ope_sb_c("key1").is_reference(), false); // TEST Ope[] const ASSERT_EQ(x.ope_sb_c("key2").is_reference(), true); // TEST Ope[] const } +TEST(memory_terp, var_ope_square_brackets_hash_REF_02){ + sstd::terp::var x; + x = sstd::terp::list(2); + x[0] = sstd::terp::hash(); + x[0]["k"] = "v"; + x[1] = &x[0]; + + ASSERT_STREQ(x[1]["k"].to().c_str(), "v"); // TEST Ope[] + ASSERT_STREQ(x[1].ope_sb ("k").to().c_str(), "v"); // TEST Ope[] + ASSERT_STREQ(x[1].ope_sb_c("k").to().c_str(), "v"); // TEST Ope[] const +} //----------------------------------------------------------------------------------------------------------------------------------------------- // For the Reference Type (Copy) @@ -1256,6 +1375,9 @@ TEST(memory_terp, terp__deep_copy_err){} //----------------------------------------------------------------------------------------------------------------------------------------------- // For the Reference Type: `sstd::terp::equal()` +//--- +// for list() + TEST(memory_terp, terp__equal__case01_not_eq){ sstd::terp::var x; x = sstd::terp::list(2); @@ -1354,6 +1476,26 @@ TEST(memory_terp, terp__equal__case05_not_eq){ } //--- +// for hash() + +TEST(memory_terp, terp__equal__list_and_hash__case01_eq){ + sstd::terp::var x; + x = sstd::terp::list(2); + x[0] = "a-z"; + x[1] = sstd::terp::hash(); + x[1]["key"] = &x[0]; + + sstd::terp::var y; + y = sstd::terp::list(2); + y[0] = "a-z"; + y[1] = sstd::terp::hash(); + y[1]["key"] = &y[0]; + + ASSERT_TRUE(sstd::terp::equal(x, y)); // TEST THIS LINE +} + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// For the Reference Type: `sstd::terp::equal_val()` TEST(memory_terp, terp__equal_val__case01_eq){ sstd::terp::var x; @@ -1443,43 +1585,6 @@ TEST(memory_terp, terp__equal_val__case05_not_eq){ //----------------------------------------------------------------------------------------------------------------------------------------------- -//--- - -/* -TEST(memory_terp, list_ope_assign_with_reference_tmp){ // Ope= - sstd::terp::var a; - a = sstd::terp::list(2); - a[0] = sstd::terp::list(3); - a[0][0] = "a"; - a[0][1] = "b"; - a[0][2] = "c"; - printf("894\n"); - sstd::printn(a.pSRCR_tbl()); - sstd::printn(a[0].pSRCR_tbl()); - printf("895\n"); - a[1] = &a[0]; - printf("897\n"); - - ASSERT_TRUE(a[0].is_reference() == false); - ASSERT_TRUE(a[1].is_reference() == true ); - printf("899\n"); - - sstd::terp::var x = a; // TEST THIS LINE - - ASSERT_TRUE(x[0].is_reference() == false); - ASSERT_TRUE(x[1].is_reference() == true ); - printf("905\n"); - - x[0][0]="x"; - ASSERT_TRUE(a[0][0].to() == "x"); - ASSERT_TRUE(a[1][0].to() == "x"); - printf("910\n"); - - ASSERT_TRUE(x[0][0].to() == "x"); - ASSERT_TRUE(x[1][0].to() == "x"); - printf("913\n"); -} -*/ TEST(memory_terp, list_ope_assign_with_reference_case_01_delete_src){ sstd::terp::var dst; { diff --git a/test/src_test/string/strEdit.cpp b/test/src_test/string/strEdit.cpp index aad6665e..04ddbcce 100644 --- a/test/src_test/string/strEdit.cpp +++ b/test/src_test/string/strEdit.cpp @@ -157,7 +157,6 @@ TEST(strEdit, extract_unquoted__false){ } //----------------------------------------------------------------------------------------------------------------------------------------------- - //splitByLine //TEST(strEdit, splitByLine){} @@ -186,6 +185,7 @@ R"()"}) ); } //----------------------------------------------------------------------------------------------------------------------------------------------- +// sstd::split(), sstd::splitAll(), sstd::split_rmSpace() #define TEST_SPLIT_CS(S_IN, ...) \ std::vector ret_v = sstd::split(S_IN); /* TEST THIS LINE */ \ @@ -195,12 +195,29 @@ R"()"}) ); TEST(strEdit, split_c_0){ TEST_SPLIT_CS(" a b, c", "a", "b,", "c"); } TEST(strEdit, split_c_1){ TEST_SPLIT_CS(" a b, c ", "a", "b,", "c"); } TEST(strEdit, split_c_2){ TEST_SPLIT_CS(" a b, c ", "a", "b,", "c"); } +TEST(strEdit, split_c_3){ TEST_SPLIT_CS(" "); } +TEST(strEdit, split_c_4){ TEST_SPLIT_CS(" "); } TEST(strEdit, split_s){ TEST_SPLIT_CS(std::string(" a b, c"), "a", "b,", "c"); } #undef TEST_SPLIT_CS //--- +#define TEST_SPLIT_MAX_CS(S_IN, MAX, ...) \ + std::vector ret_v = sstd::split(S_IN, MAX); /* TEST THIS LINE */ \ + /* sstd::printn(ret_v); */ \ + ASSERT_TRUE(ret_v == std::vector({__VA_ARGS__}) ); + +TEST(strEdit, split_max_c_0){ TEST_SPLIT_MAX_CS(" a b, c ", 0, " a b, c "); } +TEST(strEdit, split_max_c_1){ TEST_SPLIT_MAX_CS(" a b, c ", 1, "a", "b, c"); } +TEST(strEdit, split_max_c_2){ TEST_SPLIT_MAX_CS(" a b, c ", 2, "a", "b,", "c"); } +TEST(strEdit, split_max_c_3){ TEST_SPLIT_MAX_CS(" a b, c ", 3, "a", "b,", "c"); } +TEST(strEdit, split_max_s){ TEST_SPLIT_MAX_CS(std::string(" a b, c "), 1, "a", "b, c"); } + +#undef TEST_SPLIT_MAX_CS + +//--- + #define TEST_SPLIT_CS_X(X_IN, S_IN, ...) \ std::vector ret_v = sstd::split(S_IN, X_IN); /* TEST THIS LINE */ \ /* sstd::printn(ret_v); */ \ @@ -228,12 +245,54 @@ TEST(strEdit, split_s_s_space_m_0){ TEST_SPLIT_SS_X("xxx", "123abcabs456", "123a TEST(strEdit, split_s_s_space_m_1){ TEST_SPLIT_SS_X("abc", "123abcabs456", "123", "abs456"); } TEST(strEdit, split_s_s_space_m_2a){ TEST_SPLIT_SS_X("abc", "123abc456abc789", "123", "456", "789"); } TEST(strEdit, split_s_s_space_m_2b){ TEST_SPLIT_SS_X("abc", "123abc456abc789abc", "123", "456", "789", ""); } +TEST(strEdit, split_s_s_space_m_3){ TEST_SPLIT_SS_X(" ", " ", "", ""); } TEST(strEdit, split_s_s){ TEST_SPLIT_SS_X(std::string("abc"), std::string("123abc456abc789"), std::string("123"), std::string("456"), std::string("789")); } #undef TEST_SPLIT_SS_X //--- +// sstd::splitAll() + +#define TEST_SPLIT_ALL(X_IN, S_IN, ...) \ + std::vector ret_v = sstd::splitAll(S_IN, X_IN); /* TEST THIS LINE */ \ + /* sstd::printn(ret_v); */ \ + ASSERT_TRUE(ret_v == std::vector({__VA_ARGS__}) ); + +TEST(strEdit, splitAll_CC_interface_test){ TEST_SPLIT_ALL( " ,\n", " a b, c", "", "a", "", "b", "", "c"); } +TEST(strEdit, splitAll_SC_interface_test){ TEST_SPLIT_ALL(std::string(" ,\n"), " a b, c" , "", "a", "", "b", "", "c"); } +TEST(strEdit, splitAll_CS_interface_test){ TEST_SPLIT_ALL( " ,\n" , std::string(" a b, c"), "", "a", "", "b", "", "c"); } +TEST(strEdit, splitAll_SS_interface_test){ TEST_SPLIT_ALL(std::string(" ,\n"), std::string(" a b, c"), "", "a", "", "b", "", "c"); } + +TEST(strEdit, splitAll_01){ TEST_SPLIT_ALL("", " ", " "); } +TEST(strEdit, splitAll_02){ TEST_SPLIT_ALL("", "", ""); } +TEST(strEdit, splitAll_03){ TEST_SPLIT_ALL(" ", " ", "", ""); } +TEST(strEdit, splitAll_04){ TEST_SPLIT_ALL(" \n", "&h abc\n def\n &x", "&h", "abc", "", "def", "", "&x"); } + +#undef TEST_SPLITALL_CS + +//--- +// sstd::splitAll_tight() + +#define TEST_SPLIT_ALL_TIGHT(X_IN, S_IN, ...) \ + std::vector ret_v = sstd::splitAll_tight(S_IN, X_IN); /* TEST THIS LINE */ \ + /* sstd::printn(ret_v); */ \ + ASSERT_TRUE(ret_v == std::vector({__VA_ARGS__}) ); + +TEST(strEdit, splitAll_tight_CC_interface_test){ TEST_SPLIT_ALL_TIGHT( " ,\n", " a b, c", "a", "b", "c"); } +TEST(strEdit, splitAll_tight_SC_interface_test){ TEST_SPLIT_ALL_TIGHT(std::string(" ,\n"), " a b, c" , "a", "b", "c"); } +TEST(strEdit, splitAll_tight_CS_interface_test){ TEST_SPLIT_ALL_TIGHT( " ,\n" , std::string(" a b, c"), "a", "b", "c"); } +TEST(strEdit, splitAll_tight_SS_interface_test){ TEST_SPLIT_ALL_TIGHT(std::string(" ,\n"), std::string(" a b, c"), "a", "b", "c"); } + +TEST(strEdit, splitAll_tight_01){ TEST_SPLIT_ALL_TIGHT("", " ", " "); } +TEST(strEdit, splitAll_tight_02){ TEST_SPLIT_ALL_TIGHT("", "", ""); } +TEST(strEdit, splitAll_tight_03){ TEST_SPLIT_ALL_TIGHT(" ", " "); } +TEST(strEdit, splitAll_tight_04){ TEST_SPLIT_ALL_TIGHT(" \n", "&h abc\n def\n &x", "&h", "abc", "def", "&x"); } + +#undef TEST_SPLITALL_CS + +//--- +// sstd::split_rmSpace() #define TEST_SPLIT_RMSPACE_CS(S_IN, ...) \ std::vector ret_v = sstd::split_rmSpace(S_IN); /* TEST THIS LINE */ \