Package org.jruby.truffle.nodes.core

Source Code of org.jruby.truffle.nodes.core.EncodingConverterNodes$SearchConvPathNode

/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.Encoding;
import org.jcodings.EncodingDB;
import org.jcodings.specific.UTF8Encoding;
import org.jcodings.transcode.EConv;
import org.jcodings.transcode.Transcoder;
import org.jcodings.transcode.TranscoderDB;
import org.jcodings.util.CaseInsensitiveBytesHash;
import org.jcodings.util.Hash;
import org.jruby.Ruby;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.encoding.EncodingService;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.*;
import org.jruby.util.ByteList;
import org.jruby.util.io.EncodingUtils;

@CoreClass(name = "Encoding::Converter")
public abstract class EncodingConverterNodes {

    @CoreMethod(names = "convpath")
    public abstract static class ConvPathNode extends CoreMethodNode {

        public ConvPathNode(RubyContext context, SourceSection sourceSection) {
            super(context, sourceSection);
        }

        public ConvPathNode(ConvPathNode prev) {
            super(prev);
        }

        @Specialization
        public RubyArray convpath(RubyEncodingConverter converter) {
            notDesignedForCompilation();

            // Adapated from RubyConverter - see attribution there

            Ruby runtime = getContext().getRuntime();

            EConv ec = converter.getEConv();

            Object[] result = new Object[ec.numTranscoders];
            int r = 0;

            for (int i = 0; i < ec.numTranscoders; i++) {
                Transcoder tr = ec.elements[i].transcoding.transcoder;
                Object v;
                if (EncodingUtils.DECORATOR_P(tr.getSource(), tr.getDestination())) {
                    v = new RubyString(getContext().getCoreLibrary().getStringClass(), new ByteList(tr.getDestination()));
                } else {
                    Encoding source = runtime.getEncodingService().findEncodingOrAliasEntry(tr.getSource()).getEncoding();
                    Encoding destination = runtime.getEncodingService().findEncodingOrAliasEntry(tr.getDestination()).getEncoding();

                    v = new RubyArray(getContext().getCoreLibrary().getArrayClass(),
                            new Object[]{
                                RubyEncoding.getEncoding(getContext(), source),
                                RubyEncoding.getEncoding(getContext(), destination)
                            }, 2);
                }
                result[r++] = v;
            }

            return new RubyArray(getContext().getCoreLibrary().getArrayClass(), result, result.length);
        }

    }

    @CoreMethod(names = "initialize", required = 2)
    public abstract static class InitializeNode extends CoreMethodNode {

        public InitializeNode(RubyContext context, SourceSection sourceSection) {
            super(context, sourceSection);
        }

        public InitializeNode(InitializeNode prev) {
            super(prev);
        }

        @Specialization
        public RubyNilClass initialize(RubyEncodingConverter self, RubyString source, RubyString destination) {
            notDesignedForCompilation();

            // Adapted from RubyConverter - see attribution there

            Ruby runtime = getContext().getRuntime();
            Encoding[] encs = {null, null};
            byte[][] encNames = {null, null};
            int[] ecflags = {0};
            IRubyObject[] ecopts = {runtime.getNil()};

            EncodingUtils.econvArgs(runtime.getCurrentContext(), new IRubyObject[]{getContext().toJRuby(source), getContext().toJRuby(destination)}, encNames, encs, ecflags, ecopts);
            EConv econv = EncodingUtils.econvOpenOpts(runtime.getCurrentContext(), encNames[0], encNames[1], ecflags[0], ecopts[0]);

            if (econv == null) {
                throw new UnsupportedOperationException();
            }

            self.setEConv(econv);

            return getContext().getCoreLibrary().getNilObject();
        }

    }

    @CoreMethod(names = "search_convpath", isModuleFunction = true, needsSelf = false, required = 2)
    public abstract static class SearchConvPathNode extends CoreMethodNode {

        public SearchConvPathNode(RubyContext context, SourceSection sourceSection) {
            super(context, sourceSection);
        }

        public SearchConvPathNode(SearchConvPathNode prev) {
            super(prev);
        }

        @Specialization
        public RubyArray searchConvpath(RubyString source, RubyString destination) {
            notDesignedForCompilation();

            // Adapted from RubyConverter - see attribution there

            final Ruby runtime = getContext().getRuntime();
            final RubyNilClass nil = getContext().getCoreLibrary().getNilObject();
            ThreadContext context = runtime.getCurrentContext();
            final byte[][] encNames = {null, null};
            final Encoding[] encs = {null, null};
            final int[] ecflags_p = {0};
            final IRubyObject[] ecopts_p = {context.nil};
            final Object[] convpath = {getContext().getCoreLibrary().getNilObject()};

            EncodingUtils.econvArgs(context, new IRubyObject[]{getContext().toJRuby(source), getContext().toJRuby(destination)}, encNames, encs, ecflags_p, ecopts_p);

            TranscoderDB.searchPath(encNames[0], encNames[1], new TranscoderDB.SearchPathCallback() {
                EncodingService es = runtime.getEncodingService();

                public void call(byte[] source, byte[] destination, int depth) {
                    Object v;

                    if (convpath[0] == nil) {
                        convpath[0] = new RubyArray(getContext().getCoreLibrary().getArrayClass(), null, 0);
                    }

                    if (EncodingUtils.DECORATOR_P(encNames[0], encNames[1])) {
                        v = new RubyString(getContext().getCoreLibrary().getStringClass(), new ByteList(encNames[2]));
                    } else {
                        Encoding sourceEncoding = runtime.getEncodingService().findEncodingOrAliasEntry(source).getEncoding();
                        Encoding destinationEncoding = runtime.getEncodingService().findEncodingOrAliasEntry(destination).getEncoding();

                        v = new RubyArray(getContext().getCoreLibrary().getArrayClass(),
                                new Object[]{
                                        RubyEncoding.getEncoding(getContext(), destinationEncoding),
                                        RubyEncoding.getEncoding(getContext(), sourceEncoding)
                                }, 2);
                    }

                    ((RubyArray) convpath[0]).slowPush(v); // depth?
                }
            });

            if (convpath[0] == nil) {
                throw new UnsupportedOperationException();
            }

            //if (EncodingUtils.decorateConvpath(context, convpath[0], ecflags_p[0]) == -1) {
            //    throw EncodingUtils.econvOpenExc(context, encNames[0], encNames[1], ecflags_p[0]);
            //}

            return (RubyArray) convpath[0];
        }

    }

}
TOP

Related Classes of org.jruby.truffle.nodes.core.EncodingConverterNodes$SearchConvPathNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.