github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/streamer.go (about)

     1  package jzon
     2  
     3  import (
     4  	"io"
     5  )
     6  
     7  // Streamer is a chained class for encoding object to json
     8  type Streamer struct {
     9  	cfg *EncoderConfig
    10  
    11  	writer io.Writer
    12  	buffer []byte
    13  
    14  	Error error
    15  	poped bool
    16  
    17  	// TODO: 1. type of context?
    18  	// TODO: 2. should context be reset as well?
    19  	Context interface{} // custom stream context
    20  
    21  	// runtime
    22  	escapeHTML bool
    23  	safeSet    []string
    24  	// prefix  string
    25  	// indent  string
    26  }
    27  
    28  // NewStreamer returns a new streamer
    29  func NewStreamer() *Streamer {
    30  	return DefaultEncoderConfig.NewStreamer()
    31  }
    32  
    33  // Release the streamer, the streamer should not be used after call
    34  func (s *Streamer) Release() {
    35  	s.cfg.returnStreamer(s)
    36  }
    37  
    38  func (s *Streamer) reset() {
    39  	s.writer = nil
    40  	s.Error = nil
    41  	s.poped = false
    42  	s.buffer = s.buffer[:0]
    43  	s.Context = nil
    44  }
    45  
    46  // Reset resets the streamer with a new writer
    47  func (s *Streamer) Reset(w io.Writer) {
    48  	s.reset()
    49  	s.writer = w
    50  }
    51  
    52  // EscapeHTML set if the string should be html-escaped
    53  func (s *Streamer) EscapeHTML(on bool) {
    54  	s.escapeHTML = on
    55  	if on {
    56  		s.safeSet = htmlSafeSet[:]
    57  	} else {
    58  		s.safeSet = safeSet[:]
    59  	}
    60  }
    61  
    62  // func (s *Streamer) SetIndent(prefix, indent string) {
    63  // 	s.prefix = prefix
    64  // 	s.indent = indent
    65  // }
    66  
    67  // Flush flushes from buffer to the writer
    68  func (s *Streamer) Flush() error {
    69  	if s.Error != nil {
    70  		return s.Error
    71  	}
    72  	if s.writer == nil {
    73  		return ErrNoAttachedWriter
    74  	}
    75  	l := len(s.buffer)
    76  	// see comment of io.Writer
    77  	n, err := s.writer.Write(s.buffer)
    78  	if n < l {
    79  		copy(s.buffer, s.buffer[n:])
    80  		s.buffer = s.buffer[:l-n]
    81  	} else {
    82  		s.buffer = s.buffer[:0]
    83  	}
    84  	return err
    85  }
    86  
    87  func (s *Streamer) onVal() {
    88  	if s.poped {
    89  		s.buffer = append(s.buffer, ',')
    90  	} else {
    91  		s.poped = true
    92  	}
    93  }
    94  
    95  // RawString writes a raw object (in string)
    96  func (s *Streamer) RawString(raw string) *Streamer {
    97  	if s.Error != nil {
    98  		return s
    99  	}
   100  	s.onVal()
   101  	s.buffer = append(s.buffer, raw...)
   102  	return s
   103  }
   104  
   105  // Raw writes a raw object (in byte slice)
   106  func (s *Streamer) Raw(raw []byte) *Streamer {
   107  	if s.Error != nil {
   108  		return s
   109  	}
   110  	s.onVal()
   111  	s.buffer = append(s.buffer, raw...)
   112  	return s
   113  }
   114  
   115  func (s *Streamer) null() {
   116  	s.onVal()
   117  	s.buffer = append(s.buffer, 'n', 'u', 'l', 'l')
   118  }
   119  
   120  // Null writes a `null`
   121  func (s *Streamer) Null() *Streamer {
   122  	if s.Error != nil {
   123  		return s
   124  	}
   125  	s.null()
   126  	return s
   127  }
   128  
   129  // True writes a `true`
   130  func (s *Streamer) True() *Streamer {
   131  	if s.Error != nil {
   132  		return s
   133  	}
   134  	s.onVal()
   135  	s.buffer = append(s.buffer, 't', 'r', 'u', 'e')
   136  	return s
   137  }
   138  
   139  // False writes a `false`
   140  func (s *Streamer) False() *Streamer {
   141  	if s.Error != nil {
   142  		return s
   143  	}
   144  	s.onVal()
   145  	s.buffer = append(s.buffer, 'f', 'a', 'l', 's', 'e')
   146  	return s
   147  }
   148  
   149  // Bool writes a boolean value
   150  func (s *Streamer) Bool(b bool) *Streamer {
   151  	if b {
   152  		return s.True()
   153  	}
   154  	return s.False()
   155  }
   156  
   157  // ObjectStart starts to write an object
   158  func (s *Streamer) ObjectStart() *Streamer {
   159  	if s.Error != nil {
   160  		return s
   161  	}
   162  	s.onVal()
   163  	s.buffer = append(s.buffer, '{')
   164  	s.poped = false
   165  	return s
   166  }
   167  
   168  // Field writes an object field
   169  func (s *Streamer) Field(field string) *Streamer {
   170  	if s.Error != nil {
   171  		return s
   172  	}
   173  	s.onVal()
   174  	s.buffer = encodeString(s.buffer, field, s.safeSet)
   175  	s.buffer = append(s.buffer, ':')
   176  	s.poped = false
   177  	return s
   178  }
   179  
   180  // RawField writes an object field (in raw byte slice)
   181  func (s *Streamer) RawField(b []byte) *Streamer {
   182  	if s.Error != nil {
   183  		return s
   184  	}
   185  	s.onVal()
   186  	s.buffer = append(s.buffer, b...)
   187  	s.buffer = append(s.buffer, ':')
   188  	s.poped = false
   189  	return s
   190  }
   191  
   192  // ObjectEnd ends the object writing
   193  func (s *Streamer) ObjectEnd() *Streamer {
   194  	if s.Error != nil {
   195  		return s
   196  	}
   197  	s.buffer = append(s.buffer, '}')
   198  	s.poped = true
   199  	return s
   200  }
   201  
   202  // ArrayStart starts to write an array
   203  func (s *Streamer) ArrayStart() *Streamer {
   204  	if s.Error != nil {
   205  		return s
   206  	}
   207  	s.onVal()
   208  	s.buffer = append(s.buffer, '[')
   209  	s.poped = false
   210  	return s
   211  }
   212  
   213  // ArrayEnd ends the array writing
   214  func (s *Streamer) ArrayEnd() *Streamer {
   215  	if s.Error != nil {
   216  		return s
   217  	}
   218  	s.buffer = append(s.buffer, ']')
   219  	s.poped = true
   220  	return s
   221  }