pfs::error_code ubjson_ostream<OStreamType, JsonType>::write_array (json_type const & j) { _os << UBJSON_CHAR_ARRAY_BEGIN; bool use_count_optimization = ((_flags & count_optimized) && !j.empty()); bool is_special_case = false; // If a type is specified, a count must also be specified. // A type cannot be specified by itself. bool use_type_optimization = ((_flags & type_optimized) && use_count_optimization); // Additional checks for type optimization if (use_type_optimization) { // This call is safe. Array is not empty as checked before int8_t first_prefix = prefix(*j.cbegin()); use_type_optimization = pfs::all_of(j.cbegin() , j.cend() , compare_prefix(first_prefix)); if (use_type_optimization) { _os << UBJSON_CHAR_TYPE; _os << first_prefix; // Check special cases if (first_prefix == UBJSON_CHAR_NOOP || first_prefix == UBJSON_CHAR_NULL || first_prefix == UBJSON_CHAR_TRUE || first_prefix == UBJSON_CHAR_FALSE) { is_special_case = true; } } } if (use_count_optimization) { _os << UBJSON_CHAR_SIZE; write_integer(static_cast<typename json_type::integer_type>(j.size()), true); } // Ignore special cases: strongly-typed arrays of null, no-op and boolean values if (! is_special_case) { typename json_type::const_iterator first = j.cbegin(); typename json_type::const_iterator last = j.cend(); for (; first != last; ++first) write_json(*first, !use_type_optimization); } // If a count is specified the container must not specify an end-marker. if (!use_count_optimization) _os << UBJSON_CHAR_ARRAY_END; return pfs::error_code(); }
pfs::error_code ubjson_ostream<OStreamType, JsonType>::write_object (json_type const & j) { _os << UBJSON_CHAR_OBJECT_BEGIN; bool use_count_optimization = ((_flags & count_optimized) && !j.empty()); bool is_special_case = false; // If a type is specified, a count must also be specified. // A type cannot be specified by itself. bool use_type_optimization = ((_flags & type_optimized) && use_count_optimization); // Additional checks for type optimization if (use_type_optimization) { // This call is safe. Array is not empty as checked before int8_t first_prefix = prefix(*j.cbegin()); use_type_optimization = pfs::all_of(j.cbegin(), j.cend(), compare_prefix(first_prefix)); if (use_type_optimization) { _os << UBJSON_CHAR_TYPE; _os << first_prefix; // Check special cases if (first_prefix == UBJSON_CHAR_NOOP || first_prefix == UBJSON_CHAR_NULL || first_prefix == UBJSON_CHAR_TRUE || first_prefix == UBJSON_CHAR_FALSE) { is_special_case = true; } } } if (use_count_optimization) { _os << UBJSON_CHAR_SIZE; write_integer(static_cast<typename json_type::integer_type>(j.size()), true); } typename json_type::const_iterator first = j.cbegin(); typename json_type::const_iterator last = j.cend(); if (is_special_case) { for (; first != last; ++first) { // The [S] (string) marker is omitted from each of the names in the // name/value pairings inside the object. The JSON specification does // not allow non-string name values, therefore the [S] marker // is redundant and must not be used. write_string(first.key(), false); } } else { for (; first != last; ++first) { write_string(first.key(), false); write_json(*first, !use_type_optimization); } } // If a count is specified the container must not specify an end-marker. if (!use_count_optimization) _os << UBJSON_CHAR_OBJECT_END; return pfs::error_code(); }
char* wordwrap(char* inbuf, int len, int oldlen, BOOL handle_quotes) { int l; int crcount=0; long i,k,t; int ocol=1; int icol=1; char* outbuf; char* outp; char* linebuf; char* prefix=NULL; int prefix_len=0; int prefix_bytes=0; int quote_count=0; int old_prefix_bytes=0; int outbuf_size=0; int inbuf_len=strlen(inbuf); outbuf_size=inbuf_len*3+1; if((outbuf=(char*)malloc(outbuf_size))==NULL) return NULL; outp=outbuf; if((linebuf=(char*)malloc(inbuf_len+2))==NULL) { /* room for ^A codes */ free(outbuf); return NULL; } if(handle_quotes) { if((prefix=(char *)malloc(inbuf_len+1))==NULL) { /* room for ^A codes */ free(linebuf); free(outbuf); return NULL; } prefix[0]=0; } outbuf[0]=0; /* Get prefix from the first line (ouch) */ l=0; i=0; if(handle_quotes && (quote_count=get_prefix(inbuf, &prefix_bytes, &prefix_len, len*2+2))!=0) { i+=prefix_bytes; if(prefix_len>len/3*2) { /* This prefix is insane (more than 2/3rds of the new width) hack it down to size */ /* Since we're hacking it, we will always end up with a hardcr on this line. */ /* ToDo: Something prettier would be nice. */ sprintf(prefix," %d> ",quote_count); prefix_len=strlen(prefix); prefix_bytes=strlen(prefix); } else { memcpy(prefix,inbuf,prefix_bytes); /* Terminate prefix */ prefix[prefix_bytes]=0; } memcpy(linebuf,prefix,prefix_bytes); l=prefix_bytes; ocol=prefix_len+1; icol=prefix_len+1; old_prefix_bytes=prefix_bytes; } for(; inbuf[i]; i++) { if(oldlen == 0) icol=-256; if(l>=len*2+2) { l-=4; linebuf[l]=0; // lprintf(LOG_CRIT, "Word wrap line buffer exceeded... munging line %s",linebuf); } switch(inbuf[i]) { case '\r': crcount++; break; case '\n': if(handle_quotes && (quote_count=get_prefix(inbuf+i+1, &prefix_bytes, &prefix_len, len*2+2))!=0) { /* Move the input pointer offset to the last char of the prefix */ i+=prefix_bytes; } if(!inbuf[i+1]) { /* EOF */ linebuf[l++]='\r'; linebuf[l++]='\n'; outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size); l=0; ocol=1; } /* If there's a new prefix, it is a hardcr */ else if(compare_prefix(prefix, old_prefix_bytes, inbuf+i+1-prefix_bytes, prefix_bytes)!=0) { if(prefix_len>len/3*2) { /* This prefix is insane (more than 2/3rds of the new width) hack it down to size */ /* Since we're hacking it, we will always end up with a hardcr on this line. */ /* ToDo: Something prettier would be nice. */ sprintf(prefix," %d> ",quote_count); prefix_len=strlen(prefix); prefix_bytes=strlen(prefix); } else { memcpy(prefix,inbuf+i+1-prefix_bytes,prefix_bytes); /* Terminate prefix */ prefix[prefix_bytes]=0; } linebuf[l++]='\r'; linebuf[l++]='\n'; outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size); memcpy(linebuf,prefix,prefix_bytes); l=prefix_bytes; ocol=prefix_len+1; old_prefix_bytes=prefix_bytes; } else if(isspace((unsigned char)inbuf[i+1])) { /* Next line starts with whitespace. This is a "hard" CR. */ linebuf[l++]='\r'; linebuf[l++]='\n'; outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size); l=prefix_bytes; ocol=prefix_len+1; } else { if(icol < oldlen) { /* If this line is overly long, It's impossible for the next word to fit */ /* k will equal the length of the first word on the next line */ for(k=0; inbuf[i+1+k] && (!isspace((unsigned char)inbuf[i+1+k])); k++); if(icol+k+1 < oldlen) { /* The next word would have fit but isn't here. Must be a hard CR */ linebuf[l++]='\r'; linebuf[l++]='\n'; outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size); if(prefix) memcpy(linebuf,prefix,prefix_bytes); l=prefix_bytes; ocol=prefix_len+1; } else { /* Not a hard CR... add space if needed */ if(l<1 || !isspace((unsigned char)linebuf[l-1])) { linebuf[l++]=' '; ocol++; } } } else { /* Not a hard CR... add space if needed */ if(l<1 || !isspace((unsigned char)linebuf[l-1])) { linebuf[l++]=' '; ocol++; } } } icol=prefix_len+1; break; case '\x1f': /* Delete... meaningless... strip. */ break; case '\b': /* Backspace... handle if possible, but don't go crazy. */ if(l>0) { if(l>1 && linebuf[l-2]=='\x01') { if(linebuf[l-1]=='\x01') { ocol--; icol--; } l-=2; } else { l--; ocol--; icol--; } } break; case '\t': /* TAB */ linebuf[l++]=inbuf[i]; /* Can't ever wrap on whitespace remember. */ icol++; ocol++; while(ocol%8) ocol++; while(icol%8) icol++; break; case '\x01': /* CTRL-A */ linebuf[l++]=inbuf[i++]; if(inbuf[i]!='\x01') { linebuf[l++]=inbuf[i]; break; } default: linebuf[l++]=inbuf[i]; ocol++; icol++; if(ocol>len && !isspace((unsigned char)inbuf[i])) { /* Need to wrap here */ /* Find the start of the last word */ k=l; /* Original next char */ l--; /* Move back to the last char */ while((!isspace((unsigned char)linebuf[l])) && l>0) /* Move back to the last non-space char */ l--; if(l==0) { /* Couldn't wrap... must chop. */ l=k; while(l>1 && linebuf[l-2]=='\x01' && linebuf[l-1]!='\x01') l-=2; if(l>0 && linebuf[l-1]=='\x01') l--; if(l>0) l--; } t=l+1; /* Store start position of next line */ /* Move to start of whitespace */ while(l>0 && isspace((unsigned char)linebuf[l])) l--; outbuf_append(&outbuf, &outp, linebuf, l+1, &outbuf_size); outbuf_append(&outbuf, &outp, "\r\n", 2, &outbuf_size); /* Move trailing words to start of buffer. */ l=prefix_bytes; if(k-t>0) /* k-1 is the last char position. t is the start of the next line position */ memmove(linebuf+l, linebuf+t, k-t); l+=k-t; /* Find new ocol */ for(ocol=prefix_len+1,t=prefix_bytes; t<l; t++) { switch(linebuf[t]) { case '\x01': /* CTRL-A */ t++; if(linebuf[t]!='\x01') break; /* Fall-through */ default: ocol++; } } } } } /* Trailing bits. */ if(l) { linebuf[l++]='\r'; linebuf[l++]='\n'; outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size); } *outp=0; /* If there were no CRs in the input, strip all CRs */ if(!crcount) { for(inbuf=outbuf; *inbuf; inbuf++) { if(*inbuf=='\r') memmove(inbuf, inbuf+1, strlen(inbuf)); } } free(linebuf); if(prefix) free(prefix); return outbuf; }