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 + -
显示快捷键?