open-source-search-engine/Msg2b.cpp

160 lines
4.4 KiB
C++
Raw Normal View History

2013-08-03 00:12:24 +04:00
#include "gb-include.h"
#include "Msg2b.h"
#include "sort.h"
static char *gCatBuffer;
static int sortSubCats ( const void *c1, const void *c2 );
Msg2b::Msg2b ( ) {
m_subCats = NULL;
m_subCatsSize = 0;
m_numSubCats = 0;
m_catBuffer = NULL;
m_catBufferSize = 0;
m_catBufferLen = 0;
}
Msg2b::~Msg2b ( ) {
// if sizes are 0, we don't own the data
// otherwise free it up
if (m_subCats && m_subCatsSize > 0)
mfree(m_subCats, m_subCatsSize, "Msg2b");
if (m_catBuffer && m_catBufferSize > 0)
mfree(m_catBuffer, m_catBufferSize, "Msg2b");
}
//
// Generate sorted sub categories in m_subCats Array
// m_catBuffer stores sub category names and prefixes
//
2014-11-11 01:45:11 +03:00
bool Msg2b::generateDirectory ( int32_t dirId,
2013-08-03 00:12:24 +04:00
void *state,
void (*callback)(void *state) ) {
m_dirId = dirId;
m_st = state;
m_callback = callback;
// sub categories buffer
m_subCatsSize = MAX_SUB_CATS * sizeof(SubCategory);
m_numSubCats = 0;
m_subCats = (SubCategory*)mmalloc(m_subCatsSize, "Msg2b");
if (!m_subCats) {
2014-11-11 01:45:11 +03:00
log("Msg2b: Could not allocate %"INT32" bytes for m_subCats.",
2013-08-03 00:12:24 +04:00
m_subCatsSize);
g_errno = ENOMEM;
return true;
}
// name buffer
m_catBufferSize = 4096;
m_catBufferLen = 0;
m_catBuffer = (char*)mmalloc(m_catBufferSize, "PageResults");
if (!m_catBuffer) {
2014-11-11 01:45:11 +03:00
log("Msg2b: Could not allocate %"INT32" bytes for m_catBuffer.",
2013-08-03 00:12:24 +04:00
m_catBufferSize);
g_errno = ENOMEM;
return true;
}
// generate the sub categories
m_numSubCats = g_categories->generateSubCats ( m_dirId,
m_subCats,
&m_catBuffer,
&m_catBufferSize,
&m_catBufferLen );
// sort the categories by type and prefix
gCatBuffer = m_catBuffer;
gbsort(m_subCats, m_numSubCats, sizeof(SubCategory), sortSubCats);
return true;
}
// sort categories by type and name
int sortSubCats ( const void *c1, const void *c2 ) {
SubCategory *subCat1 = (SubCategory*)c1;
SubCategory *subCat2 = (SubCategory*)c2;
// check for a type difference of more than 10
if (subCat1->m_type - subCat2->m_type <= -10)
return -1;
else if (subCat1->m_type - subCat2->m_type >= 10)
return 1;
// otherwise compare by prefix
2014-11-11 01:45:11 +03:00
int32_t preLen;
2013-08-03 00:12:24 +04:00
if (subCat1->m_prefixLen < subCat2->m_prefixLen)
preLen = subCat1->m_prefixLen;
else
preLen = subCat2->m_prefixLen;
2014-11-11 01:45:11 +03:00
int32_t preCmp = strncasecmp(&gCatBuffer[subCat1->m_prefixOffset],
2013-08-03 00:12:24 +04:00
&gCatBuffer[subCat2->m_prefixOffset],
preLen);
2014-11-11 01:45:11 +03:00
// if equal, int16_ter is less
2013-08-03 00:12:24 +04:00
if (preCmp == 0)
return (subCat1->m_prefixLen - subCat2->m_prefixLen);
else
return preCmp;
}
//
// Serialize/Deserialize functions
//
2014-11-11 01:45:11 +03:00
int32_t Msg2b::getStoredSize ( ) {
return ( sizeof(int32_t)*3 + // m_dirId + m_numSubCats + m_catBufferLen
2013-08-03 00:12:24 +04:00
sizeof(SubCategory) * m_numSubCats + // sub cats
m_catBufferLen ); // cat buffer
}
2014-11-11 01:45:11 +03:00
int32_t Msg2b::serialize ( char *buf, int32_t bufLen ) {
2013-08-03 00:12:24 +04:00
// make sure we have room
2014-11-11 01:45:11 +03:00
int32_t storedSize = getStoredSize();
2013-08-03 00:12:24 +04:00
if (bufLen < storedSize)
return -1;
char *p = buf;
// m_dirId + m_numSubCats + m_catBufferLen
2014-11-11 01:45:11 +03:00
*(int32_t *)p = m_dirId; p += sizeof(int32_t);
*(int32_t *)p = m_numSubCats; p += sizeof(int32_t);
*(int32_t *)p = m_catBufferLen; p += sizeof(int32_t);
2013-08-03 00:12:24 +04:00
// sub cats
memcpy(p, m_subCats, sizeof(SubCategory)*m_numSubCats);
p += sizeof(SubCategory)*m_numSubCats;
// cat buffer
memcpy(p, m_catBuffer, m_catBufferLen);
p += m_catBufferLen;
// sanity check
if (p - buf != storedSize) {
2014-11-11 01:45:11 +03:00
log("Msg2b: Bad serialize size, %i != %"INT32", bad engineer.",
2013-08-03 00:12:24 +04:00
p - buf, storedSize);
char *xx = NULL; *xx = 0;
}
// return bytes stored
return storedSize;
}
2014-11-11 01:45:11 +03:00
int32_t Msg2b::deserialize ( char *buf, int32_t bufLen ) {
2013-08-03 00:12:24 +04:00
char *p = buf;
2014-11-11 01:45:11 +03:00
if ( bufLen < (int32_t)sizeof(int32_t)*3 )
2013-08-03 00:12:24 +04:00
return -1;
// m_dirId + m_numSubCats + m_catBufferLen
2014-11-11 01:45:11 +03:00
m_dirId = *(int32_t *)p; p += sizeof(int32_t);
m_numSubCats = *(int32_t *)p; p += sizeof(int32_t);
m_catBufferLen = *(int32_t *)p; p += sizeof(int32_t);
if ( bufLen < (int32_t)sizeof(int32_t)*3 +
(int32_t)sizeof(SubCategory)*m_numSubCats +
2013-08-03 00:12:24 +04:00
m_catBufferLen )
return -1;
// sub cats
m_subCatsSize = 0; // this makes sure we don't free it
m_subCats = (SubCategory*)p;
p += sizeof(SubCategory)*m_numSubCats;
// cat buffer
m_catBufferSize = 0; // again, don't free
m_catBuffer = p;
p += m_catBufferLen;
// sanity check
if (p - buf > bufLen) {
log("Msg2b: Overstepped deserialize buffer length, "
2014-11-11 01:45:11 +03:00
"%i > %"INT32", bad engineer.",
2013-08-03 00:12:24 +04:00
p - buf, bufLen);
char *xx = NULL; *xx = 0;
}
// return bytes stored
return p - buf;
}