layer0/Parse.cpp (272 lines of code) (raw):
/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* Copyright (c) Schrodinger, LLC.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
#include"os_predef.h"
#include"Parse.h"
#include <stdio.h>
#include <string.h>
const char *ParseNextLine(const char *p)
{
char ch;
const char mask = -16; /* 0xF0 */
while((mask & p[0]) && (mask & p[1]) && (mask & p[2]) && (mask & p[3])) /* trusting short-circuit to avoid overrun */
p += 4;
while((ch = *p)) {
p++;
if(ch == 0xD) { /* Mac or PC */
if((*p) == 0xA) /* PC */
return p + 1;
return p;
} else if(ch == 0xA) { /* Unix */
return p;
}
}
return p;
}
/*========================================================================*/
const char *ParseNCopy(char *q, const char *p, int n)
{ /* n character copy */
char ch;
while((ch = *p)) {
if((ch == 0xD) || (ch == 0xA)) /* don't copy end of lines */
break;
if(!n)
break;
n--;
p++;
*(q++) = ch;
}
*q = 0;
return p;
}
const char *ParseSkipEquals(const char *p)
{
while(*p) {
if(*p != '=')
p++;
else
break;
}
if(*p) {
p++;
while(*p) {
if(*p < 33) /* skip whitespace */
p++;
else
break;
}
}
return p;
}
/*
* Skip all characters in `chars`
*
* Example to skip all whitespace:
* p = ParseSkipChars(p, " \t\r\n");
*/
static const char *ParseSkipChars(const char *p, const char *chars) {
while (*p && strchr(chars, *p)) { ++p; }
return p;
}
/*========================================================================*/
const char *ParseIntCopy(char *q, const char *p, int n)
{ /* integer copy */
while(*p) {
if((*p == 0xD) || (*p == 0xA)) /* don't skip end of lines */
break;
if(*p <= 32 || !((*p >= '0') && (*p <= '9')))
p++;
else
break;
}
while(*p) {
if(*p <= 32)
break;
if(!n)
break;
if((*p == 0xD) || (*p == 0xA)) /* don't copy end of lines */
break;
if(!((*p >= '0') && (*p <= '9')))
break;
*(q++) = *(p++);
n--;
}
*q = 0;
return p;
}
/*========================================================================*/
const char *ParseAlphaCopy(char *q, const char *p, int n)
{ /* integer copy */
while(*p) {
if((*p == 0xD) || (*p == 0xA)) /* don't skip end of lines */
break;
if(*p <= 32 || !(((*p >= 'A') && (*p <= 'Z')) || ((*p >= 'a') && (*p <= 'z'))))
p++;
else
break;
}
while(*p) {
if(*p <= 32)
break;
if(!n)
break;
if((*p == 0xD) || (*p == 0xA)) /* don't copy end of lines */
break;
if(!(((*p >= 'A') && (*p <= 'Z')) || ((*p >= 'a') && (*p <= 'z'))))
break;
*(q++) = *(p++);
n--;
}
*q = 0;
return p;
}
/* ParseFloat3List: scan in Python-like list of 3 floats */
int ParseFloat3List(const char *parg, float *vals){
int n;
// skip white space and opening brackets
parg = ParseSkipChars(parg, "([ \t\r\n");
for (int i = 0; i < 3; ++i) {
if (!sscanf(parg, "%f%n", vals, &n))
return false;
// skip white space and commas
parg = ParseSkipChars(parg + n, ", \t\r\n");
++vals;
}
return true;
}
/*========================================================================*/
const char *ParseWordCopy(char *q, const char *p, int n)
{ /* word copy */
while(*p) {
if((*p == 0xD) || (*p == 0xA)) /* don't skip end of lines */
break;
if(*p <= 32)
p++;
else
break;
}
while(*p) {
if(*p <= 32)
break;
if(!n) {
while(*p > 32) /* finish scanning word, but don't copy into field */
p++;
break;
}
if((*p == 0xD) || (*p == 0xA)) /* don't copy end of lines */
break;
*(q++) = *(p++);
n--;
}
*q = 0;
return p;
}
/*========================================================================*/
const char *ParseWordNumberCopy(char *q, const char *p, int n)
{ /* word copy */
int digit_seen_last = 0;
while(*p) {
if((*p == 0xD) || (*p == 0xA)) /* don't skip end of lines */
break;
if(*p <= 32)
p++;
else
break;
}
while(*p) {
if(*p <= 32)
break;
if(!n) {
while(*p > 32) /* finish scanning word, but don't copy into field */
p++;
break;
}
if((*p == 0xD) || (*p == 0xA)) /* don't copy end of lines */
break;
if(digit_seen_last && (*p == '-')) /* parse 123.123-1234.465 as two separate words */
break;
digit_seen_last = (((*p) >= '0') && ((*p) <= '9')) || ((*p) == '.');
*(q++) = *(p++);
n--;
}
*q = 0;
return p;
}
/*========================================================================
* ParseWord
* Copy first word from p into q with fewer than n letters
* PARAMS
* char* q
* destination; will contain the first word from p
* char* p
* source; comes in as a string of tokens
* RETURNS
* p modified so it points to one character past the end of the first
* word of p. Eg. "im a temp selection" => " a temp selection" and
* the return value *q = "im"
*/
const char *ParseWord(char *q, const char *p, int n)
{ /* word copy, across lines */
/* increment ptr past non character input, like spaces and line feeds, bells. */
while(*p) {
if(*p <= 32)
p++;
else
break;
}
/* copy p to q stopping when we hit a space, or run out of
* space (memory) according to the limit n */
while(*p) {
if(*p <= 32)
break;
if(!n)
break;
*(q++) = *(p++);
n--;
}
*q = 0;
return p;
}
/*========================================================================*/
const char *ParseNTrim(char *q, const char *p, int n)
{ /* n character trimmed copy */
char *q_orig = q;
while(*p && n) {
if((*p == 0xD) || (*p == 0xA)) /* don't skip end of lines */
break;
if(*p <= 32) {
p++;
n--;
} else
break;
}
while(*p) {
if(!n)
break;
if((*p == 0xD) || (*p == 0xA)) /* don't copy end of lines */
break;
*(q++) = *(p++);
n--;
}
while(q > q_orig) {
if(*(q - 1) <= 32)
q--;
else
break;
}
*q = 0;
return p;
}
/*========================================================================*/
const char *ParseNTrimRight(char *q, const char *p, int n)
{ /* n character trimmed copy */
char *q_orig = q;
while(*p) {
if(!n)
break;
if((*p == 0xD) || (*p == 0xA)) /* don't copy end of lines */
break;
*(q++) = *(p++);
n--;
}
while(q > q_orig) {
if(*(q - 1) <= 32)
q--;
else
break;
}
*q = 0;
return p;
}
/*========================================================================*/
const char *ParseCommaCopy(char *q, const char *p, int n)
{ /* n character copy up to comma */
while(*p) {
if(!n)
break;
if((*p == 0xD) || (*p == 0xA)) /* don't copy end of lines */
break;
if(*p == ',')
break;
*(q++) = *(p++);
n--;
}
*q = 0;
return p;
}
/*========================================================================*/
const char *ParseNSkip(const char *p, int n)
{ /* n character skip */
while(*p) {
if(!n)
break;
if((*p == 0xD) || (*p == 0xA)) /* stop at newlines */
break;
p++;
n--;
}
return p;
}