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