当前位置: 首页>>代码示例>>C++>>正文


C++ BSONElement::codeWScopeObject方法代码示例

本文整理汇总了C++中BSONElement::codeWScopeObject方法的典型用法代码示例。如果您正苦于以下问题:C++ BSONElement::codeWScopeObject方法的具体用法?C++ BSONElement::codeWScopeObject怎么用?C++ BSONElement::codeWScopeObject使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在BSONElement的用法示例。


在下文中一共展示了BSONElement::codeWScopeObject方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: okForStorage

 bool BSONObj::okForStorage() const {
     BSONObjIterator i( *this );
     while ( i.more() ){
         BSONElement e = i.next();
         const char * name = e.fieldName();
         
         if ( strchr( name , '.' ) ||
              strchr( name , '$' ) ){
             return 
                 strcmp( name , "$ref" ) == 0 ||
                 strcmp( name , "$id" ) == 0
                 ;
         }
         
         if ( e.mayEncapsulate() ){
             switch ( e.type() ){
             case Object:
             case Array:
                 if ( ! e.embeddedObject().okForStorage() )
                     return false;
                 break;
             case CodeWScope:
                 if ( ! e.codeWScopeObject().okForStorage() )
                     return false;
                 break;
             default:
                 uassert( 12579, "unhandled cases in BSONObj okForStorage" , 0 );
             }
             
         }
     }
     return true;
 }
开发者ID:erickt,项目名称:mongo,代码行数:33,代码来源:jsobj.cpp

示例2:

        JSFunction::JSFunction( string type , const BSONElement& e ) {
            _type = type;
            _code = e._asCode();

            if ( e.type() == CodeWScope )
                _wantedScope = e.codeWScopeObject();
        }
开发者ID:jackingod,项目名称:mongo,代码行数:7,代码来源:mr_shard.cpp

示例3: parseRequest

    Status GroupCommand::parseRequest(const string& dbname,
                                      const BSONObj& cmdObj,
                                      GroupRequest* request) const {
        request->ns = parseNs(dbname, cmdObj);

        // By default, group requests are regular group not explain of group.
        request->explain = false;

        const BSONObj& p = cmdObj.firstElement().embeddedObjectUserCheck();

        if (p["cond"].type() == Object) {
            request->query = p["cond"].embeddedObject().getOwned();
        }
        else if (p["condition"].type() == Object) {
            request->query = p["condition"].embeddedObject().getOwned();
        }
        else if (p["query"].type() == Object) {
            request->query = p["query"].embeddedObject().getOwned();
        }
        else if (p["q"].type() == Object) {
            request->query = p["q"].embeddedObject().getOwned();
        }

        if (p["key"].type() == Object) {
            request->keyPattern = p["key"].embeddedObjectUserCheck().getOwned();
            if (!p["$keyf"].eoo()) {
                return Status(ErrorCodes::BadValue, "can't have key and $keyf");
            }
        }
        else if (!p["$keyf"].eoo()) {
            request->keyFunctionCode = p["$keyf"]._asCode();
        }
        else {
            // No key specified.  Use the entire object as the key.
        }

        BSONElement reduce = p["$reduce"];
        if (reduce.eoo()) {
            return Status(ErrorCodes::BadValue, "$reduce has to be set");
        }
        request->reduceCode = reduce._asCode();

        if (reduce.type() == CodeWScope) {
            request->reduceScope = reduce.codeWScopeObject().getOwned();
        }

        if (p["initial"].type() != Object) {
            return Status(ErrorCodes::BadValue, "initial has to be an object");
        }
        request->initial = p["initial"].embeddedObject().getOwned();

        if (!p["finalize"].eoo()) {
            request->finalize = p["finalize"]._asCode();
        }

        return Status::OK();
    }
开发者ID:lalford,项目名称:mongo,代码行数:57,代码来源:group.cpp

示例4: recursiveHash

    void BSONElementHasher::recursiveHash( Hasher* h ,
                                           const BSONElement& e ,
                                           bool includeFieldName ) {

        int canonicalType = e.canonicalType();
        h->addData( &canonicalType , sizeof( canonicalType ) );

        if ( includeFieldName ){
            h->addData( e.fieldName() , e.fieldNameSize() );
        }

        if ( !e.mayEncapsulate() ){
            //if there are no embedded objects (subobjects or arrays),
            //compute the hash, squashing numeric types to 64-bit ints
            if ( e.isNumber() ){
                long long int i = e.safeNumberLong(); //well-defined for troublesome doubles
                h->addData( &i , sizeof( i ) );
            }
            else {
                h->addData( e.value() , e.valuesize() );
            }
        }
        else {
            //else identify the subobject.
            //hash any preceding stuff (in the case of codeWscope)
            //then each sub-element
            //then finish with the EOO element.
            BSONObj b;
            if ( e.type() == CodeWScope ) {
                h->addData( e.codeWScopeCode() , e.codeWScopeCodeLen() );
                b = e.codeWScopeObject();
            }
            else {
                b = e.embeddedObject();
            }
            BSONObjIterator i(b);
            while( i.moreWithEOO() ) {
                BSONElement el = i.next();
                recursiveHash( h , el ,  true );
            }
        }
    }
开发者ID:10genReviews,项目名称:mongo,代码行数:42,代码来源:hasher.cpp

示例5: switch

StatusWith<WhereMatchExpressionBase::WhereParams>
ExtensionsCallback::extractWhereMatchExpressionParams(BSONElement where) {
    WhereMatchExpressionBase::WhereParams params;

    switch (where.type()) {
        case mongo::String:
        case mongo::Code:
            params.code = where._asCode();
            params.scope = BSONObj();
            break;
        case mongo::CodeWScope:
            params.code = where._asCode();
            params.scope = where.codeWScopeObject().getOwned();
            break;
        default:
            return {ErrorCodes::BadValue, "$where got bad type"};
    }

    if (params.code.empty()) {
        return {ErrorCodes::BadValue, "code for $where cannot be empty"};
    }

    return params;
}
开发者ID:AlexOreshkevich,项目名称:mongo,代码行数:24,代码来源:extensions_callback.cpp

示例6: valid

// todo: can be a little faster if we don't use toString() here.
    bool BSONObj::valid() const {
        try{
            BSONObjIterator it(*this);
            while( it.moreWithEOO() ){
                // both throw exception on failure
                BSONElement e = it.next(true);
                e.validate();

                if (e.eoo()){
                    if (it.moreWithEOO())
                        return false;
                    return true;
                }else if (e.isABSONObj()){
                    if(!e.embeddedObject().valid())
                        return false;
                }else if (e.type() == CodeWScope){
                    if(!e.codeWScopeObject().valid())
                        return false;
                }
            }
        } catch (...) {
        }
        return false;
    }
开发者ID:erickt,项目名称:mongo,代码行数:25,代码来源:jsobj.cpp

示例7: dcmlNorm


//.........这里部分代码省略.........
            break;

        case mongo::Bool:
            boost::hash_combine(hash, elemToHash.boolean());
            break;

        case mongo::bsonTimestamp:
            boost::hash_combine(hash, elemToHash.timestamp().asULL());
            break;

        case mongo::Date:
            boost::hash_combine(hash, elemToHash.date().asInt64());
            break;

        case mongo::NumberDecimal: {
            const Decimal128 dcml = elemToHash.numberDecimal();
            if (dcml.toAbs().isGreater(Decimal128(std::numeric_limits<double>::max(),
                                                  Decimal128::kRoundTo34Digits,
                                                  Decimal128::kRoundTowardZero)) &&
                !dcml.isInfinite() && !dcml.isNaN()) {
                // Normalize our decimal to force equivalent decimals
                // in the same cohort to hash to the same value
                Decimal128 dcmlNorm(dcml.normalize());
                boost::hash_combine(hash, dcmlNorm.getValue().low64);
                boost::hash_combine(hash, dcmlNorm.getValue().high64);
                break;
            }
            // Else, fall through and convert the decimal to a double and hash.
            // At this point the decimal fits into the range of doubles, is infinity, or is NaN,
            // which doubles have a cheaper representation for.
        }
        case mongo::NumberDouble:
        case mongo::NumberLong:
        case mongo::NumberInt: {
            // This converts all numbers to doubles, which ignores the low-order bits of
            // NumberLongs > 2**53 and precise decimal numbers without double representations,
            // but that is ok since the hash will still be the same for equal numbers and is
            // still likely to be different for different numbers. (Note: this issue only
            // applies for decimals when they are outside of the valid double range. See
            // the above case.)
            // SERVER-16851
            const double dbl = elemToHash.numberDouble();
            if (std::isnan(dbl)) {
                boost::hash_combine(hash, std::numeric_limits<double>::quiet_NaN());
            } else {
                boost::hash_combine(hash, dbl);
            }
            break;
        }

        case mongo::jstOID:
            elemToHash.__oid().hash_combine(hash);
            break;

        case mongo::String: {
            if (stringComparator) {
                stringComparator->hash_combine(hash, elemToHash.valueStringData());
            } else {
                SimpleStringDataComparator::kInstance.hash_combine(hash,
                                                                   elemToHash.valueStringData());
            }
            break;
        }

        case mongo::Code:
        case mongo::Symbol:
            SimpleStringDataComparator::kInstance.hash_combine(hash, elemToHash.valueStringData());
            break;

        case mongo::Object:
        case mongo::Array:
            hashCombineBSONObj(hash,
                               elemToHash.embeddedObject(),
                               true,  // considerFieldName
                               stringComparator);
            break;

        case mongo::DBRef:
        case mongo::BinData:
            // All bytes of the value are required to be identical.
            SimpleStringDataComparator::kInstance.hash_combine(
                hash, StringData(elemToHash.value(), elemToHash.valuesize()));
            break;

        case mongo::RegEx:
            SimpleStringDataComparator::kInstance.hash_combine(hash, elemToHash.regex());
            SimpleStringDataComparator::kInstance.hash_combine(hash, elemToHash.regexFlags());
            break;

        case mongo::CodeWScope: {
            SimpleStringDataComparator::kInstance.hash_combine(
                hash, StringData(elemToHash.codeWScopeCode(), elemToHash.codeWScopeCodeLen()));
            hashCombineBSONObj(hash,
                               elemToHash.codeWScopeObject(),
                               true,  // considerFieldName
                               &SimpleStringDataComparator::kInstance);
            break;
        }
    }
}
开发者ID:DINKIN,项目名称:mongo,代码行数:101,代码来源:bson_comparator_interface_base.cpp

示例8: jsonString


//.........这里部分代码省略.........
                }

                s << "{ \"$binary\" : \"";
                char *start = ( char * )( elem.value() ) + sizeof( int ) + 1;
                base64::encode( s , start , len );
                s << "\", \"$type\" : \"" << hex;
                s.width( 2 );
                s.fill( '0' );
                s << type << dec;
                s << "\" }";
                break;
            }
            case mongo::Date:
                if ( format == Strict )
                    s << "{ \"$date\" : ";
                else
                    s << "ISODate(";
                if( pretty ) {
                    Date_t d = elem.date();

                    long long ms = (long long) d.millis;
                    boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
                    boost::posix_time::time_duration diff = boost::posix_time::millisec(ms);
                    boost::posix_time::ptime time = epoch + diff;
                    std::string timestr = miutil::isotimeString(time, true, true);
                    s << '"' << timestr << '"';

        /*            if( d == 0 ) s << '0';
                    else
                        //P s << '"' << elem.date().toString() << '"';
                        s << '"' << elem.date().millis << '"';*/

                }
                else
                    s << elem.date();
                if ( format == Strict )
                    s << " }";
                else
                    s << ")";
                break;
            case RegEx:
                if ( format == Strict ) {
                    s << "{ \"$regex\" : \"" << escape( elem.regex() );
                    s << "\", \"$options\" : \"" << elem.regexFlags() << "\" }";
                }
                else {
                    s << "/" << escape( elem.regex() , true ) << "/";
                    // FIXME Worry about alpha order?
                    for ( const char *f = elem.regexFlags(); *f; ++f ) {
                        switch ( *f ) {
                        case 'g':
                        case 'i':
                        case 'm':
                            s << *f;
                        default:
                            break;
                        }
                    }
                }
                break;

            case CodeWScope: {
                BSONObj scope = elem.codeWScopeObject();
                if ( ! scope.isEmpty() ) {
                    s << "{ \"$code\" : " << elem._asCode() << " , "
                      << " \"$scope\" : " << scope.jsonString() << " }";
                    break;
                }
            }

            case Code:
                s << elem._asCode();
                break;

            case Timestamp:
                if ( format == TenGen ) {
                    s << "Timestamp(" << ( elem.timestampTime() / 1000 ) << ", " << elem.timestampInc() << ")";
                }
                else {
                    s << "{ \"$timestamp\" : { \"t\" : " << ( elem.timestampTime() / 1000 ) << ", \"i\" : " << elem.timestampInc() << " } }";
                }
                break;

            case MinKey:
                s << "{ \"$minKey\" : 1 }";
                break;

            case MaxKey:
                s << "{ \"$maxKey\" : 1 }";
                break;

            default:
                StringBuilder ss;
                ss << "Cannot create a properly formatted JSON string with "
                   << "element: " << elem.toString() << " of type: " << elem.type();
                string message = ss.str();
                //massert( 10312 ,  message.c_str(), false );
            }
            return s.str();
        }
开发者ID:strogo,项目名称:robomongo,代码行数:101,代码来源:BsonUtils.cpp

示例9: compareElements


//.........这里部分代码省略.........
                    return compareLongs(l._numberLong(), r._numberLong());
                case NumberInt:
                    return compareLongs(l._numberLong(), r._numberInt());
                case NumberDouble:
                    return compareLongToDouble(l._numberLong(), r._numberDouble());
                case NumberDecimal:
                    return compareLongToDecimal(l._numberLong(), r._numberDecimal());
                default:
                    MONGO_UNREACHABLE;
            }
        }

        case BSONType::NumberDouble: {
            switch (r.type()) {
                case NumberDouble:
                    return compareDoubles(l._numberDouble(), r._numberDouble());
                case NumberInt:
                    return compareDoubles(l._numberDouble(), r._numberInt());
                case NumberLong:
                    return compareDoubleToLong(l._numberDouble(), r._numberLong());
                case NumberDecimal:
                    return compareDoubleToDecimal(l._numberDouble(), r._numberDecimal());
                default:
                    MONGO_UNREACHABLE;
            }
        }

        case BSONType::NumberDecimal: {
            switch (r.type()) {
                case NumberDecimal:
                    return compareDecimals(l._numberDecimal(), r._numberDecimal());
                case NumberInt:
                    return compareDecimalToInt(l._numberDecimal(), r._numberInt());
                case NumberLong:
                    return compareDecimalToLong(l._numberDecimal(), r._numberLong());
                case NumberDouble:
                    return compareDecimalToDouble(l._numberDecimal(), r._numberDouble());
                default:
                    MONGO_UNREACHABLE;
            }
        }

        case BSONType::jstOID:
            return memcmp(l.value(), r.value(), OID::kOIDSize);
        case BSONType::Code:
            return compareElementStringValues(l, r);
        case BSONType::Symbol:
        case BSONType::String: {
            if (comparator) {
                return comparator->compare(l.valueStringData(), r.valueStringData());
            } else {
                return compareElementStringValues(l, r);
            }
        }
        case BSONType::Object:
        case BSONType::Array: {
            return l.embeddedObject().woCompare(
                r.embeddedObject(),
                BSONObj(),
                rules | BSONElement::ComparisonRules::kConsiderFieldName,
                comparator);
        }
        case BSONType::DBRef: {
            int lsz = l.valuesize();
            int rsz = r.valuesize();
            if (lsz - rsz != 0)
                return lsz - rsz;
            return memcmp(l.value(), r.value(), lsz);
        }
        case BSONType::BinData: {
            int lsz = l.objsize();  // our bin data size in bytes, not including the subtype byte
            int rsz = r.objsize();
            if (lsz - rsz != 0)
                return lsz - rsz;
            return memcmp(l.value() + 4, r.value() + 4, lsz + 1 /*+1 for subtype byte*/);
        }
        case BSONType::RegEx: {
            int c = strcmp(l.regex(), r.regex());
            if (c)
                return c;
            return strcmp(l.regexFlags(), r.regexFlags());
        }
        case BSONType::CodeWScope: {
            int cmp = StringData(l.codeWScopeCode(), l.codeWScopeCodeLen() - 1)
                          .compare(StringData(r.codeWScopeCode(), r.codeWScopeCodeLen() - 1));
            if (cmp)
                return cmp;

            // When comparing the scope object, we should consider field names. Special string
            // comparison semantics do not apply to strings nested inside the CodeWScope scope
            // object, so we do not pass through the string comparator.
            return l.codeWScopeObject().woCompare(
                r.codeWScopeObject(),
                BSONObj(),
                rules | BSONElement::ComparisonRules::kConsiderFieldName);
        }
    }

    MONGO_UNREACHABLE;
}
开发者ID:EvgeniyPatlan,项目名称:percona-server-mongodb,代码行数:101,代码来源:bsonelement.cpp

示例10: newFunction

    Handle<v8::Value> mongoToV8Element( const BSONElement &f ) {
        Local< v8::ObjectTemplate > internalFieldObjects = v8::ObjectTemplate::New();
        internalFieldObjects->SetInternalFieldCount( 1 );

        switch ( f.type() ){

        case mongo::Code:
            return newFunction( f.valuestr() );
                
        case CodeWScope:
            if ( f.codeWScopeObject().isEmpty() )
                log() << "warning: CodeWScope doesn't transfer to db.eval" << endl;
            return newFunction( f.codeWScopeCode() );
                
        case mongo::String: 
            return v8::String::New( f.valuestr() );
            
        case mongo::jstOID:
            return newId( f.__oid() );
            
        case mongo::NumberDouble:
        case mongo::NumberInt:
            return v8::Number::New( f.number() );
            
        case mongo::Array:
        case mongo::Object:
            return mongoToV8( f.embeddedObject() , f.type() == mongo::Array );
            
        case mongo::Date:
            return v8::Date::New( f.date() );
            
        case mongo::Bool:
            return v8::Boolean::New( f.boolean() );

        case mongo::EOO:            
        case mongo::jstNULL:
        case mongo::Undefined: // duplicate sm behavior
            return v8::Null();
            
        case mongo::RegEx: {
            v8::Function * regex = getNamedCons( "RegExp" );
            
            v8::Handle<v8::Value> argv[2];
            argv[0] = v8::String::New( f.regex() );
            argv[1] = v8::String::New( f.regexFlags() );
            
            return regex->NewInstance( 2 , argv );
            break;
        }
            
        case mongo::BinData: {
            int len;
            const char *data = f.binData( len );
            
            v8::Function* binData = getNamedCons( "BinData" );
            v8::Handle<v8::Value> argv[3];
            argv[0] = v8::Number::New( len );
            argv[1] = v8::Number::New( f.binDataType() );
            argv[2] = v8::String::New( data, len );
            return binData->NewInstance( 3, argv );
        };
            
        case mongo::Timestamp: {
            Local<v8::Object> sub = internalFieldObjects->NewInstance();
            
            sub->Set( v8::String::New( "time" ) , v8::Date::New( f.timestampTime() ) );
            sub->Set( v8::String::New( "i" ) , v8::Number::New( f.timestampInc() ) );
            sub->SetInternalField( 0, v8::Uint32::New( f.type() ) );

            return sub;
        }
                
        case mongo::NumberLong: {
            Local<v8::Object> sub = internalFieldObjects->NewInstance();
            unsigned long long val = f.numberLong();
            v8::Function* numberLong = getNamedCons( "NumberLong" );
            v8::Handle<v8::Value> argv[2];
            argv[0] = v8::Integer::New( val >> 32 );
            argv[1] = v8::Integer::New( (unsigned long)(val & 0x00000000ffffffff) );
            return numberLong->NewInstance( 2, argv );
        }
            
        case mongo::MinKey: {
            Local<v8::Object> sub = internalFieldObjects->NewInstance();
            sub->Set( v8::String::New( "$MinKey" ), v8::Boolean::New( true ) );
            sub->SetInternalField( 0, v8::Uint32::New( f.type() ) );
            return sub;
        }
            
        case mongo::MaxKey: {
            Local<v8::Object> sub = internalFieldObjects->NewInstance();
            sub->Set( v8::String::New( "$MaxKey" ), v8::Boolean::New( true ) );
            sub->SetInternalField( 0, v8::Uint32::New( f.type() ) );
            return sub;
        }
                
        case mongo::DBRef: {
            v8::Function* dbPointer = getNamedCons( "DBPointer" );
            v8::Handle<v8::Value> argv[2];
            argv[0] = v8::String::New( f.dbrefNS() );
//.........这里部分代码省略.........
开发者ID:IlyaM,项目名称:mongo,代码行数:101,代码来源:v8_wrapper.cpp

示例11: toval

    jsval toval( const BSONElement& e ) {

        switch( e.type() ) {
        case EOO:
        case jstNULL:
        case Undefined:
            return JSVAL_NULL;
        case NumberDouble:
        case NumberInt:
            return toval( e.number() );
        case Symbol: // TODO: should we make a special class for this
        case String:
            return toval( e.valuestr() );
        case Bool:
            return e.boolean() ? JSVAL_TRUE : JSVAL_FALSE;
        case Object: {
            BSONObj embed = e.embeddedObject().getOwned();
            return toval( &embed );
        }
        case Array: {

            BSONObj embed = e.embeddedObject().getOwned();

            if ( embed.isEmpty() ) {
                return OBJECT_TO_JSVAL( JS_NewArrayObject( _context , 0 , 0 ) );
            }

            int n = embed.nFields();

            JSObject * array = JS_NewArrayObject( _context , n , 0 );
            assert( array );

            jsval myarray = OBJECT_TO_JSVAL( array );

            for ( int i=0; i<n; i++ ) {
                jsval v = toval( embed[i] );
                assert( JS_SetElement( _context , array , i , &v ) );
            }

            return myarray;
        }
        case jstOID: {
            OID oid = e.__oid();
            JSObject * o = JS_NewObject( _context , &object_id_class , 0 , 0 );
            setProperty( o , "str" , toval( oid.str().c_str() ) );
            return OBJECT_TO_JSVAL( o );
        }
        case RegEx: {
            const char * flags = e.regexFlags();
            uintN flagNumber = 0;
            while ( *flags ) {
                switch ( *flags ) {
                case 'g':
                    flagNumber |= JSREG_GLOB;
                    break;
                case 'i':
                    flagNumber |= JSREG_FOLD;
                    break;
                case 'm':
                    flagNumber |= JSREG_MULTILINE;
                    break;
                //case 'y': flagNumber |= JSREG_STICKY; break;

                default:
                    log() << "warning: unknown regex flag:" << *flags << endl;
                }
                flags++;
            }

            JSObject * r = JS_NewRegExpObject( _context , (char*)e.regex() , strlen( e.regex() ) , flagNumber );
            assert( r );
            return OBJECT_TO_JSVAL( r );
        }
        case Code: {
            JSFunction * func = compileFunction( e.valuestr() );
            return OBJECT_TO_JSVAL( JS_GetFunctionObject( func ) );
        }
        case CodeWScope: {
            JSFunction * func = compileFunction( e.codeWScopeCode() );

            BSONObj extraScope = e.codeWScopeObject();
            if ( ! extraScope.isEmpty() ) {
                log() << "warning: CodeWScope doesn't transfer to db.eval" << endl;
            }

            return OBJECT_TO_JSVAL( JS_GetFunctionObject( func ) );
        }
        case Date:
            return OBJECT_TO_JSVAL( js_NewDateObjectMsec( _context , (jsdouble) e.date().millis ) );

        case MinKey:
            return OBJECT_TO_JSVAL( JS_NewObject( _context , &minkey_class , 0 , 0 ) );

        case MaxKey:
            return OBJECT_TO_JSVAL( JS_NewObject( _context , &maxkey_class , 0 , 0 ) );

        case Timestamp: {
            JSObject * o = JS_NewObject( _context , &timestamp_class , 0 , 0 );
            setProperty( o , "t" , toval( (double)(e.timestampTime()) ) );
            setProperty( o , "i" , toval( (double)(e.timestampInc()) ) );
//.........这里部分代码省略.........
开发者ID:xrogaan,项目名称:mongo,代码行数:101,代码来源:engine_spidermonkey.cpp


注:本文中的BSONElement::codeWScopeObject方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。