}
/*
-** Escape the input string if it is needed and in accordance with
-** eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
+** Escape the text starting at byte iStart of pStr, if needed, using the
+** escape encoding of eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
+** The pStr string is modified appropriately.
**
** Escaping is needed if the string contains any control characters
** other than \t, \n, and \r\n
**
-** If no escaping is needed (the common case) then set *ppOut to NULL
-** and return 0. If escaping is needed, write the escaped string into
-** memory obtained from sqlite3_malloc64() and make *ppOut point to that
-** memory and return 0. If an error occurs, return non-zero.
-**
-** The caller is responsible for freeing *ppFree if it is non-NULL in order
-** to reclaim memory.
+** If no escaping is needed (the common case) then pStr is unchanged.
+** If escaping is required, then pStr is expanded and modified to hold
+** an escaped representation of the text.
*/
static void qrfEscape(
int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */
int iStart /* Begin escapding on this byte of pStr */
){
sqlite3_int64 i, j; /* Loop counters */
- sqlite3_int64 sz; /* Size of the string prior to escaping */
sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
unsigned char *zIn; /* Text to be escaped */
+ unsigned char nIn; /* Bytes of text to be escaped */
unsigned char c; /* A single character of the text */
unsigned char *zOut; /* Where to write the results */
/* Find the text to be escaped */
zIn = (unsigned char*)sqlite3_str_value(pStr);
+ nIn = sqlite3_str_length(pStr);
if( zIn==0 ) return;
zIn += iStart;
+ nIn -= iStart;
/* Count the control characters */
- for(i=0; (c = zIn[i])!=0; i++){
- if( c<=0x1f
+ for(i=0; i<nIn; i++){
+ if( (c = zIn[i])<=0x1f
&& c!='\t'
&& c!='\n'
&& (c!='\r' || zIn[i+1]!='\n')
/* Make space to hold the escapes. Copy the original text to the end
** of the available space. */
- sz = sqlite3_str_length(pStr) - iStart;
if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
sqlite3_str_appendchar(pStr, nCtrl, ' ');
zOut = (unsigned char*)sqlite3_str_value(pStr);
if( zOut==0 ) return;
zOut += iStart;
zIn = zOut + nCtrl;
- memmove(zIn,zOut,sz);
+ memmove(zIn,zOut,nIn);
/* Convert the control characters */
- for(i=j=0; (c = zIn[i])!=0; i++){
- if( c>0x1f
+ for(i=j=0; i<nIn; i++){
+ if( (c = zIn[i])>0x1f
|| c=='\t'
|| c=='\n'
|| (c=='\r' && zIn[i+1]=='\n')
j += i;
}
zIn += i+1;
+ nIn -= i+1;
i = -1;
if( eEsc==QRF_ESC_Symbol ){
zOut[j++] = 0xe2;
break;
}
default: {
- const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
- qrfEncodeText(p, pOut, zTxt);
+ const void *pBlob = sqlite3_column_blob(p->pStmt,iCol);
+ int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
+ int rc;
+ qrfWrite(p);
+ if( nBlob==0 ){
+ /* no-op */
+ }else if( p->spec.eEsc==QRF_ESC_Off ){
+ rc = p->spec.xWrite(p->spec.pWriteArg,pBlob,nBlob);
+ if( rc ){
+ qrfError(p, rc, "Failed to write %d bytes of BLOB output", nBlob);
+ }
+ }else{
+ sqlite3_str_append(pOut, pBlob, nBlob);
+ qrfEscape(p->spec.eEsc, pOut, 0);
+ qrfWrite(p);
+ }
}
}
break;
-C Fix\sharmless\scompiler\swarning\sin\sQRF.
-D 2026-04-21T22:19:38.042
+C QRF\sand\sthe\sCLI\spreserve\szero\sbytes\swhen\soutputing\sunformatted\sBLOB\svalues.
+D 2026-04-22T12:22:32.829
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
F ext/qrf/README.md 9e644615d7d7b77ef7e9db798765679e50c5ed12eda48bce21c9ef9eb4715e9d
F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
-F ext/qrf/qrf.c 0c3396aa6d38ed50d741b81ceef18d1f591813a2691e52e3d33b20b065108867
+F ext/qrf/qrf.c b177155147ae97ce3ddc5791c08782e835405c51ca9b9655f4beffcc03028cae
F ext/qrf/qrf.h fbb223ff5789b324b3e9c22e787e4c1f53e217cff7cc5a243164d4b2e8410f4b
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4c05cde130f26991b7411d8c6809e0630625e18078742c963a047b4b9cc01d49
-F src/shell.c.in 4e68371fec5a8ab31038d51e7179d9ef3539d693e05a5fdabcd59483e445b27d
+F src/shell.c.in 68ce578f06cf2fcf6fa17867f9a35a139be1c39fd019be3ab1a7b9e6732e78ea
F src/sqlite.h.in 39d2e09114d2bdb7afd998f4a469c8f8cd065f8093835a7d0422f260fc78fb4f
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P d0d95a39bc211034071746395ee6dbcfbea9d573d27480655391ba9698f7e214
-R 358d94241303ce254bf450c1de0664be
+P dcfb505ac7762f7a3102e1c3853a83dca1d1ef436cc8981949b63c7d7992cc5b
+R 6f7eb80bc3d8547ebc53c3288e84721f
U drh
-Z f2e54d7d5452408c8009417fa06b81d6
+Z 8d40acb0befcd8d33f03cbfe6f7ca5f8
# Remove this line to create a well-formed Fossil manifest.
-dcfb505ac7762f7a3102e1c3853a83dca1d1ef436cc8981949b63c7d7992cc5b
+dbc1d6f0a3452607e4e92155df0fdb1c5ea4ea5ad1654664f86383faf6c105ef
** Works like.
** --------------
** cli_printf(FILE*, const char*, ...); fprintf()
+** cli_write(FILE*, const char*, int); write()
** cli_puts(const char*, FILE*); fputs()
** cli_vprintf(FILE*, const char*, va_list); vfprintf()
**
va_end(ap);
return rc;
}
+static int cli_write(FILE *out, const char *zData, int nData){
+ if( cli_output_capture && (out==stdout || out==stderr) ){
+ sqlite3_str_append(cli_output_capture, zData, nData);
+ }else{
+ nData = (int)fwrite(zData, 1, nData, out);
+ }
+ return nData;
+}
static int cli_puts(const char *zText, FILE *out){
if( cli_output_capture && (out==stdout || out==stderr) ){
sqlite3_str_appendall(cli_output_capture, zText);
*/
static int shellWriteQR(void *pX, const char *z, sqlite3_int64 n){
ShellState *pArg = (ShellState*)pX;
- cli_printf(pArg->out, "%.*s", (int)n, z);
+ cli_write(pArg->out, z, (int)n);
return SQLITE_OK;
}