Panda3D
Loading...
Searching...
No Matches
rangeDescription.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file rangeDescription.cxx
10 * @author drose
11 * @date 2003-09-07
12 */
13
14#include "rangeDescription.h"
15#include "string_utils.h"
16#include "pnotify.h"
17
18using std::string;
19
20/**
21 *
22 */
23RangeDescription::
24RangeDescription() {
25}
26
27/**
28 * Parses a string of comma- and hyphen-delimited unicode values, in decimal
29 * and/or hex, including possible bracket-delimited ASCII characters, as may
30 * have been passed on a command line. Returns true if the parameter is
31 * parsed correctly, false otherwise.
32 */
34parse_parameter(const string &param) {
35 // First, go through and separate the string by commas. We have to do this
36 // by hand instead of calling tokenize(), because we also have to scan for
37 // square brackets, which may contain nested commas.
38 size_t p = 0;
39 while (p < param.length()) {
40 size_t q = param.find_first_of("[,", p);
41 if (q == string::npos) {
42 return parse_word(trim(param.substr(p)));
43 }
44 if (!parse_word(trim(param.substr(p, q - p)))) {
45 return false;
46 }
47
48 if (param[q] == '[') {
49 // A square bracket means we must search for the matching square
50 // bracket. However, a right bracket immediately after the left bracket
51 // doesn't count; we start the scan after that.
52 p = param.find("]", q + 2);
53 if ( p == string::npos) {
54 nout << "Unclosed open bracket.\n";
55 return false;
56 }
57 if (!parse_bracket(param.substr(q + 1, p - q - 1))) {
58 return false;
59 }
60 p = p + 1;
61
62 } else {
63 // Otherwise, if the separator was just a comma, the next character
64 // begins the next word.
65 p = q + 1;
66 }
67 }
68
69 return true;
70}
71
72/**
73 *
74 */
75void RangeDescription::
76output(std::ostream &out) const {
77 bool first_time = true;
78 RangeList::const_iterator ri;
79 for (ri = _range_list.begin(); ri != _range_list.end(); ++ri) {
80 const Range &range = (*ri);
81 if (!first_time) {
82 out << ",";
83 }
84 first_time = false;
85 if (range._from_code == range._to_code) {
86 out << range._from_code;
87 } else {
88 out << range._from_code << "-" << range._to_code;
89 }
90 }
91}
92
93/**
94 * Parses a single "word", i.e. the text delimited by commas, that might be
95 * listed on the command line. This is generally either the empty string, a
96 * single number, or a pair of numbers separated by a hyphen.
97 */
98bool RangeDescription::
99parse_word(const string &word) {
100 if (word.empty()) {
101 return true;
102 }
103
104 // It's not empty, so see if it includes a hyphen.
105 size_t hyphen = word.find('-');
106 if (hyphen == string::npos) {
107 // Nope, just one number.
108 int code;
109 if (!parse_code(word, code)) {
110 return false;
111 }
112 add_singleton(code);
113
114 } else {
115 // Two numbers separated by a hyphen.
116 int from_code, to_code;
117 if (!parse_code(word.substr(0, hyphen), from_code)) {
118 return false;
119 }
120 if (!parse_code(word.substr(hyphen + 1), to_code)) {
121 return false;
122 }
123 add_range(from_code, to_code);
124 }
125
126 return true;
127}
128
129/**
130 * Parses a single numeric value, either decimal or hexadecimal, and stores it
131 * in the indicated parameter. Returns true if successful, false otherwise.
132 */
133bool RangeDescription::
134parse_code(const string &word, int &code) {
135 string str = trim(word);
136 const char *nptr = str.c_str();
137 char *endptr;
138 code = strtol(nptr, &endptr, 0);
139 if (*endptr == '\0') {
140 return true;
141 }
142
143 nout << "Invalid Unicode value: " << word << "\n";
144 return false;
145}
146
147/**
148 * Parses the text listed between square brackets on the command line.
149 */
150bool RangeDescription::
151parse_bracket(const string &str) {
152 string::const_iterator si;
153 si = str.begin();
154 while (si != str.end()) {
155 int ch = (*si);
156 ++si;
157 if (si != str.end() && (*si) == '-') {
158 // A hyphen indicates a range.
159 ++si;
160 if (si == str.end()) {
161 // Unless the hyphen is the last character.
162 add_singleton(ch);
163 add_singleton('-');
164 } else {
165 add_range(ch, (*si));
166 ++si;
167 }
168 } else {
169 // Anything other than a hyphen indicates a singleton.
170 add_singleton(ch);
171 }
172 }
173
174 return true;
175}
bool parse_parameter(const std::string &param)
Parses a string of comma- and hyphen-delimited unicode values, in decimal and/or hex,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string trim(const string &str)
Returns a new string representing the contents of the given string with both leading and trailing whi...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.