diff --git a/pvtoolsSrc/pvput.cpp b/pvtoolsSrc/pvput.cpp index d86d004..3f96ac5 100644 --- a/pvtoolsSrc/pvput.cpp +++ b/pvtoolsSrc/pvput.cpp @@ -58,8 +58,15 @@ bool debug = false; void usage (bool details=false) { fprintf (stderr, - "Usage: pvput [options] \n\n" + "Usage: pvput [options] \n" + " pvput [options] [ ...]\n" " pvput [options] = ...\n" + " pvput [options] \n"); +#ifdef USE_JSON + fprintf (stderr, + " pvput [options] \n"); +#endif + fprintf (stderr, "\n" " -h: Help: Print this message\n" " -v: Print version and exit\n" @@ -80,26 +87,35 @@ void usage (bool details=false) if(details) { fprintf (stderr, #ifdef USE_JSON - " JSON support is present\n" + "\n JSON support is present\n" #else - " no JSON support (needs EPICS Base >=3.15.0.1)\n"; + "\n no JSON support (needs EPICS Base >=3.15.0.1)\n" #endif ); fprintf (stderr, "\nExamples:\n" "\n" - " pvput double01 1.234\n" - "equivalent to:\n" + " pvput double01 1.234 # shorthand\n" " pvput double01 value=1.234\n" + "\n" + " pvput arr:pv X 1.0 2.0 # shorthand (X is arbitrary and ignored)\n" + " pvput arr:pv \"[1.0, 2.0]\" # shorthand\n" + " pvput arr:pv value=\"[1.0, 2.0]\"\n" ); #ifdef USE_JSON fprintf (stderr, "\n" - "Field values may be given with JSON syntax. eg. and array:\n" + "Field values may be given with JSON syntax.\n" "\n" - " pvput arr:pv \"[1.0, 2.0]\"\n" - "equivalent to:\n" - " pvput arr:pv value=\"[1.0, 2.0]\"\n"); + "Complete structure\n" + "\n" + " pvput double01 '{\"value\":1.234}'\n" + "\n" + "Sub-structure(s)\n" + "\n" + " pvput group:pv some='{\"value\":1.234}' other='{\"value\":\"a string\"}'\n" + "\n" + ); #endif } } @@ -244,7 +260,8 @@ struct Putter : public pvac::ClientChannel::PutCallback Putter() :done(false) {} - std::string jblob; + typedef shared_vector bare_t; + bare_t bare; typedef std::pair KV_t; typedef std::vector pairs_t; @@ -254,13 +271,68 @@ struct Putter : public pvac::ClientChannel::PutCallback virtual void putBuild(const epics::pvData::StructureConstPtr& build, Args& args) { + if(debug) std::cerr<<"Server defined structure\n"<createPVStructure(build)); - if(pairs.empty()) { - std::istringstream strm(jblob); + if(bare.size()==1 && bare[0][0]=='{') { + if(debug) fprintf(stderr, "In JSON top mode\n"); +#ifdef USE_JSON + std::istringstream strm(bare[0]); parseJSON(strm, root, &args.tosend); +#else +#endif + + } else if(pairs.empty()) { + if(debug) fprintf(stderr, "In plain value mode\n"); + + PVFieldPtr fld(root->getSubField("value")); + Type ftype = fld->getField()->getType(); + + if(ftype==scalar) { + if(bare.size()!=1) { + throw std::runtime_error("Can't assign multiple values to scalar"); + } + PVScalar* sfld(static_cast(fld.get())); + sfld->putFrom(bare[0]); + args.tosend.set(sfld->getFieldOffset()); + + } else if(ftype==scalarArray) { + PVScalarArray* sfld(static_cast(fld.get())); + + // first element is "length" which we ignore for compatibility + bare.slice(1); + + sfld->putFrom(freeze(bare)); + args.tosend.set(sfld->getFieldOffset()); + + } else if(ftype==structure && fld->getField()->getID()=="enum_t") { + if(bare.size()!=1) { + throw std::runtime_error("Can't assign multiple values to enum"); + } + PVStructure* sfld(static_cast(fld.get())); + + PVScalar* idxfld(sfld->getSubFieldT("index").get()); + PVStringArray::const_svector choices(sfld->getSubFieldT("choices")->view()); + + bool found=false; + for(size_t i=0; iputFrom(i); + found=true; + } + } + + if(!found) { + // try to parse as integer + idxfld->putFrom(bare[0]); + } + + args.tosend.set(idxfld->getFieldOffset()); + } } else { + if(debug) fprintf(stderr, "In field=value mode\n"); + for(pairs_t::const_iterator it=pairs.begin(), end=pairs.end(); it!=end; ++it) { PVFieldPtr fld(root->getSubField(it->first)); @@ -282,7 +354,11 @@ struct Putter : public pvac::ClientChannel::PutCallback } else if(it->second[0]=='{' || it->second[0]=='[') { std::istringstream strm(it->second); +#ifdef USE_JSON parseJSON(strm, fld, &args.tosend); +#else + throw std::runtime_error("JSON support not built"); +#endif } else { PVScalarPtr sfld(std::tr1::dynamic_pointer_cast(fld)); if(!sfld) { @@ -478,39 +554,38 @@ int main (int argc, char *argv[]) Putter thework; - if(values[0][0]=='{' && values.size()>1) { - usage(); - fprintf(stderr, "\nMissing quotes around JSON?\n"); - return 1; - } else if(values[0][0]=='{') { - // write entire blob + for(size_t i=0, N=values.size(); i