12 #include "projectcontext.h"
15 #include "filewrite.h"
17 #include "wdlstring.h"
18 #include "wdlcstring.h"
19 #include "fastqueue.h"
20 #include "lineparse.h"
23 //#define WDL_MEMPROJECTCONTEXT_USE_ZLIB 1
25 #ifdef WDL_MEMPROJECTCONTEXT_USE_ZLIB
27 #define WDL_MEMPROJECTCONTEXT_ZLIB_CHUNKSIZE 65536
28 #include "zlib/zlib.h"
35 char *projectcontext_fastDoubleToString(double value
, char *bufOut
, int prec_digits
)
37 value
= denormal_filter_double2(value
);
44 if (value
> 2147483647.0)
46 if (value
>= 1.0e40
) sprintf(bufOut
, "%e", value
);
47 else sprintf(bufOut
, "%.*f", wdl_min(prec_digits
,8), value
);
48 while (*bufOut
) bufOut
++;
52 unsigned int value_i
, frac
, frac2
;
57 static const unsigned int scales
[9] =
70 value_i
= (unsigned int)value
;
71 const int value_digits
=
74 (value_i
>= 100000000 ?
75 (value_i
>= 1000000000 ? 10 : 9) :
76 (value_i
>= 10000000 ? 8 : 7)) :
77 (value_i
>= 100000 ? 6 : 5)
82 (value_i
>= 1000 ? 4 : 3) :
83 (value_i
>= 10 ? 2 : 1)
86 // double precision is limited to about 17 decimal digits of meaningful values
87 if (prec_digits
+ value_digits
> 17) prec_digits
= 17-value_digits
;
91 prec_digits2
= prec_digits
- 9;
93 if (prec_digits2
> 9) prec_digits2
= 9;
96 const unsigned int prec_scale
= scales
[prec_digits
-1];
97 const double dfrac
= (value
- value_i
) * prec_scale
;
100 const unsigned int prec_scale2
= scales
[prec_digits2
-1];
101 frac
= (unsigned int) dfrac
;
103 double dfrac2
= (dfrac
- frac
) * prec_scale2
;
104 frac2
= (unsigned int) (dfrac2
+ 0.5);
106 const int prec_scale2_small
= wdl_min(prec_scale2
/1024,10);
108 if (frac2
<= prec_scale2_small
) frac2
=0;
109 else if (frac2
>= prec_scale2
- prec_scale2_small
- 1) frac2
=prec_scale2
;
111 if (frac2
>= prec_scale2
)
113 frac2
-= prec_scale2
;
119 frac
= (unsigned int) (dfrac
+ 0.5);
121 const int prec_scale_small
= wdl_min(prec_scale
/1024,10);
122 if (frac
<= prec_scale_small
) frac
=0;
123 else if (frac
>=prec_scale
-prec_scale_small
- 1) frac
=prec_scale
;
126 if (frac
>= prec_scale
) // round up to next integer
134 value_i
= (unsigned int)(value
+0.5);
145 const int a
= (tmp
%10);
150 while (x
>0) *bufOut
++ = digs
[--x
];
162 int dleft
= prec_digits
;
167 const int a
= (tmp
%10);
169 if (x
|| a
|| frac2
) digs
[x
++] = '0'+a
;
170 } while (dleft
-- > 0 && tmp
);
172 while (dleft
-->0) *bufOut
++ = '0';
173 while (x
>0) *bufOut
++ = digs
[--x
];
179 dleft
= prec_digits2
;
182 const int a
= (tmp
%10);
184 if (x
|| a
) digs
[x
++] = '0'+a
;
185 } while (dleft
-- > 0 && tmp
);
187 while (dleft
-->0) *bufOut
++ = '0';
188 while (x
>0) *bufOut
++ = digs
[--x
];
196 int ProjectContextFormatString(char *outbuf
, size_t outbuf_size
, const char *fmt
, va_list va
)
200 while (*fmt
&& outbuf_size
> 1)
205 outbuf
[wroffs
++] = c
!= '\n' ? c
: ' ';
212 outbuf
[wroffs
++] = '%';
219 const char *ofmt
= fmt
-1;
220 bool want_abort
=false;
228 while (*fmt
>= '0' && *fmt
<= '9') prec
= prec
*10 + (*fmt
++-'0');
229 if (*fmt
!= 'f' || prec
< 0 || prec
>20)
234 else if (*fmt
== '0')
238 while (*fmt
>= '0' && *fmt
<= '9') prec
= prec
*10 + (*fmt
++-'0');
239 if (*fmt
!= 'x' && *fmt
!= 'X' && *fmt
!= 'd' && *fmt
!= 'u')
246 if (!want_abort
) switch (c
)
252 const char *str
=va_arg(va
,const char *);
253 const char qc
= outbuf_size
>= 3 && c
!= 's' ? getConfigStringQuoteChar(str
) : ' ';
257 outbuf
[wroffs
++] = qc
? qc
: '`';
258 outbuf_size
-=2; // will add trailing quote below
261 if (str
) while (outbuf_size
> 1 && *str
)
264 if (!qc
&& v
== '`') v
= '\'';
265 outbuf
[wroffs
++] = v
!= '\n' ? v
: ' ';
271 outbuf
[wroffs
++] = qc
? qc
: '`';
272 // outbuf_size already decreased above
278 int v
= (va_arg(va
,int)) & 0xff;
279 outbuf
[wroffs
++] = v
!= '\n' ? v
: ' ';
285 int v
= va_arg(va
,int);
288 outbuf
[wroffs
++] = '-';
290 v
=-v
; // this won't handle -2147483648 right, todo special case?
301 if (has_prec
== 2) while (x
<prec
) { tab
[x
++] = 0; }
303 while (--x
>= 0 && outbuf_size
>1)
305 outbuf
[wroffs
++] = '0' + tab
[x
];
312 unsigned int v
= va_arg(va
,unsigned int);
322 if (has_prec
== 2) while (x
<prec
) { tab
[x
++] = 0; }
324 while (--x
>= 0 && outbuf_size
>1)
326 outbuf
[wroffs
++] = '0' + tab
[x
];
334 const char base
= (c
- 'x') + 'a';
335 unsigned int v
= va_arg(va
,unsigned int);
346 if (has_prec
== 2) while (x
<prec
) { tab
[x
++] = 0; }
348 while (--x
>= 0 && outbuf_size
>1)
351 outbuf
[wroffs
++] = '0' + tab
[x
];
353 outbuf
[wroffs
++] = base
+ tab
[x
] - 10;
361 double v
= va_arg(va
,double);
365 projectcontext_fastDoubleToString(v
,tmp
,has_prec
?prec
:6);
366 const char *str
= tmp
;
367 while (outbuf_size
> 1 && *str
)
369 outbuf
[wroffs
++] = *str
++;
375 const char *p
=projectcontext_fastDoubleToString(v
,outbuf
+wroffs
,has_prec
?prec
:6);
376 int amt
= (int) (p
-(outbuf
+wroffs
));
388 #if defined(_WIN32) && defined(_DEBUG)
389 OutputDebugString("ProjectContextFormatString(): falling back to stock vsnprintf because of:");
390 OutputDebugString(ofmt
);
399 if (outbuf_size
<2||!*fmt
)
402 #if defined(_WIN32) && defined(_MSC_VER)
403 // _vsnprintf() does not always null terminate (see below)
404 _vsnprintf(outbuf
,outbuf_size
,fmt
,va
);
406 // vsnprintf() on non-win32, always null terminates
407 vsnprintf(outbuf
,outbuf_size
,fmt
,va
);
412 for (l
= 0; l
< outbuf_size
&& outbuf
[l
]; l
++) if (outbuf
[l
] == '\n') outbuf
[l
] = ' ';
414 #if defined(_WIN32) && defined(_MSC_VER)
415 // nul terminate for _vsnprintf()
424 class ProjectStateContext_Mem
: public ProjectStateContext
428 ProjectStateContext_Mem(WDL_HeapBuf
*hb
, int rwflags
)
434 #ifdef WDL_MEMPROJECTCONTEXT_USE_ZLIB
435 memset(&m_compstream
,0,sizeof(m_compstream
));
440 virtual ~ProjectStateContext_Mem()
442 #ifdef WDL_MEMPROJECTCONTEXT_USE_ZLIB
446 deflateEnd(&m_compstream
);
448 else if (m_usecomp
==2)
450 inflateEnd(&m_compstream
);
455 virtual void WDL_VARARG_WARN(printf
,2,3) AddLine(const char *fmt
, ...);
456 virtual int GetLine(char *buf
, int buflen
); // returns -1 on eof
458 virtual WDL_INT64
GetOutputSize() { return m_heapbuf
? m_heapbuf
->GetSize() : 0; }
460 virtual int GetTempFlag() { return m_tmpflag
; }
461 virtual void SetTempFlag(int flag
) { m_tmpflag
=flag
; }
464 WDL_HeapBuf
*m_heapbuf
;
468 #ifdef WDL_MEMPROJECTCONTEXT_USE_ZLIB
471 if (m_pos
>= m_heapbuf
->GetSize()) return 1;
473 m_compstream
.next_in
= (unsigned char *)m_heapbuf
->Get() + m_pos
;
474 m_compstream
.avail_in
= m_heapbuf
->GetSize()-m_pos
;
475 m_compstream
.total_in
= 0;
477 int outchunk
= 65536;
478 m_compstream
.next_out
= (unsigned char *)m_compdatabuf
.Add(NULL
,outchunk
);
479 m_compstream
.avail_out
= outchunk
;
480 m_compstream
.total_out
= 0;
482 int e
= inflate(&m_compstream
,Z_NO_FLUSH
);
484 m_pos
+= m_compstream
.total_in
;
485 m_compdatabuf
.Add(NULL
,m_compstream
.total_out
- outchunk
); // rewind
490 void FlushComp(bool eof
)
492 while (m_compdatabuf
.Available()>=WDL_MEMPROJECTCONTEXT_ZLIB_CHUNKSIZE
|| eof
)
494 if (!m_heapbuf
->GetSize()) m_heapbuf
->SetGranul(256*1024);
495 m_compstream
.next_in
= (unsigned char *)m_compdatabuf
.Get();
496 m_compstream
.avail_in
= m_compdatabuf
.Available();
497 m_compstream
.total_in
= 0;
499 int osz
= m_heapbuf
->GetSize();
501 int newsz
=osz
+ wdl_max(m_compstream
.avail_in
,8192) + 256;
502 m_compstream
.next_out
= (unsigned char *)m_heapbuf
->Resize(newsz
, false) + osz
;
503 if (m_heapbuf
->GetSize()!=newsz
) return; // ERROR
504 m_compstream
.avail_out
= newsz
-osz
;
505 m_compstream
.total_out
=0;
507 deflate(&m_compstream
,eof
?Z_SYNC_FLUSH
:Z_NO_FLUSH
);
509 m_heapbuf
->Resize(osz
+m_compstream
.total_out
,false);
510 m_compdatabuf
.Advance(m_compstream
.total_in
);
511 if (m_compstream
.avail_out
) break; // no need to process anymore
514 m_compdatabuf
.Compact();
517 // these will be used for either decompression or compression, fear
518 int m_usecomp
; // 0=?, -1 = fail, 1=yes
519 WDL_Queue m_compdatabuf
;
520 z_stream m_compstream
;
525 // returns length, modifies ptr to point to tmp if newline needed to be filtered
526 static int filter_newline_buf(const char **ptr
, char *tmp
, int tmpsz
)
528 const char *use_buf
= *ptr
;
529 if (!use_buf
) return -1;
532 for (l
=0; use_buf
[l
] && use_buf
[l
] != '\n'; l
++);
534 if (!use_buf
[l
]) return l
;
536 lstrcpyn_safe(tmp
,use_buf
,tmpsz
);
539 if (l
>= tmpsz
) return tmpsz
-1;
541 for (;tmp
[l
]; l
++) if (tmp
[l
] == '\n') tmp
[l
] = ' '; // replace any newlines with spaces
546 void ProjectStateContext_Mem::AddLine(const char *fmt
, ...)
548 if (!m_heapbuf
|| !(m_rwflags
&2)) return;
558 if (fmt
&& fmt
[0] == '%' && (fmt
[1] == 's' || fmt
[1] == 'S') && !fmt
[2])
560 use_buf
= va_arg(va
,const char *);
561 l
= filter_newline_buf(&use_buf
,tmp
,(int)sizeof(tmp
)) + 1;
565 l
= ProjectContextFormatString(tmp
,sizeof(tmp
),fmt
, va
) + 1;
573 #ifdef WDL_MEMPROJECTCONTEXT_USE_ZLIB
576 if (deflateInit(&m_compstream
,WDL_MEMPROJECTCONTEXT_USE_ZLIB
)==Z_OK
) m_usecomp
=1;
582 m_compdatabuf
.Add(use_buf
,(int)l
);
589 const int sz
=m_heapbuf
->GetSize();
590 if (!sz
&& m_heapbuf
->GetGranul() < 256*1024)
592 m_heapbuf
->SetGranul(256*1024);
595 char *p
= (char *)m_heapbuf
->ResizeOK(sz
+l
);
598 // ERROR, resize to 0 and return
599 m_heapbuf
->Resize(0);
603 memcpy(p
+sz
,use_buf
,l
);
606 int ProjectStateContext_Mem::GetLine(char *buf
, int buflen
) // returns -1 on eof
608 if (!m_heapbuf
|| !(m_rwflags
&1)) return -1;
613 #ifdef WDL_MEMPROJECTCONTEXT_USE_ZLIB
616 unsigned char hdr
[]={0x78,0x01};
617 if (m_heapbuf
->GetSize()>2 && !memcmp(hdr
,m_heapbuf
->Get(),4) && inflateInit(&m_compstream
)==Z_OK
) m_usecomp
=2;
625 const char *p
= (const char*) m_compdatabuf
.Get();
626 for (x
= 0; x
< m_compdatabuf
.Available() && p
[x
] && p
[x
] != '\r' && p
[x
] != '\n'; x
++);
627 while (x
>= m_compdatabuf
.Available())
629 int err
= DecompressData();
630 p
= (const char *)m_compdatabuf
.Get();
631 for (; x
< m_compdatabuf
.Available() && p
[x
] && p
[x
] != '\r' && p
[x
] != '\n'; x
++);
636 if (x
||!m_compdatabuf
.Available()) break;
638 m_compdatabuf
.Advance(1); // skip over nul or newline char
643 if (buflen
> 0 && buf
)
645 int l
= wdl_min(buflen
-1,x
);
646 memcpy(buf
,m_compdatabuf
.Get(),l
);
650 m_compdatabuf
.Advance(x
+1);
651 m_compdatabuf
.Compact();
657 int avail
= m_heapbuf
->GetSize() - m_pos
;
658 const char *p
=(const char *)m_heapbuf
->Get() + m_pos
;
659 while (avail
> 0 && (p
[0] =='\r'||p
[0]=='\n'||!p
[0]||p
[0] == ' ' || p
[0] == '\t'))
665 if (avail
<= 0) return -1;
668 for (x
= 0; x
< avail
&& p
[x
] && p
[x
] != '\n'; x
++);
676 if (l
>0 && buf
[l
-1]=='\r') l
--;
682 class ProjectStateContext_File
: public ProjectStateContext
686 ProjectStateContext_File(WDL_FileRead
*rd
, WDL_FileWrite
*wr
)
694 _rdbuf_pos
= _rdbuf_valid
= 0;
696 virtual ~ProjectStateContext_File(){ delete m_rd
; delete m_wr
; };
698 virtual void WDL_VARARG_WARN(printf
,2,3) AddLine(const char *fmt
, ...);
699 virtual int GetLine(char *buf
, int buflen
); // returns -1 on eof
701 virtual WDL_INT64
GetOutputSize() { return m_bytesOut
; }
703 virtual int GetTempFlag() { return m_tmpflag
; }
704 virtual void SetTempFlag(int flag
) { m_tmpflag
=flag
; }
706 bool HasError() { return m_errcnt
; }
708 WDL_INT64 m_bytesOut WDL_FIXALIGN
;
714 int _rdbuf_pos
, _rdbuf_valid
;
722 int ProjectStateContext_File::GetLine(char *buf
, int buflen
)
724 if (!m_rd
||buflen
<3) return -1;
726 char * const buf_orig
=buf
;
727 int rdpos
= _rdbuf_pos
;
728 int rdvalid
= _rdbuf_valid
;
733 while (rdpos
< rdvalid
)
735 char c
=rdbuf
[rdpos
++];
738 case ' ': case '\r': case '\n': case '\t': break;
744 int mxl
= rdvalid
- rdpos
;
745 if (mxl
> buflen
) mxl
=buflen
;
748 char c2
= rdbuf
[rdpos
++];
749 if (c2
=='\n') goto finished
;
757 rdvalid
= m_rd
->Read(rdbuf
, sizeof(rdbuf
));
758 if (rdvalid
<1) break;
765 _rdbuf_valid
=rdvalid
;
767 if (buf
> buf_orig
&& buf
[-1] == '\r') buf
--;
774 rdvalid
= m_rd
->Read(rdbuf
, sizeof(rdbuf
));
783 void ProjectStateContext_File::AddLine(const char *fmt
, ...)
785 if (m_wr
&& !m_errcnt
)
795 if (fmt
&& fmt
[0] == '%' && (fmt
[1] == 's' || fmt
[1] == 'S') && !fmt
[2])
797 // special case "%s" passed, directly use it
798 use_buf
= va_arg(va
,const char *);
799 l
= filter_newline_buf(&use_buf
,tmp
,(int)sizeof(tmp
));
803 l
= ProjectContextFormatString(tmp
,sizeof(tmp
),fmt
, va
);
812 if (use_buf
[0] == '<') m_indent
+=2;
813 else if (use_buf
[0] == '>') a
=(m_indent
-=2);
819 memset(tb
,' ',a
< (int)sizeof(tb
) ? a
: (int)sizeof(tb
));
822 const int tl
= a
< (int)sizeof(tb
) ? a
: (int)sizeof(tb
);
828 err
|= m_wr
->Write(use_buf
,l
) != l
;
829 err
|= m_wr
->Write("\r\n",2) != 2;
832 if (err
) m_errcnt
=true;
838 ProjectStateContext
*ProjectCreateFileRead(const char *fn
)
840 WDL_FileRead
*rd
= new WDL_FileRead(fn
,0,65536,1);
841 if (!rd
|| !rd
->IsOpen())
846 return new ProjectStateContext_File(rd
,NULL
);
848 ProjectStateContext
*ProjectCreateFileWrite(const char *fn
)
850 WDL_FileWrite
*wr
= new WDL_FileWrite(fn
);
851 if (!wr
|| !wr
->IsOpen())
856 return new ProjectStateContext_File(NULL
,wr
);
860 ProjectStateContext
*ProjectCreateMemCtx(WDL_HeapBuf
*hb
)
862 return new ProjectStateContext_Mem(hb
,3);
865 ProjectStateContext
*ProjectCreateMemCtx_Read(const WDL_HeapBuf
*hb
)
867 return new ProjectStateContext_Mem((WDL_HeapBuf
*)hb
,1);
869 ProjectStateContext
*ProjectCreateMemCtx_Write(WDL_HeapBuf
*hb
)
871 return new ProjectStateContext_Mem(hb
,2);
877 class ProjectStateContext_FastQueue
: public ProjectStateContext
881 ProjectStateContext_FastQueue(WDL_FastQueue
*fq
)
887 virtual ~ProjectStateContext_FastQueue()
891 virtual void WDL_VARARG_WARN(printf
,2,3) AddLine(const char *fmt
, ...);
892 virtual int GetLine(char *buf
, int buflen
) { return -1; }//unsup
894 virtual WDL_INT64
GetOutputSize() { return m_fq
? m_fq
->Available() : 0; }
896 virtual int GetTempFlag() { return m_tmpflag
; }
897 virtual void SetTempFlag(int flag
) { m_tmpflag
=flag
; }
905 void ProjectStateContext_FastQueue::AddLine(const char *fmt
, ...)
913 if (fmt
&& fmt
[0] == '%' && (fmt
[1] == 's' || fmt
[1] == 'S') && !fmt
[2])
915 const char *use_buf
= va_arg(va
,const char *);
916 const int l
= filter_newline_buf(&use_buf
,tmp
,(int)sizeof(tmp
));
917 if (use_buf
) m_fq
->Add(use_buf
, l
+ 1);
921 const int l
= ProjectContextFormatString(tmp
,sizeof(tmp
),fmt
, va
);
922 if (l
>0) m_fq
->Add(tmp
, l
+1);
933 ProjectStateContext
*ProjectCreateMemWriteFastQueue(WDL_FastQueue
*fq
) // only write!
935 return new ProjectStateContext_FastQueue(fq
);
938 bool ProjectContext_GetNextLine(ProjectStateContext
*ctx
, LineParser
*lpOut
)
943 if (ctx
->GetLine(linebuf
,sizeof(linebuf
)))
949 if (lpOut
->parse(linebuf
)||lpOut
->getnumtokens()<=0) continue;
951 return true; // success!
957 bool ProjectContext_EatCurrentBlock(ProjectStateContext
*ctx
, ProjectStateContext
*ctxOut
)
963 if (ctx
->GetLine(linebuf
,sizeof(linebuf
))) break;
964 const char *sp
= linebuf
;
965 while (*sp
== ' ' || *sp
== '\t') sp
++;
968 if (*p
== '\'' || *p
== '"' || *p
== '`') p
++; // skip a quote if any
969 if (p
[0] == '>') if (--child_count
< 1) return true;
971 if (ctxOut
) ctxOut
->AddLine("%s",sp
);
973 if (p
[0] == '<') child_count
++;
980 #include "wdl_base64.h"
982 int cfg_decode_binary(ProjectStateContext
*ctx
, WDL_HeapBuf
*hb
) // 0 on success, doesnt clear hb
988 if (ctx
->GetLine(linebuf
,sizeof(linebuf
))) break;
990 const char *p
= linebuf
;
991 while (*p
== ' ' || *p
== '\t') p
++;
992 if (*p
== '\'' || *p
== '"' || *p
== '`') p
++; // skip a quote if any
994 if (p
[0] == '<') child_count
++;
995 else if (p
[0] == '>') { if (child_count
-- == 1) return 0; }
996 else if (child_count
== 1 && p
[0])
998 unsigned char buf
[3200];
999 const int buf_l
=wdl_base64decode(p
,buf
,sizeof(buf
));
1002 const int os
=hb
->GetSize();
1003 char *dest
= (char*)hb
->ResizeOK(os
+buf_l
);
1004 if (dest
) memcpy(dest
+os
,buf
,buf_l
);
1011 void cfg_encode_binary(ProjectStateContext
*ctx
, const void *ptr
, int len
)
1013 if (!ctx
|| len
< 1) return;
1015 const unsigned char *p
=(const unsigned char *)ptr
;
1016 if (len
> 128 && len
< (1<<30))
1018 // we could (probably should) use dynamic_cast<> here, but as we span modules this
1019 // raises all kinds of questions (especially with VC having the option to disable RTTI).
1020 // for now, we assume that the first void * in an object is the vtable pointer. with
1021 // testing, of course.
1022 WDL_FastQueue
*fq
= NULL
;
1023 WDL_HeapBuf
*hb
= NULL
;
1024 #ifndef WDL_MEMPROJECTCONTEXT_USE_ZLIB
1025 static const ProjectStateContext_Mem
hb_def(NULL
,0);
1027 static const ProjectStateContext_FastQueue
fq_def(NULL
);
1028 if (*(void **)ctx
== *(void **)&fq_def
)
1030 fq
=((ProjectStateContext_FastQueue
*)ctx
)->m_fq
;
1032 #ifndef WDL_MEMPROJECTCONTEXT_USE_ZLIB
1033 else if (*(void **)ctx
== *(void **)&hb_def
)
1035 hb
=((ProjectStateContext_Mem
*)ctx
)->m_heapbuf
;
1041 const int linelen8
= 280/8;
1043 const int enc_len
= ((len
+2)/3)*4; // every 3 characters end up as 4
1044 const int lines
= (enc_len
+ linelen8
*8 - 1) / (linelen8
*8);
1049 wr
= (char*)fq
->Add(WDL_FASTQUEUE_ADD_NOZEROBUF
,enc_len
+ lines
);
1053 const int oldsz
=hb
->GetSize();
1054 wr
=(char*)hb
->ResizeOK(oldsz
+ enc_len
+ lines
,false);
1061 char * const wr_end
=wr
+ enc_len
+ lines
;
1068 const int accum
= (p
[0] << 16) + (p
[1] << 8) + p
[2];
1069 const int accum2
= (p
[3] << 16) + (p
[4] << 8) + p
[5];
1070 wr
[0] = wdl_base64_alphabet
[(accum
>> 18) & 0x3F];
1071 wr
[1] = wdl_base64_alphabet
[(accum
>> 12) & 0x3F];
1072 wr
[2] = wdl_base64_alphabet
[(accum
>> 6) & 0x3F];
1073 wr
[3] = wdl_base64_alphabet
[accum
& 0x3F];
1074 wr
[4] = wdl_base64_alphabet
[(accum2
>> 18) & 0x3F];
1075 wr
[5] = wdl_base64_alphabet
[(accum2
>> 12) & 0x3F];
1076 wr
[6] = wdl_base64_alphabet
[(accum2
>> 6) & 0x3F];
1077 wr
[7] = wdl_base64_alphabet
[accum2
& 0x3F];
1082 if (++lpos
>= linelen8
) { *wr
++= 0; lpos
=0; }
1087 const int accum
= (p
[0] << 16) + (p
[1] << 8) + p
[2];
1088 wr
[0] = wdl_base64_alphabet
[(accum
>> 18) & 0x3F];
1089 wr
[1] = wdl_base64_alphabet
[(accum
>> 12) & 0x3F];
1090 wr
[2] = wdl_base64_alphabet
[(accum
>> 6) & 0x3F];
1091 wr
[3] = wdl_base64_alphabet
[accum
& 0x3F];
1103 const int accum
= (p
[0] << 8) | p
[1];
1104 wr
[0] = wdl_base64_alphabet
[(accum
>> 10) & 0x3F];
1105 wr
[1] = wdl_base64_alphabet
[(accum
>> 4) & 0x3F];
1106 wr
[2] = wdl_base64_alphabet
[(accum
& 0xF)<<2];
1110 const int accum
= p
[0];
1111 wr
[0] = wdl_base64_alphabet
[(accum
>> 2) & 0x3F];
1112 wr
[1] = wdl_base64_alphabet
[(accum
& 0x3)<<4];
1118 if (lpos
>0) *wr
++=0;
1122 if (wr
!= wr_end
) OutputDebugString("cfg_encode_binary: block mode size mismatch!\n");
1124 if (wr
!= wr_end
) printf("cfg_encode_binary: block mode size mismatch %d!\n", (int)(wr
-wr_end
));
1136 if (thiss
> 96) thiss
=96;
1137 wdl_base64encode(p
,buf
,thiss
);
1139 ctx
->AddLine("%s",buf
);
1148 int cfg_decode_textblock(ProjectStateContext
*ctx
, WDL_String
*str
) // 0 on success, appends to str
1151 bool did_firstline
=!!str
->Get()[0];
1155 if (ctx
->GetLine(linebuf
,sizeof(linebuf
))) break;
1157 const char *p
= linebuf
;
1158 while (*p
== ' ' || *p
== '\t') p
++;
1159 if (*p
== '\'' || *p
== '"' || *p
== '`') p
++; // skip a quote if any
1161 if (!p
[0]) continue;
1162 else if (p
[0] == '<') child_count
++;
1163 else if (p
[0] == '>') { if (child_count
-- == 1) return 0; }
1164 else if (child_count
== 1 && p
[0] == '|')
1166 if (!did_firstline
) did_firstline
=true;
1167 else str
->Append("\r\n");
1174 int cfg_decode_textblock(ProjectStateContext
*ctx
, WDL_FastString
*str
) // 0 on success, appends to str
1177 bool did_firstline
=!!str
->Get()[0];
1181 if (ctx
->GetLine(linebuf
,sizeof(linebuf
))) break;
1183 const char *p
= linebuf
;
1184 while (*p
== ' ' || *p
== '\t') p
++;
1185 if (*p
== '\'' || *p
== '"' || *p
== '`') p
++; // skip a quote if any
1187 if (!p
[0]) continue;
1188 else if (p
[0] == '<') child_count
++;
1189 else if (p
[0] == '>') { if (child_count
-- == 1) return 0; }
1190 else if (child_count
== 1 && p
[0] == '|')
1192 if (!did_firstline
) did_firstline
=true;
1193 else str
->Append("\r\n");
1202 void cfg_encode_textblock(ProjectStateContext
*ctx
, const char *text
)
1204 WDL_String
tmpcopy(text
);
1205 char *txt
=(char*)tmpcopy
.Get();
1209 while (*ntext
&& *ntext
!= '\r' && *ntext
!= '\n') ntext
++;
1210 if (ntext
> txt
|| *ntext
)
1214 ctx
->AddLine("|%s",txt
);
1220 if (*++txt
== '\n') txt
++;
1222 else if (*txt
== '\n')
1224 if (*++txt
== '\r') txt
++;
1229 char getConfigStringQuoteChar(const char *p
)
1231 if (!p
|| !*p
) return '"';
1235 while (*p
&& flags
!=15)
1238 if (c
=='"') flags
|=1;
1239 else if (c
=='\'') flags
|=2;
1240 else if (c
=='`') flags
|=4;
1241 else if (c
== ' ' || c
== '\t') flags
|= 8;
1243 #ifndef PROJECTCONTEXT_USE_QUOTES_WHEN_NO_SPACES
1244 if (!(flags
& 8) && fc
!= '"' && fc
!= '\'' && fc
!= '`' && fc
!= '#' && fc
!= ';') return ' ';
1247 if (!(flags
& 1)) return '"';
1248 if (!(flags
& 2)) return '\'';
1249 if (!(flags
& 4)) return '`';
1253 void makeEscapedConfigString(const char *in
, WDL_String
*out
)
1256 if (!in
|| !*in
) out
->Set("\"\"");
1257 else if ((c
= getConfigStringQuoteChar(in
)))
1270 else // ick, change ` into '
1275 char *p
=out
->Get()+1;
1278 if (*p
== '`') *p
='\'';
1284 void makeEscapedConfigString(const char *in
, WDL_FastString
*out
)
1287 if (!in
|| !*in
) out
->Set("\"\"");
1288 else if ((c
= getConfigStringQuoteChar(in
)))
1301 else // ick, change ` into '
1306 char *p
=(char *)out
->Get()+1;
1309 if (*p
== '`') *p
='\'';