bool readfields(void* object, const bsreq* fields) { while(*p && !islinefeed()) { const bsreq* req = 0; if(readidentifier()) req = fields->find(buffer); if(!req) warning(ErrorNotFoundMember1pInBase2p, buffer, getbasename(fields)); readreq(object, req, 0); } return true; }
// Return true if "c" is line feed or carriage return or null static bool islinefeed0(char c) { return (!c || islinefeed(c)); }
// parse CIF contents bool cif_file::parse() { char *p = contents; char quote; char prev = '\0'; std::vector<bool> keypossible; // tokenize while (true) { while (iswhitespace(*p)) prev = *(p++); if (!*p) break; if (*p == '#') { while (!(islinefeed0(*++p))); prev = *p; } else if (isquote(*p)) { // will NULL the closing quote quote = *p; keypossible.push_back(false); tokens.push_back(p + 1); while (*++p && !(*p == quote && iswhitespace0(p[1]))); if (*p) *(p++) = 0; prev = *p; } else if (*p == ';' && islinefeed(prev)) { // will NULL the line feed before the closing semicolon keypossible.push_back(false); tokens.push_back(p + 1); while (*++p && !(islinefeed(*p) && p[1] == ';')); if (*p) { *p = 0; p += 2; } prev = ';'; } else { // will null the whitespace char * q = p++; while (!iswhitespace0(*p)) ++p; prev = *p; if (p - q == 1 && (*q == '?' || *q == '.')) { // store values '.' (inapplicable) and '?' (unknown) as null-pointers q = nullptr; keypossible.push_back(false); } else { if (*p) *(p++) = 0; keypossible.push_back(true); } tokens.push_back(q); } } cif_data *current_data = nullptr, *current_frame = nullptr, *global_block = nullptr; // parse into dictionary for (unsigned int i = 0, n = tokens.size(); i < n; i++) { if (!keypossible[i]) { std::cout << "ERROR" << std::endl; break; } else if (tokens[i][0] == '_') { if (i + 1 == n) { std::cout << "ERROR truncated" << std::endl; break; } if (current_frame) { tolowerinplace(tokens[i]); current_frame->dict[tokens[i]].set_value(tokens[i + 1]); } i++; } else if (strcasecmp("loop_", tokens[i]) == 0) { int ncols = 0; int nrows = 0; cif_loop *loop = nullptr; // loop data if (current_frame) { loop = new cif_loop; // add to loops list current_frame->loops.push_back(loop); } // columns while (++i < n && keypossible[i] && tokens[i][0] == '_') { tolowerinplace(tokens[i]); if (current_frame) { current_frame->dict[tokens[i]].set_loop(loop, ncols); } ncols++; } if (loop) { // loop data loop->values = (const char **) &tokens[i]; loop->ncols = ncols; } // rows while (i < n && !(keypossible[i] && isspecial(tokens[i]))) { i += ncols; if (i > n) { std::cout << "ERROR truncated loop" << std::endl; break; } nrows++; } // loop data if (loop) { loop->nrows = nrows; } i--; } else if (strncasecmp("data_", tokens[i], 5) == 0) { const char * key(tokens[i] + 5); datablocks[key] = current_data = current_frame = new cif_data; } else if (strncasecmp("global_", tokens[i], 5) == 0) { // STAR feature, not supported in CIF global_block = current_data = current_frame = new cif_data; } else if (strncasecmp("save_", tokens[i], 5) == 0) { if (tokens[i][5] && current_data) { // begin const char * key(tokens[i] + 5); current_data->saveframes[key] = current_frame = new cif_data; } else { // end current_frame = current_data; } } else { std::cout << "ERROR" << std::endl; break; } } if (global_block) delete global_block; return true; }