1 /* ----------------------------------------------------------------------
2 LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
3 https://www.lammps.org/, Sandia National Laboratories
4 Steve Plimpton, sjplimp@sandia.gov
5
6 Copyright (2003) Sandia Corporation. Under the terms of Contract
7 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
8 certain rights in this software. This software is distributed under
9 the GNU General Public License.
10
11 See the README file in the top-level LAMMPS directory.
12 ------------------------------------------------------------------------- */
13
14 #include "arg_info.h"
15
16 #include <cstring>
17 #include <stdexcept>
18
19 using namespace LAMMPS_NS;
20
21 /** Class for processing references to fixes, computes and variables
22 *
23 * This class provides an abstraction for the repetitive task of
24 * parsing arguments that may contain references to fixes, computes,
25 * variables, or custom per-atom properties. It will identify the name
26 * and the index value in the first and second dimension, if present.
27 *
28 * \param arg string with possible reference
29 * \param allowed integer with bitmap of allowed types of references */
30
ArgInfo(const std::string & arg,int allowed)31 ArgInfo::ArgInfo(const std::string &arg, int allowed) : type(NONE), dim(0), index1(-1), index2(-1)
32 {
33 if (((arg.size() > 3) && (arg[1] == '2') && (arg[2] == '_')) ||
34 ((arg.size() > 2) && (arg[1] == '_'))) {
35 if ((arg[0] == 'c') && (allowed & COMPUTE))
36 type = COMPUTE;
37 else if ((arg[0] == 'f') && (allowed & FIX))
38 type = FIX;
39 else if ((arg[0] == 'v') && (allowed & VARIABLE))
40 type = VARIABLE;
41 else if ((arg[0] == 'd') && (allowed & DNAME))
42 type = DNAME;
43 else if ((arg[0] == 'i') && (allowed & INAME))
44 type = INAME;
45 else {
46 index1 = 0;
47 name = arg;
48 return;
49 }
50 const int offset = (arg[1] == '_') ? 2 : 3;
51
52 std::size_t has_idx1 = arg.find('[', offset);
53 if (has_idx1 != std::string::npos) {
54 name = arg.substr(offset, has_idx1 - offset);
55 dim = 1;
56
57 std::size_t has_idx2 = arg.find('[', has_idx1 + 1);
58 if (has_idx2 != std::string::npos) {
59 dim = 2;
60
61 if (arg[arg.size() - 1] != ']') {
62 type = UNKNOWN;
63 } else {
64 try {
65 index2 = std::stoi(arg.substr(has_idx2 + 1, arg.size() - (has_idx2 + 2)));
66 } catch (std::invalid_argument &) {
67 type = UNKNOWN;
68 }
69 }
70 } else
71 has_idx2 = arg.size();
72
73 if ((arg[has_idx2 - 1] != ']') || ((dim == 1) && (arg.find(']') != has_idx2 - 1))) {
74 type = UNKNOWN;
75 } else {
76 try {
77 index1 = std::stoi(arg.substr(has_idx1 + 1, arg.size() - (has_idx1 + 2)));
78 } catch (std::invalid_argument &) {
79 type = UNKNOWN;
80 }
81 }
82 } else {
83 index1 = 0;
84 name = arg.substr(offset);
85 }
86 } else {
87 index1 = 0;
88 name = arg;
89 }
90 }
91
92 /* ---------------------------------------------------------------------- */
93
94 /*! make copy of the ID of the reference as C-style string
95 *
96 * The ID is copied into a buffer allocated with "new" and thus
97 * must be later deleted with "delete []" to avoid a memory leak.
98 * Because it is a full copy in a newly allocated buffer, the
99 * lifetime of this string extends beyond the the time the ArgInfo
100 * class is in scope.
101 *
102 * \return copy of string as char * */
103
copy_name()104 char *ArgInfo::copy_name()
105 {
106 char *dest = new char[name.size() + 1];
107 strcpy(dest, name.c_str()); // NOLINT
108 return dest;
109 }
110