2016-03-08 22:14:30 +01:00
|
|
|
#ifndef GB_SAFEBUF_H
|
|
|
|
#define GB_SAFEBUF_H
|
2013-08-02 13:12:24 -07:00
|
|
|
|
2013-12-10 15:28:04 -08:00
|
|
|
#include "gb-include.h"
|
2013-08-02 13:12:24 -07:00
|
|
|
|
2015-05-15 11:55:40 -07:00
|
|
|
/**
|
|
|
|
* Safe Char Buffer, or mutable Strings.
|
|
|
|
* (for java programmers, very similar to the StringBuffer class, with all the speed that c++ allows).
|
|
|
|
* Most of strings in Gigablast are handled by those.
|
|
|
|
*/
|
2015-07-13 14:59:44 -06:00
|
|
|
|
|
|
|
#include "iana_charset.h"
|
2016-06-28 11:01:47 +02:00
|
|
|
#include "Sanity.h"
|
2016-06-20 19:29:10 +02:00
|
|
|
|
|
|
|
|
2017-01-06 12:35:41 +01:00
|
|
|
template<int n=1024> class StackBuf;
|
2017-02-15 22:26:41 +01:00
|
|
|
template<int n=1024> class SmallBuf;
|
2017-01-06 12:35:41 +01:00
|
|
|
|
2014-08-28 12:55:02 -07:00
|
|
|
class SafeBuf {
|
|
|
|
public:
|
2013-08-02 13:12:24 -07:00
|
|
|
//*TRUCTORS
|
|
|
|
SafeBuf();
|
2016-02-23 15:19:18 +01:00
|
|
|
SafeBuf(int32_t initSize, const char *label);
|
2013-11-24 19:46:44 -07:00
|
|
|
|
|
|
|
void constructor();
|
|
|
|
|
2017-01-06 12:35:41 +01:00
|
|
|
private:
|
2013-08-02 13:12:24 -07:00
|
|
|
//be careful with passing in a stackBuf! it could go out
|
|
|
|
//of scope independently of the safebuf.
|
2017-01-05 17:22:42 +01:00
|
|
|
SafeBuf(char* stackBuf, int32_t cap);
|
2017-01-08 15:17:38 +01:00
|
|
|
template<int n> friend class StackBuf;
|
2017-02-15 22:26:41 +01:00
|
|
|
template<int n> friend class SmallBuf;
|
2017-01-06 12:35:41 +01:00
|
|
|
|
|
|
|
public:
|
2014-11-10 14:45:11 -08:00
|
|
|
SafeBuf(char *heapBuf, int32_t bufMax, int32_t bytesInUse, bool ownData);
|
2013-08-02 13:12:24 -07:00
|
|
|
~SafeBuf();
|
2013-11-19 23:53:40 -07:00
|
|
|
|
2016-02-23 15:19:18 +01:00
|
|
|
void setLabel ( const char *label );
|
2013-08-02 13:12:24 -07:00
|
|
|
|
|
|
|
// CAUTION: BE CAREFUL WHEN USING THE FOLLOWING TWO FUNCTIONS!!
|
|
|
|
// setBuf() allows you reset the contents of the SafeBuf to either
|
|
|
|
// a stack buffer or a dynamic buffer. Only pass in true for
|
|
|
|
// ownData if this is not a stack buffer and you are sure you
|
|
|
|
// want SafeBuf to free the data for you. Keep in mind, all
|
|
|
|
// previous content in SafeBuf will be cleared when you pass it
|
|
|
|
// a new buffer.
|
2015-07-13 14:59:44 -06:00
|
|
|
bool setBuf(char *newBuf,
|
|
|
|
int32_t bufMax,
|
|
|
|
int32_t bytesInUse,
|
2016-11-07 12:55:37 +01:00
|
|
|
bool ownData);
|
2013-08-02 13:12:24 -07:00
|
|
|
|
|
|
|
// set buffer from another safebuf, stealing it
|
|
|
|
bool stealBuf ( SafeBuf *sb );
|
|
|
|
|
|
|
|
//ACCESSORS
|
2016-05-23 16:49:25 +02:00
|
|
|
char *getBufPtr() { return m_buf + m_length; }
|
|
|
|
const char *getBufPtr() const { return m_buf + m_length; }
|
|
|
|
char *getBufStart() { return m_buf; }
|
|
|
|
const char *getBufStart() const { return m_buf; }
|
|
|
|
char *getBufEnd() { return m_buf + m_capacity; }
|
|
|
|
const char *getBufEnd() const { return m_buf + m_capacity; }
|
|
|
|
int32_t getCapacity() const { return m_capacity; }
|
|
|
|
int32_t getAvail() const { return m_capacity - m_length; }
|
|
|
|
int32_t length() const { return m_length; }
|
2016-10-28 13:43:40 +02:00
|
|
|
void print() const {
|
|
|
|
if ( write(1,m_buf,m_length) != m_length) { gbshutdownAbort(true); }
|
|
|
|
}
|
2013-08-02 13:12:24 -07:00
|
|
|
|
|
|
|
// . returns bytes written to file, 0 is acceptable if m_length == 0
|
|
|
|
// . returns -1 on error and sets g_errno
|
2016-10-28 13:43:40 +02:00
|
|
|
int32_t saveToFile(const char *dir, const char *filename) const;
|
|
|
|
int32_t dumpToFile(const char *filename) const;
|
|
|
|
int32_t save(const char *dir, const char *fname) const { return saveToFile(dir,fname); }
|
|
|
|
int32_t save(const char *fullFilename) const;
|
2014-07-29 10:02:43 -07:00
|
|
|
// saves to tmp file and if that succeeds then renames to orig filename
|
2016-10-28 13:43:40 +02:00
|
|
|
int32_t safeSave(const char *filename) const;
|
2014-01-11 16:08:42 -08:00
|
|
|
|
2016-02-23 15:19:18 +01:00
|
|
|
int32_t fillFromFile(const char *filename);
|
|
|
|
int32_t fillFromFile(const char *dir, const char *filename, const char *label=NULL);
|
2016-03-08 12:44:21 +01:00
|
|
|
|
2016-02-23 15:19:18 +01:00
|
|
|
int32_t load(const char *dir, const char *fname, const char *label = NULL) {
|
2016-03-08 12:44:21 +01:00
|
|
|
return fillFromFile(dir,fname,label);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t load(const char *fname) {
|
|
|
|
return fillFromFile(fname);
|
|
|
|
}
|
2014-01-11 16:08:42 -08:00
|
|
|
|
2016-03-12 16:18:13 +01:00
|
|
|
bool safeTruncateEllipsis ( const char *src , int32_t maxLen );
|
|
|
|
bool safeTruncateEllipsis ( const char *src , int32_t srcLen, int32_t maxLen );
|
2014-07-08 19:38:54 -07:00
|
|
|
|
2016-09-23 16:30:17 +02:00
|
|
|
bool safeDecodeJSONToUtf8 ( const char *json, int32_t jsonLen);
|
2013-10-11 16:14:26 -06:00
|
|
|
|
2016-05-19 16:17:03 +02:00
|
|
|
bool set ( const char *str ) {
|
2013-08-30 16:20:38 -07:00
|
|
|
purge();
|
|
|
|
if ( ! str ) return true;
|
2013-10-14 18:19:59 -06:00
|
|
|
// puts a \0 at the end, but does not include it in m_length:
|
2013-08-30 16:20:38 -07:00
|
|
|
return safeStrcpy ( str );
|
2016-05-19 18:37:26 +02:00
|
|
|
}
|
2013-08-30 16:20:38 -07:00
|
|
|
|
2013-09-13 09:23:18 -07:00
|
|
|
void removeLastChar ( char lastChar ) {
|
|
|
|
if ( m_length <= 0 ) return;
|
|
|
|
if ( m_buf[m_length-1] != lastChar ) return;
|
|
|
|
m_length--;
|
|
|
|
m_buf[m_length] = '\0';
|
2016-05-19 18:37:26 +02:00
|
|
|
}
|
2013-09-13 09:23:18 -07:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
//MUTATORS
|
2016-02-18 17:08:30 +01:00
|
|
|
bool safePrintf(const char *formatString, ...)
|
2013-08-02 13:12:24 -07:00
|
|
|
__attribute__ ((format(printf, 2, 3)));
|
2016-04-27 15:04:09 +02:00
|
|
|
|
2016-02-23 20:16:06 +01:00
|
|
|
bool safeMemcpy(const void *s, int32_t len){return safeMemcpy((const char*)s,len);}
|
2015-11-12 12:10:39 +01:00
|
|
|
bool safeMemcpy(const char *s, int32_t len);
|
2016-02-23 15:19:18 +01:00
|
|
|
bool safeMemcpy_nospaces(const char *s, int32_t len);
|
2016-05-23 16:49:25 +02:00
|
|
|
bool safeMemcpy(const SafeBuf *c) { return safeMemcpy(c->m_buf,c->m_length); }
|
2016-02-23 15:19:18 +01:00
|
|
|
bool safeStrcpy ( const char *s ) ;
|
2014-01-28 11:10:59 -08:00
|
|
|
//bool safeStrcpyPrettyJSON ( char *decodedJson ) ;
|
2015-11-12 12:10:39 +01:00
|
|
|
bool safeUtf8ToJSON ( const char *utf8 ) ;
|
|
|
|
bool jsonEncode ( const char *utf8 ) { return safeUtf8ToJSON(utf8); }
|
2014-11-10 14:45:11 -08:00
|
|
|
bool jsonEncode ( char *utf8 , int32_t utf8Len );
|
2013-11-12 13:51:52 -08:00
|
|
|
|
2016-09-23 16:30:17 +02:00
|
|
|
bool base64Encode ( const char *s , int32_t len );
|
|
|
|
bool base64Decode ( const char *src , int32_t srcLen ) ;
|
2014-04-24 14:04:57 -07:00
|
|
|
|
2016-05-23 16:49:25 +02:00
|
|
|
bool base64Encode( const char *s ) ;
|
2015-03-05 11:10:40 -08:00
|
|
|
|
2014-11-10 14:45:11 -08:00
|
|
|
//bool pushLong ( int32_t val ) { return safeMemcpy((char *)&val,4); }
|
2016-05-23 16:49:25 +02:00
|
|
|
bool cat(const SafeBuf& c);
|
2016-01-27 16:39:39 +01:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
void reset() { m_length = 0; }
|
|
|
|
void purge(); // Clear all data and free all allocated memory
|
2013-11-20 15:51:58 -08:00
|
|
|
|
2013-10-16 12:12:22 -07:00
|
|
|
// . if clearIt is true we init the new buffer space to zeroes
|
|
|
|
// . used by Collectiondb.cpp
|
2016-02-23 15:19:18 +01:00
|
|
|
bool reserve(int32_t i, const char *label=NULL , bool clearIt = false );
|
|
|
|
bool reserve2x(int32_t i, const char *label = NULL );
|
2013-10-11 16:14:26 -06:00
|
|
|
|
2014-11-10 14:45:11 -08:00
|
|
|
void incrementLength(int32_t i) {
|
2013-09-13 09:23:18 -07:00
|
|
|
m_length += i;
|
|
|
|
// watch out for negative i's
|
|
|
|
if ( m_length < 0 ) m_length = 0;
|
2016-05-19 18:37:26 +02:00
|
|
|
}
|
2015-11-13 17:55:44 +01:00
|
|
|
void setLength(int32_t i) { m_length = i; }
|
2013-08-02 13:12:24 -07:00
|
|
|
char *getNextLine ( char *p ) ;
|
2016-02-23 15:19:18 +01:00
|
|
|
int32_t catFile(const char *filename) ;
|
2016-01-27 16:37:35 +01:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
void detachBuf();
|
2016-05-23 22:20:01 +02:00
|
|
|
bool insert ( const char *s , int32_t insertPos ) ;
|
|
|
|
bool insert2 ( const char *s , int32_t slen, int32_t insertPos ) ;
|
|
|
|
bool replace ( const char *src, const char *dst ) ; // must be same lengths!
|
2016-12-14 15:11:10 +01:00
|
|
|
bool removeChunk1 ( const char *p , int32_t len ) ;
|
2014-11-10 14:45:11 -08:00
|
|
|
bool removeChunk2 ( int32_t pos , int32_t len ) ;
|
2016-05-23 22:20:01 +02:00
|
|
|
bool safeReplace(const char *s, int32_t len, int32_t pos, int32_t replaceLen);
|
|
|
|
bool safeReplace2 ( const char *s, int32_t slen,
|
|
|
|
const char *t, int32_t tlen,
|
2014-11-10 14:45:11 -08:00
|
|
|
int32_t startOff = 0 );
|
2013-11-12 13:51:52 -08:00
|
|
|
void replaceChar ( char src , char dst );
|
2013-08-02 13:12:24 -07:00
|
|
|
|
|
|
|
void zeroOut() { memset ( m_buf , 0 , m_capacity ); }
|
|
|
|
|
2015-07-01 18:59:52 -06:00
|
|
|
// insert <br>'s to make 's' no more than 'cols' chars per line
|
2016-05-30 15:12:44 +02:00
|
|
|
bool brify2 ( const char *s, int32_t cols, const char *sep = "<br>" ,
|
2014-01-02 01:20:08 -07:00
|
|
|
bool isHtml = true ) ;
|
2013-08-02 13:12:24 -07:00
|
|
|
|
2016-09-23 16:30:17 +02:00
|
|
|
bool brify( const char *s, int32_t slen, int32_t cols, const char *sep = "<br>",
|
2016-02-16 12:30:15 +01:00
|
|
|
bool isHtml = true );
|
2013-08-02 13:12:24 -07:00
|
|
|
|
2016-10-03 15:03:35 +02:00
|
|
|
bool hasDigits() const;
|
2014-05-30 15:05:00 -07:00
|
|
|
|
2016-09-23 16:30:17 +02:00
|
|
|
bool utf8Encode2( char *s, int32_t len, bool htmlEncode = false);
|
2016-01-27 16:30:37 +01:00
|
|
|
|
2016-02-16 12:30:15 +01:00
|
|
|
bool utf32Encode(UChar32* codePoints, int32_t cpLen);
|
2015-11-12 11:08:26 +01:00
|
|
|
|
2016-09-23 16:30:17 +02:00
|
|
|
bool htmlEncode( const char *s, int32_t len, bool encodePoundSign, int32_t truncateLen = -1 );
|
2013-08-30 16:20:38 -07:00
|
|
|
|
2016-02-25 17:38:31 +01:00
|
|
|
bool htmlEncode(const char *s) ;
|
2014-05-15 14:11:12 -07:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// html-encode any of the last "len" bytes that need it
|
2016-09-23 16:30:17 +02:00
|
|
|
bool htmlEncode(int32_t len);
|
2013-08-30 16:20:38 -07:00
|
|
|
|
2017-01-17 14:01:14 +01:00
|
|
|
bool htmlDecode(const char *s, int32_t len);
|
2013-08-30 16:20:38 -07:00
|
|
|
|
2016-02-25 17:38:31 +01:00
|
|
|
bool dequote ( const char *t , int32_t tlen );
|
2013-08-02 13:12:24 -07:00
|
|
|
|
2013-09-13 09:23:18 -07:00
|
|
|
// . append a \0 but do not inc m_length
|
|
|
|
// . for null terminating strings
|
|
|
|
bool nullTerm ( ) {
|
|
|
|
if(m_length >= m_capacity && !reserve(m_capacity + 1) )
|
|
|
|
return false;
|
|
|
|
m_buf[m_length] = '\0';
|
|
|
|
return true;
|
2016-05-19 18:37:26 +02:00
|
|
|
}
|
2016-11-03 18:17:51 +01:00
|
|
|
//utf8 hack. make sure the buffer has 4 NULs beyond the end so we can use the fast approach to decoding utf8 characters
|
|
|
|
bool nullTerm4() {
|
2016-11-04 13:48:34 +01:00
|
|
|
if(m_length+3 >= m_capacity && !reserve(m_capacity + 4) )
|
2016-11-03 18:17:51 +01:00
|
|
|
return false;
|
|
|
|
m_buf[m_length+0] = '\0';
|
|
|
|
m_buf[m_length+1] = '\0';
|
|
|
|
m_buf[m_length+2] = '\0';
|
|
|
|
m_buf[m_length+3] = '\0';
|
|
|
|
return true;
|
|
|
|
}
|
2013-09-13 09:23:18 -07:00
|
|
|
|
2016-10-03 15:03:35 +02:00
|
|
|
int32_t indexOf(char c) const;
|
2013-09-13 09:23:18 -07:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
bool pushChar (char i) {
|
|
|
|
if(m_length >= m_capacity)
|
|
|
|
if(!reserve(2*m_capacity + 1))
|
|
|
|
return false;
|
|
|
|
m_buf[m_length++] = i;
|
|
|
|
// let's do this because we kinda expect it when making strings
|
|
|
|
// and i've been burned by not having this before.
|
|
|
|
// no, cause if we reserve just the right length, we end up
|
|
|
|
// doing a realloc!! sux...
|
|
|
|
//m_buf[m_length] = '\0';
|
|
|
|
return true;
|
2016-05-19 18:37:26 +02:00
|
|
|
}
|
2013-08-02 13:12:24 -07:00
|
|
|
|
|
|
|
|
2014-11-10 14:45:11 -08:00
|
|
|
bool pushLong (int32_t i);
|
2014-10-30 13:36:39 -06:00
|
|
|
bool pushLongLong (int64_t i);
|
2013-08-02 13:12:24 -07:00
|
|
|
bool pushFloat (float i);
|
2014-11-10 14:45:11 -08:00
|
|
|
int32_t popLong();
|
2013-08-02 13:12:24 -07:00
|
|
|
float popFloat();
|
|
|
|
|
2014-11-10 14:45:11 -08:00
|
|
|
int32_t pad(const char ch, const int32_t len);
|
2013-08-02 13:12:24 -07:00
|
|
|
|
|
|
|
//OPERATORS
|
|
|
|
//copy numbers into the buffer, *in binary*
|
|
|
|
//useful for making lists.
|
|
|
|
bool operator += (uint64_t i);
|
2014-10-30 13:36:39 -06:00
|
|
|
bool operator += (int64_t i);
|
2013-08-02 13:12:24 -07:00
|
|
|
bool operator += (char i);
|
|
|
|
|
|
|
|
bool operator += (uint32_t i);
|
|
|
|
bool operator += (uint16_t i);
|
|
|
|
bool operator += (uint8_t i);
|
|
|
|
|
2016-05-19 18:37:26 +02:00
|
|
|
bool operator += (int32_t i) { return *this += (uint32_t)i; }
|
|
|
|
bool operator += (int16_t i) { return *this += (uint16_t)i; }
|
|
|
|
bool operator += (int8_t i) { return *this += (uint8_t)i; }
|
2013-08-02 13:12:24 -07:00
|
|
|
|
2016-10-03 15:47:32 +02:00
|
|
|
const char& operator[](int32_t i) const;
|
2013-08-02 13:12:24 -07:00
|
|
|
|
2013-12-07 22:12:48 -07:00
|
|
|
public:
|
2014-11-10 14:45:11 -08:00
|
|
|
int32_t m_length;
|
2016-11-07 14:31:54 +01:00
|
|
|
private:
|
2016-11-07 14:38:43 +01:00
|
|
|
int32_t m_capacity;
|
2013-08-02 13:12:24 -07:00
|
|
|
char *m_buf;
|
|
|
|
bool m_usingStack;
|
2016-11-07 14:31:54 +01:00
|
|
|
const char *m_label;
|
2013-08-02 13:12:24 -07:00
|
|
|
};
|
|
|
|
|
2015-06-30 14:09:57 -06:00
|
|
|
|
2017-01-06 12:35:41 +01:00
|
|
|
template<int n>
|
2016-11-03 18:10:30 +01:00
|
|
|
class StackBuf : public SafeBuf {
|
|
|
|
char buf[n];
|
|
|
|
public:
|
|
|
|
StackBuf() : SafeBuf(buf,sizeof(buf)) {}
|
|
|
|
};
|
|
|
|
|
2017-02-15 22:26:41 +01:00
|
|
|
template<int n>
|
|
|
|
class SmallBuf : public SafeBuf {
|
|
|
|
char buf[n];
|
|
|
|
public:
|
|
|
|
SmallBuf(const char *label)
|
|
|
|
: SafeBuf(buf,sizeof(buf))
|
|
|
|
{
|
|
|
|
setLabel(label);
|
|
|
|
}
|
|
|
|
};
|
2015-06-30 14:09:57 -06:00
|
|
|
|
|
|
|
|
2016-03-08 22:14:30 +01:00
|
|
|
#endif // GB_SAFEBUF_H
|