File: CifDataValueFormatter.cpp

package info (click to toggle)
pymol 2.5.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 42,288 kB
  • sloc: cpp: 476,472; python: 76,538; ansic: 29,510; javascript: 6,792; sh: 47; makefile: 24
file content (97 lines) | stat: -rw-r--r-- 2,282 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 * Cif export helper stuff
 *
 * (c) 2016 Schrodinger, Inc.
 */

#include "os_std.h"
#include "CifDataValueFormatter.h"
#include "strcasecmp.h"

/**
 * Simplified whitespace test. Returns true if string `s` contains any character
 * between 0x01 and 0x20 (this range contains all whitespace characters and
 * no printable characters)
 */
static
bool has_whitespace(const char * s) {
  for (; *s; ++s)
    if (*s <= ' ')
      return true;
  return false;
}

/**
 * Return true if `s` contains the given quote character followed by white space
 */
static
bool has_quotespace(const char * s, char quote) {
  for (; (s = strchr(s, quote)); ++s)
    if (s[1] && s[1] <= ' ')
      return true;
  return false;
}

/**
 * Return true if `s` is a "simple data value" according to the CIF
 * syntax specification
 */
static
bool cif_is_simpledatavalue(const char * s) {
  return (
      // first character is special
      !strchr("_#$'\"[];", s[0]) &&
      // whitespace
      !has_whitespace(s) &&
      // special values '.' (inapplicable) and '?' (unknown)
      !((s[0] == '.' || s[0] == '?') && !s[1]) &&
      // prefix is special
      strncasecmp("data_", s, 5) &&
      strncasecmp("save_", s, 5) &&
      // reserved words
      strcasecmp("loop_", s) &&
      strcasecmp("stop_", s) &&
      strcasecmp("global_", s));
}

std::string & CifDataValueFormatter::nextbuf() {
  // advance circular pointer
  m_i = (m_i + 1) % m_buf.size();
  return m_buf[m_i];
}

const char * CifDataValueFormatter::quoted(const char * s) {
  const char * quote = nullptr;

  if (!strchr(s, '\n')) {
    if (!has_quotespace(s, '\'')) {
      quote = "'";
    } else if (!has_quotespace(s, '"')) {
      quote = "\"";
    }
  }

  if (!quote) {
    quote = "\n;";
    if (strstr(s, quote)) {
      printf(" CIF-Warning: data value contains unquotable <newline><semicolon>\n");
      return "<UNQUOTABLE>";
    }
  }

  return nextbuf().assign(quote).append(s).append(quote).c_str();
}

const char * CifDataValueFormatter::operator() (const char * s, const char * d) {
  if (!s[0])
    return d;

  if (cif_is_simpledatavalue(s))
    return s;

  return quoted(s);
}

const char * CifDataValueFormatter::operator() (char c, const char * d) {
  return (*this)(nextbuf().assign(1, c).c_str(), d);
}