<commit_before>/*
 * Copyright 1999-2101 Alibaba Group.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.fastjson.serializer;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import com.alibaba.fastjson.JSONAware;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONStreamAware;
import com.alibaba.fastjson.util.ServiceLoader;

/**
 * @author wenshao<<EMAIL>>
 */
public class JSONSerializer {

    private final SerializeConfig                  config;

    private final SerializeWriter                  out;

    private List<PropertyFilter>                   propertyFilters = null;
    private List<ValueFilter>                      valueFilters    = null;
    private List<NameFilter>                       nameFilters     = null;

    private int                                    indentCount     = 0;
    private String                                 indent          = "\t";

    private IdentityHashMap<Object, SerialContext> references      = null;
    private SerialContext                          context;

    public JSONSerializer(){
        this(new SerializeWriter(), SerializeConfig.getGlobalInstance());
    }

    public JSONSerializer(SerializeWriter out){
        this(out, SerializeConfig.getGlobalInstance());
    }

    public JSONSerializer(SerializeConfig config){
        this(new SerializeWriter(), config);
    }

    @Deprecated
    public JSONSerializer(JSONSerializerMap mapping){
        this(new SerializeWriter(), mapping);
    }

    public JSONSerializer(SerializeWriter out, SerializeConfig config){
        this.out = out;
        this.config = config;
    }

    public SerialContext getContext() {
        return context;
    }

    public void setContext(SerialContext context) {
        this.context = context;
    }

    public void setContext(SerialContext parent, Object object, Object fieldName) {
        if (isEnabled(SerializerFeature.DisableCircularReferenceDetect)) {
            return;
        }

        this.context = new SerialContext(parent, object, fieldName);
        if (references == null) {
            references = new IdentityHashMap<Object, SerialContext>();
        }
        this.references.put(object, context);
    }

    public void setContext(SerialContext parent, Object object) {
        if (isEnabled(SerializerFeature.DisableCircularReferenceDetect)) {
            return;
        }

        this.context = new SerialContext(parent, object, null);
        if (references == null) {
            references = new IdentityHashMap<Object, SerialContext>();
        }
        this.references.put(object, context);
    }

    public Collection<SerialContext> getReferences() {
        if (references == null) {
            references = new IdentityHashMap<Object, SerialContext>();
        }
        
        return references.values();
    }

    public boolean containsReference(Object value) {
        if (isEnabled(SerializerFeature.DisableCircularReferenceDetect)) {
            return false;
        }
        
        if (references == null) {
            return false;
        }
       
        return references.containsKey(value);
    }

    public void writeReference(Object object) {
        if (isEnabled(SerializerFeature.DisableCircularReferenceDetect)) {
            return;
        }

        SerialContext context = this.getContext();
        Object current = context.getObject();

        if (object == current) {
            out.write("{\"$ref\":\"@\"}");
            return;
        }

        SerialContext parentContext = context.getParent();

        if (parentContext != null) {
            if (object == parentContext.getObject()) {
                out.write("{\"$ref\":\"..\"}");
                return;
            }
        }

        SerialContext rootContext = context;
        for (;;) {
            if (rootContext.getParent() == null) {
                break;
            }
            rootContext = rootContext.getParent();
        }

        if (object == rootContext.getObject()) {
            out.write("{\"$ref\":\"$\"}");
            return;
        }

        SerialContext refContext = null;
        for (SerialContext item : this.getReferences()) {
            if (item.getObject() == object) {
                refContext = item;
                break;
            }
        }

        String path = refContext.getPath();

        out.write("{\"$ref\":\"");
        out.write(path);
        out.write("\"}");
        return;
    }

    public List<ValueFilter> getValueFilters() {
        if (valueFilters == null) {
            valueFilters = new ArrayList<ValueFilter>();
        }

        return valueFilters;
    }

    public List<ValueFilter> getValueFiltersDirect() {
        return valueFilters;
    }

    public int getIndentCount() {
        return indentCount;
    }
<commit_msg>解决循环引用性能<commit_after>/*
 * Copyright 1999-2101 Alibaba Group.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.fastjson.serializer;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import com.alibaba.fastjson.JSONAware;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONStreamAware;
import com.alibaba.fastjson.util.ServiceLoader;

/**
 * @author wenshao<<EMAIL>>
 */
public class JSONSerializer {

    private final SerializeConfig                  config;

    private final SerializeWriter                  out;

    private List<PropertyFilter>                   propertyFilters = null;
    private List<ValueFilter>                      valueFilters    = null;
    private List<NameFilter>                       nameFilters     = null;

    private int                                    indentCount     = 0;
    private String                                 indent          = "\t";

    private IdentityHashMap<Object, SerialContext> references      = null;
    private SerialContext                          context;

    public JSONSerializer(){
        this(new SerializeWriter(), SerializeConfig.getGlobalInstance());
    }

    public JSONSerializer(SerializeWriter out){
        this(out, SerializeConfig.getGlobalInstance());
    }

    public JSONSerializer(SerializeConfig config){
        this(new SerializeWriter(), config);
    }

    @Deprecated
    public JSONSerializer(JSONSerializerMap mapping){
        this(new SerializeWriter(), mapping);
    }

    public JSONSerializer(SerializeWriter out, SerializeConfig config){
        this.out = out;
        this.config = config;
    }

    public SerialContext getContext() {
        return context;
    }

    public void setContext(SerialContext context) {
        this.context = context;
    }

    public void setContext(SerialContext parent, Object object, Object fieldName) {
        if (isEnabled(SerializerFeature.DisableCircularReferenceDetect)) {
            return;
        }

        this.context = new SerialContext(parent, object, fieldName);
        if (references == null) {
            references = new IdentityHashMap<Object, SerialContext>();
        }
        this.references.put(object, context);
    }

    public void setContext(SerialContext parent, Object object) {
        if (isEnabled(SerializerFeature.DisableCircularReferenceDetect)) {
            return;
        }

        this.context = new SerialContext(parent, object, null);
        if (references == null) {
            references = new IdentityHashMap<Object, SerialContext>();
        }
        this.references.put(object, context);
    }

    public Collection<SerialContext> getReferences() {
        if (references == null) {
            references = new IdentityHashMap<Object, SerialContext>();
        }
        
        return references.values();
    }
    
    public SerialContext getSerialContext(Object object) {
        if (references == null) {
            return null;
        }
        
        return references.get(object);
    }

    public boolean containsReference(Object value) {
        if (isEnabled(SerializerFeature.DisableCircularReferenceDetect)) {
            return false;
        }
        
        if (references == null) {
            return false;
        }
       
        return references.containsKey(value);
    }

    public void writeReference(Object object) {
        if (isEnabled(SerializerFeature.DisableCircularReferenceDetect)) {
            return;
        }

        SerialContext context = this.getContext();
        Object current = context.getObject();

        if (object == current) {
            out.write("{\"$ref\":\"@\"}");
            return;
        }

        SerialContext parentContext = context.getParent();

        if (parentContext != null) {
            if (object == parentContext.getObject()) {
                out.write("{\"$ref\":\"..\"}");
                return;
            }
        }

        SerialContext rootContext = context;
        for (;;) {
            if (rootContext.getParent() == null) {
                break;
            }
            rootContext = rootContext.getParent();
        }

        if (object == rootContext.getObject()) {
            out.write("{\"$ref\":\"$\"}");
            return;
        }

        SerialContext refContext = this.getSerialContext(object);

        String path = refContext.getPath();

        out.write("{\"$ref\":\"");
        out.write(path);
        out.write("\"}");
        return;
    }

    public List<ValueFilter> getValueFilters() {
        if (valueFilters == null) {
            valueFilters = new ArrayList<ValueFilter>();
        }

        return valueFilters;
    }

    public List<ValueFilter> getValueFiltersDirect() {
        return valueFilters;
    }

    public int getIndentCount() {
        return indentCount;
    }

{'fraction_non_alphanumeric': 0.09956748168417336, 'fraction_numerical': 0.0022949951452025776, 'mean_word_length': 2.1595092024539877, 'pattern_counts': {'":': 8, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '417869', 'n_tokens_mistral': 2924, 'n_tokens_neox': 2835, 'n_words': 723}