11 #define epicsExportSharedSymbols 18 using std::ostringstream;
31 struct CreateRequestImpl {
46 OptionPair(
string name,
string value)
53 vector<OptionPair> optionList;
57 CreateRequestImpl() {}
60 void removeBlanks(
string&
str)
63 string::size_type pos = str.find_first_of(
' ');
64 if(pos==string::npos)
return;
69 size_t findMatchingBrace(
string&
request,
size_t index,
int numOpen) {
70 size_t openBrace = request.find(
'{', index+1);
71 size_t closeBrace = request.find(
'}', index+1);
72 if(openBrace == string::npos && closeBrace == string::npos){
73 throw std::runtime_error(request +
" mismatched {}");
75 if (openBrace != string::npos && openBrace!=0) {
76 if(openBrace<closeBrace)
return findMatchingBrace(request,openBrace,numOpen+1);
77 if(numOpen==1)
return closeBrace;
78 return findMatchingBrace(request,closeBrace,numOpen-1);
80 if(numOpen==1)
return closeBrace;
81 return findMatchingBrace(request,closeBrace,numOpen-1);
84 size_t findMatchingBracket(
string& request,
size_t index) {
85 for(
size_t i=index+1;
i< request.size(); ++
i) {
86 if(request[
i] ==
']') {
88 throw std::runtime_error(request +
" mismatched []");
93 throw std::runtime_error(request +
" missing ]");
96 size_t findEndField(
string& request) {
98 size_t maxind = request.size() -1;
100 if(request[ind]==
',')
return ind;
101 if(request[ind]==
'[') {
102 size_t closeBracket = findMatchingBracket(request,ind);
103 if(closeBracket==string::npos)
return closeBracket;
107 if(request[ind]==
'{') {
108 size_t closeBrace = findMatchingBrace(request,ind,1);
109 if(closeBrace==string::npos)
return closeBrace;
110 if(ind>=request.size())
return request.size();
114 if(request[ind]==
'.') {
118 if(ind>=maxind)
break;
121 return request.size();
124 vector<string> split(
string const & commaSeparatedList) {
125 string::size_type numValues = 1;
126 string::size_type index=0;
128 string::size_type pos = commaSeparatedList.find(
',',index);
129 if(pos==string::npos)
break;
133 vector<string> valueList(numValues,
"");
135 for(
size_t i=0;
i<numValues;
i++) {
136 size_t pos = commaSeparatedList.find(
',',index);
137 string value = commaSeparatedList.substr(index,pos-index);
138 valueList[
i] = value;
144 Node createRequestOptions(
145 string const & request)
147 if(request.length()<=1) {
148 throw std::runtime_error(
"logic error empty options");
151 vector<string> items = split(request);
153 size_t nitems = items.size();
154 for(
size_t j=0; j<
nitems; j++) {
155 string item = items[j];
156 size_t equals = item.find(
'=');
157 if(equals==string::npos || equals==0) {
158 throw std::runtime_error(item +
" illegal option " + request);
160 top.push_back(Node(item.substr(0,equals)));
161 string name = fullFieldName +
"._options." + item.substr(0,equals);
162 string value = item.substr(equals+1);
163 optionList.push_back(OptionPair(name,value));
165 Node node(
"_options");
171 void createSubNode(Node &node,
string const & crequest)
173 string request = crequest;
175 for(
size_t i=0;
i<request.size(); ++
i) {
176 if(request[
i]==
'[') { end =
i;
break;}
177 if(request[
i]==
'.') { end =
i;
break;}
178 if(request[
i]==
'{') { end =
i;
break;}
179 if(request[
i]==
',') { end =
i;
break;}
181 char chr = request[end];
184 string saveFullName = fullFieldName;
185 fullFieldName +=
"." + request.substr(0,end);
186 size_t endBracket = findMatchingBracket(request,end);
187 string options = request.substr(end+1,endBracket -end -1);
188 optionNode = createRequestOptions(options);
189 fullFieldName = saveFullName;
190 size_t next = endBracket+1;
191 if(next<request.size()) {
192 request = request.substr(0, end) + request.substr(endBracket+1);
194 request = request.substr(0, end);
197 for(
size_t i=0;
i<request.size(); ++
i) {
198 if(request[
i]==
'.') { end =
i;
break;}
199 if(request[
i]==
'{') { end =
i;
break;}
200 if(request[
i]==
',') { end =
i;
break;}
204 if(end==0) end = request.size();
205 string name = request.substr(0,end);
207 throw std::runtime_error(
"null field name " + request);
209 string saveFullName = fullFieldName;
210 fullFieldName +=
"." + name;
211 if(end==request.size()) {
213 if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
214 node.nodes.push_back(subNode);
215 fullFieldName = saveFullName;
220 if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
221 node.nodes.push_back(subNode);
222 string rest = request.substr(end+1);
223 fullFieldName = saveFullName;
224 createSubNode(node,rest);
228 request = request.substr(end+1);
229 if(request.size()==string::npos || request.size()<1) {
230 throw std::runtime_error(
"null field name " + request);
233 if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
234 size_t endField = findEndField(request);
235 string subRequest = request.substr(0, endField);
236 createSubNode(subNode,subRequest);
237 node.nodes.push_back(subNode);
238 size_t next = endField+1;
239 if(next>=request.size()) {
240 fullFieldName = saveFullName;
243 request = request.substr(next);
244 fullFieldName = saveFullName;
245 createSubNode(node,request);
249 size_t endBrace = findEndField(request);
250 if((end+1)>=(endBrace-1)) {
251 throw std::runtime_error(
"illegal syntax " + request);
253 string subRequest = request.substr(end+1,endBrace-1 -end -1);
254 if(subRequest.size()<1) {
255 throw std::runtime_error(
"empty {} " + request);
258 if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode);
259 createSubNode(subNode,subRequest);
260 node.nodes.push_back(subNode);
261 size_t next = endBrace + 1;
262 if(next>=request.size()) {
263 fullFieldName = saveFullName;
266 request = request.substr(next);
267 fullFieldName = saveFullName;
268 createSubNode(node,request);
271 throw std::runtime_error(
"logic error");
276 size_t num = nodes.size();
279 for(
size_t i=0;
i<num; ++
i) {
280 Node node = nodes[
i];
281 names[
i] = node.name;
282 if(node.name.compare(
"_options")==0) {
283 fields[
i] = createOptions(node.nodes);
285 vector<Node> subNode = node.nodes;
286 if(subNode.empty()) {
287 fields[
i] = fieldCreate->createStructure();
289 fields[
i] = createSubStructure(subNode);
300 size_t num = nodes.size();
303 for(
size_t i=0;
i<num; ++
i) {
304 Node node = nodes[
i];
305 names[
i] = node.name;
306 fields[
i] = fieldCreate->createScalar(
pvString);
314 string const & crequest)
317 string request = crequest;
318 if (!request.empty()) removeBlanks(request);
321 return fieldCreate->createStructure()->build();
323 size_t offsetRecord = request.find(
"record[");
324 size_t offsetField = request.find(
"field(");
325 size_t offsetPutField = request.find(
"putField(");
326 size_t offsetGetField = request.find(
"getField(");
327 if(offsetRecord==string::npos
328 && offsetField==string::npos
329 && offsetPutField==string::npos
330 && offsetGetField==string::npos)
332 request =
"field(" + request +
")";
333 offsetField = request.find(
"field(");
338 for(
size_t i=0;
i< request.length() ; ++
i) {
339 char chr = request[
i];
340 if(chr==
'(') numParan++;
341 if(chr==
')') numParan--;
342 if(chr==
'{') numBrace++;
343 if(chr==
'}') numBrace--;
344 if(chr==
'[') numBracket++;
345 if(chr==
']') numBracket--;
349 oss <<
"mismatched () " << numParan;
350 throw std::runtime_error(oss.str());
354 oss <<
"mismatched {} " << numBrace;
355 throw std::runtime_error(oss.str());
359 oss <<
"mismatched [] " << numBracket;
360 throw std::runtime_error(oss.str());
364 if(offsetRecord!=string::npos) {
365 fullFieldName =
"record";
366 size_t openBracket = request.find(
'[', offsetRecord);
367 size_t closeBracket = request.find(
']', openBracket);
368 if(closeBracket==string::npos) {
369 throw std::runtime_error(request.substr(offsetRecord) +
370 "record[ does not have matching ]");
372 if(closeBracket-openBracket > 3) {
374 Node optNode = createRequestOptions(
375 request.substr(openBracket+1,closeBracket-openBracket-1));
376 node.nodes.push_back(optNode);
380 if(offsetField!=string::npos) {
381 fullFieldName =
"field";
383 size_t openParan = request.find(
'(', offsetField);
384 size_t closeParan = request.find(
')', openParan);
385 if(closeParan==string::npos) {
386 throw std::runtime_error(request.substr(offsetField)
387 +
" field( does not have matching )");
389 if(closeParan>openParan+1) {
390 createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
394 if(offsetGetField!=string::npos) {
395 fullFieldName =
"getField";
396 Node node(
"getField");
397 size_t openParan = request.find(
'(', offsetGetField);
398 size_t closeParan = request.find(
')', openParan);
399 if(closeParan==string::npos) {
400 throw std::runtime_error(request.substr(offsetField)
401 +
" getField( does not have matching )");
403 if(closeParan>openParan+1) {
404 createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
408 if(offsetPutField!=string::npos) {
409 fullFieldName =
"putField";
410 Node node(
"putField");
411 size_t openParan = request.find(
'(', offsetPutField);
412 size_t closeParan = request.find(
')', openParan);
413 if(closeParan==string::npos) {
414 throw std::runtime_error(request.substr(offsetField)
415 +
" putField( does not have matching )");
417 if(closeParan>openParan+1) {
418 createSubNode(node,request.substr(openParan+1,closeParan-openParan-1));
422 }
catch (std::exception &e) {
423 throw std::runtime_error(std::string(
"while creating Structure exception ")+e.what());
425 size_t num = top.size();
428 for(
size_t i=0;
i<num; ++
i) {
430 names[
i] = node.name;
431 vector<Node> subNode = node.nodes;
432 if(subNode.empty()) {
433 fields[
i] = fieldCreate->createStructure();
435 fields[
i] = createSubStructure(subNode);
439 if(!structure)
throw std::invalid_argument(
"bad request " + crequest);
441 for(
size_t i=0;
i<optionList.size(); ++
i) {
442 OptionPair pair = optionList[
i];
443 string name = pair.name;
444 string value = pair.value;
446 if(!pvField)
throw std::invalid_argument(
"bad request " + crequest);
459 namespace epics {
namespace pvData {
472 }
catch(std::exception& e) {
474 return PVStructure::shared_pointer();
481 return I.createRequest(request);
PVStructure::shared_pointer createRequest(std::string const &request)
static CreateRequest::shared_pointer create()
Internal: bucket item structure.
Create pvRequest structure for Channel methods.
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
TODO only here because of the Lockable.
std::tr1::shared_ptr< const Structure > StructureConstPtr
PVStructure::shared_pointer createRequest(std::string const &request)
std::tr1::shared_ptr< PVDataCreate > PVDataCreatePtr
PVString is special case, since it implements SerializableArray.
APIs for the epicsMutex mutual exclusion semaphore.
std::vector< FieldConstPtr > FieldConstPtrArray
std::tr1::shared_ptr< const Field > FieldConstPtr
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
std::tr1::shared_ptr< PVStructure > PVStructurePtr
std::tr1::shared_ptr< PVString > PVStringPtr
std::vector< std::string > StringArray
std::tr1::shared_ptr< FieldCreate > FieldCreatePtr
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()