bottleimpl.cpp
来自「一个语言识别引擎」· C++ 代码 · 共 954 行 · 第 1/2 页
CPP
954 行
// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
/*
* Copyright (C) 2006 Paul Fitzpatrick
* CopyPolicy: Released under the terms of the GNU GPL v2.0.
*
*/
#include <yarp/BottleImpl.h>
#include <yarp/BufferedConnectionWriter.h>
#include <yarp/StreamConnectionReader.h>
#include <yarp/StringOutputStream.h>
#include <yarp/StringInputStream.h>
#include <yarp/os/Vocab.h>
#include <yarp/os/NetFloat64.h>
#include <ace/OS_NS_stdlib.h>
#include <ace/OS_NS_stdio.h>
using namespace yarp;
using namespace yarp::os;
//#define YMSG(x) ACE_OS::printf x;
//#define YTRACE(x) YMSG(("at %s\n",x))
#define YMSG(x)
#define YTRACE(x)
// YARP1 compatible codes
//const int StoreInt::code = 1;
//const int StoreString::code = 5;
//const int StoreDouble::code = 2;
//const int StoreList::code = 16;
//const int StoreVocab::code = 32;
//const int StoreBlob::code = 33;
//#define USE_YARP1_PREFIX
// new YARP2 codes
const int StoreInt::code = BOTTLE_TAG_INT;
const int StoreVocab::code = BOTTLE_TAG_VOCAB;
const int StoreDouble::code = BOTTLE_TAG_DOUBLE;
const int StoreString::code = BOTTLE_TAG_STRING;
const int StoreBlob::code = BOTTLE_TAG_BLOB;
const int StoreList::code = BOTTLE_TAG_LIST;
#define UNIT_MASK (BOTTLE_TAG_INT|BOTTLE_TAG_VOCAB|BOTTLE_TAG_DOUBLE|BOTTLE_TAG_STRING|BOTTLE_TAG_BLOB)
#define GROUP_MASK (BOTTLE_TAG_LIST)
yarp::StoreNull BottleImpl::storeNull;
BottleImpl::BottleImpl() {
dirty = true;
nested = false;
speciality = 0;
}
BottleImpl::~BottleImpl() {
clear();
}
void BottleImpl::add(Storable *s) {
content.push_back(s);
dirty = true;
}
void BottleImpl::clear() {
for (unsigned int i=0; i<content.size(); i++) {
delete content[i];
}
content.clear();
dirty = true;
}
void BottleImpl::smartAdd(const String& str) {
if (str.length()>0) {
char ch = str[0];
Storable *s = NULL;
if (ch>='0'&&ch<='9'||ch=='+'||ch=='-'||ch=='.') {
if (str.strstr(".")<0) {
s = new StoreInt(0);
} else {
s = new StoreDouble(0);
}
} else if (ch=='(') {
s = new StoreList();
} else if (ch=='[') {
s = new StoreVocab();
} else if (ch=='{') {
s = new StoreBlob();
} else {
s = new StoreString("");
}
if (s!=NULL) {
s->fromStringNested(str);
//ACE_OS::printf("*** smartAdd [%s] [%s]\n", str.c_str(), s->toString().c_str());
add(s);
}
}
}
void BottleImpl::fromString(const String& line) {
clear();
dirty = true;
String arg = "";
bool quoted = false;
bool back = false;
bool begun = false;
int nested = 0;
int nestedAlt = 0;
String nline = line + " ";
for (unsigned int i=0; i<nline.length(); i++) {
char ch = nline[i];
if (back) {
arg += ch;
back = false;
} else {
if (!begun) {
if (ch!=' '&&ch!='\t'&&ch!='\n'&&ch!='\r') {
begun = true;
}
}
if (begun) {
if (ch=='\"') {
if (!quoted) {
quoted = true;
} else {
quoted = false;
}
}
if (!quoted) {
if (ch=='(') {
nested++;
}
if (ch==')') {
nested--;
}
if (ch=='{') {
nestedAlt++;
}
if (ch=='}') {
nestedAlt--;
}
}
if (ch=='\\') {
back = true;
arg += ch;
} else {
if ((!quoted)&&(ch==' '||ch=='\t'||ch=='\n'||ch=='\r')
&&(nestedAlt==0)
&&(nested==0)) {
smartAdd(arg);
arg = "";
begun = false;
} else {
arg += ch;
}
}
}
}
}
}
bool BottleImpl::isComplete(const char *txt) {
bool quoted = false;
bool back = false;
bool begun = false;
int nested = 0;
int nestedAlt = 0;
String nline = txt;
nline += " ";
for (unsigned int i=0; i<nline.length(); i++) {
char ch = nline[i];
if (back) {
back = false;
} else {
if (!begun) {
if (ch!=' '&&ch!='\t'&&ch!='\n'&&ch!='\r') {
begun = true;
}
}
if (begun) {
if (ch=='\"') {
if (!quoted) {
quoted = true;
} else {
quoted = false;
}
}
if (!quoted) {
if (ch=='(') {
nested++;
}
if (ch==')') {
nested--;
}
if (ch=='{') {
nestedAlt++;
}
if (ch=='}') {
nestedAlt--;
}
}
if (ch=='\\') {
back = true;
//arg += ch;
} else {
if ((!quoted)&&(ch==' '||ch=='\t'||ch=='\n'||ch=='\r')
&&(nestedAlt==0)
&&(nested==0)) {
//smartAdd(arg);
begun = false;
} else {
//arg += ch;
}
}
}
}
}
return nested==0 && nestedAlt==0 && quoted==false;
}
String BottleImpl::toString() {
String result = "";
for (unsigned int i=0; i<content.size(); i++) {
if (i>0) { result += " "; }
Storable& s = *content[i];
result += s.toStringNested();
}
return result;
}
int BottleImpl::size() const {
return content.size();
}
bool BottleImpl::fromBytes(ConnectionReader& reader) {
int id = speciality;
if (id==0) {
id = reader.expectInt();
YMSG(("READ subcode %d\n", id));
} else {
YMSG(("READ skipped subcode %d\n", speciality));
}
Storable *storable = NULL;
int subCode = 0;
switch (id) {
case StoreInt::code:
storable = new StoreInt();
break;
case StoreVocab::code:
storable = new StoreVocab();
break;
case StoreDouble::code:
storable = new StoreDouble();
break;
case StoreString::code:
storable = new StoreString();
break;
case StoreBlob::code:
storable = new StoreBlob();
break;
case StoreList::code:
storable = new StoreList();
YARP_ASSERT(storable!=NULL);
storable->asList()->setNested(true);
break;
default:
if ((id&GROUP_MASK)!=0) {
// typed list
subCode = (id&UNIT_MASK);
storable = new StoreList();
YARP_ASSERT(storable!=NULL);
storable->asList()->specialize(subCode);
storable->asList()->setNested(true);
}
break;
}
if (storable==NULL) {
YARP_ERROR(Logger::get(), "BottleImpl reader failed");
throw IOException((String("BottleImpl reader failed - unrecognized format? ") + NetType::toString(id)).c_str());
}
storable->read(reader);
add(storable);
return true;
}
void BottleImpl::fromBinary(const char *text, int len) {
String wrapper;
wrapper.set(text,len,0);
StringInputStream sis;
sis.add(wrapper);
StreamConnectionReader reader;
Route route;
reader.reset(sis,NULL,route,len,false);
read(reader);
}
bool BottleImpl::fromBytes(const Bytes& data) {
String wrapper;
wrapper.set(data.get(),data.length(),0);
StringInputStream sis;
sis.add(wrapper);
StreamConnectionReader reader;
Route route;
reader.reset(sis,NULL,route,data.length(),false);
clear();
dirty = true; // for clarity
try {
int len = reader.expectInt();
YMSG(("READ bottle length %d\n", len));
for (int i=0; i<len; i++) {
fromBytes(reader);
}
} catch (IOException e) {
YARP_DEBUG(Logger::get(), e.toString() + " -- bottle reader stopped");
return false;
}
return true;
}
void BottleImpl::toBytes(const Bytes& data) {
synch();
YARP_ASSERT(data.length()==byteCount());
ACE_OS::memcpy(data.get(),getBytes(),byteCount());
}
const char *BottleImpl::getBytes() {
synch();
return &data[0];
}
int BottleImpl::byteCount() {
synch();
return data.size();
}
bool BottleImpl::write(ConnectionWriter& writer) {
try {
// could simplify this if knew lengths of blocks up front
if (writer.isTextMode()) {
//writer.appendLine(toString());
writer.appendString(toString().c_str(),'\n');
} else {
#ifdef USE_YARP1_PREFIX
if (!nested) {
String name = "YARP2";
writer.appendInt(name.length()+1);
writer.appendString(name.c_str(),'\0');
}
#endif
synch();
if (!nested) {
// No byte count any more, to facilitate nesting
//YMSG(("bottle byte count %d\n",byteCount()));
//writer.appendInt(byteCount()+sizeof(NetInt32));
writer.appendInt(StoreList::code + speciality);
}
//writer.appendBlockCopy(Bytes((char*)getBytes(),byteCount()));
writer.appendBlock((char*)getBytes(),byteCount());
}
} catch (IOException e) {
YARP_DEBUG(Logger::get(), String("Bottle write exception: ")+e.toString());
return false;
}
return true;
}
bool BottleImpl::read(ConnectionReader& reader) {
bool result = false;
try {
if (reader.isTextMode()) {
String str = reader.expectText().c_str();
bool done = (str.length()<=0);
while (!done) {
if (str[str.length()-1]=='\\') {
str = str.substr(0,str.length()-1);
str += reader.expectText().c_str();
} else {
if (isComplete(str.c_str())) {
done = true;
} else {
str += "\n";
str += reader.expectText().c_str();
}
}
}
fromString(str);
result = true;
} else {
#if USE_YARP1_PREFIX
if (!nested) {
int len = reader.expectInt();
//String name = reader.expectString(len);
String buf((size_t)len);
reader.expectBlock((const char *)buf.c_str(),len);
String name = buf.c_str();
}
#endif
if (!nested) {
// no byte length any more to facilitate nesting
//reader.expectInt(); // the bottle byte ct; ignored
clear();
specialize(0);
int code = reader.expectInt();
code = code & UNIT_MASK;
if (code!=0) {
specialize(code);
}
}
//ManagedBytes b(bct);
//reader.expectBlock(b.get(),b.length());
//result = fromBytes(b.bytes());
result = true;
clear();
dirty = true; // for clarity
int len = 0;
int i = 0;
try {
len = reader.expectInt();
YMSG(("READ got length %d\n", len));
for (i=0; i<len; i++) {
fromBytes(reader);
}
} catch (IOException e) {
YARP_DEBUG(Logger::get(), e.toString() +
" -- bottle reader stopped at " +
NetType::toString(i) + " of " +
NetType::toString(len));
result = false;;
}
}
} catch (IOException e) {
YARP_DEBUG(Logger::get(), String("Bottle read exception: ")+e.toString());
// leave result false
}
return result;
}
void BottleImpl::synch() {
if (dirty) {
if (!nested) {
subCode();
YMSG(("bottle code %d\n",StoreList::code + subCode()));
}
data.clear();
//StringOutputStream sos;
BufferedConnectionWriter writer;
YMSG(("bottle length %d\n",size()));
writer.appendInt(size());
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?