void handleStatic(staticPage* Sp) { Response& resp(*this->resp); (_staticPage=Sp)->retain(); try { int bufferL = resp.buffer.length(); if(Sp->mime.length()>0)resp.headers["Content-Type"]=Sp->mime; { char* tmps = sp.beginAdd(22); int l = itoa64(Sp->fileLen, tmps); sp.endAdd(l); resp.headers.insert({"Content-Length", { tmps, l }}); StreamWriter sw(resp.buffer); resp.serializeHeaders(sw); } if(Sp->fileLen>=CPPSP_SENDFILE_MIN_SIZE) { _sendFileOffset=0; s.sendAll(resp.buffer.data()+bufferL,resp.buffer.length()-bufferL, MSG_MORE, { &handler::sendHeadersCB, this }); } else { String data=Sp->data; iov[0]= {resp.buffer.data()+bufferL, (size_t)(resp.buffer.length()-bufferL)}; iov[1]= {data.data(), (size_t)data.length()}; resp.outputStream->writevAll(iov, data.length()<=0?1:2, { &handler::writevCB, this }); } } catch(exception& ex) { Sp->release(); server->handleError(req,resp,ex,{&handler::finalize,this}); } }
String urlDecode(const char* in, int inLen, StringPool& sp) { //XXX: dangerous (potentially exploitable) codepath; please audit char* ch = sp.beginAdd(inLen); //output size will never exceed input size int len = doURLDecode(in, inLen, ch); sp.endAdd(len); return {ch,len}; }
TEST(StringPoolTest, SortAndMaintainIndexesInReferences) { StringPool pool; StringPool::Ref ref = pool.makeRef(u"z"); StringPool::StyleRef ref2 = pool.makeRef(StyleString{ {u"a"} }); StringPool::Ref ref3 = pool.makeRef(u"m"); EXPECT_EQ(*ref, u"z"); EXPECT_EQ(0u, ref.getIndex()); EXPECT_EQ(*(ref2->str), u"a"); EXPECT_EQ(1u, ref2.getIndex()); EXPECT_EQ(*ref3, u"m"); EXPECT_EQ(2u, ref3.getIndex()); pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool { return a.value < b.value; }); EXPECT_EQ(*ref, u"z"); EXPECT_EQ(2u, ref.getIndex()); EXPECT_EQ(*(ref2->str), u"a"); EXPECT_EQ(0u, ref2.getIndex()); EXPECT_EQ(*ref3, u"m"); EXPECT_EQ(1u, ref3.getIndex()); }
void _parseFieldList (const char *str, StringPool &props, StringPool &columns) { QS_DEF(Array<char>, prop); QS_DEF(Array<char>, column); BufferScanner scanner(str); props.clear(); columns.clear(); scanner.skipSpace(); while (!scanner.isEOF()) { scanner.readWord(prop, " ,"); scanner.skipSpace(); scanner.readWord(column, " ,"); scanner.skipSpace(); props.add(prop.ptr()); columns.add(column.ptr()); if (scanner.isEOF()) break; if (scanner.readChar() != ',') throw BingoError("_parseFieldList(): comma expected"); scanner.skipSpace(); } }
TEST(StringPoolTest, InsertTwoUniqueStrings) { StringPool pool; StringPool::Ref ref = pool.makeRef(u"wut"); StringPool::Ref ref2 = pool.makeRef(u"hey"); EXPECT_EQ(*ref, u"wut"); EXPECT_EQ(*ref2, u"hey"); }
TEST(StringPoolTest, DoNotInsertNewDuplicateString) { StringPool pool; StringPool::Ref ref = pool.makeRef(u"wut"); StringPool::Ref ref2 = pool.makeRef(u"wut"); EXPECT_EQ(*ref, u"wut"); EXPECT_EQ(*ref2, u"wut"); EXPECT_EQ(1u, pool.size()); }
TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) { StringPool pool; StringPool::Ref ref = pool.makeRef(u"android"); StyleString str { { u"android" } }; StringPool::StyleRef styleRef = pool.makeRef(str); EXPECT_NE(ref.getIndex(), styleRef.getIndex()); }
TEST(StringPoolTest, MaintainInsertionOrderIndex) { StringPool pool; StringPool::Ref ref = pool.makeRef(u"z"); StringPool::Ref ref2 = pool.makeRef(u"a"); StringPool::Ref ref3 = pool.makeRef(u"m"); EXPECT_EQ(0u, ref.getIndex()); EXPECT_EQ(1u, ref2.getIndex()); EXPECT_EQ(2u, ref3.getIndex()); }
void readCB(bool success) { if(unlikely(!success)) { destruct(); return; } //if((sp=thr._stringPoolPool.tryGet())==nullptr) sp=new StringPool(); if((resp=thr._responsePool.tryGet())) resp->init(this->s,&sp); else resp=new Response(this->s,&sp); //keepAlive=true; auto it=req.headers.find("connection"); if(it!=req.headers.end() && (*it).value=="close")keepAlive=false; else keepAlive=true; resp->headers.insert({"Connection", keepAlive?"keep-alive":"close"}); /*char* date=sp.beginAdd(32); tm time; gmtime_r(&thr.curClockTime.tv_sec,&time); int l=rfctime(time,date); if(l>32)l=32; sp.endAdd(l); */ resp->headers.insert({"Date", sp.addString(thr.curRFCTime)}); thr.performanceCounters.totalRequestsReceived++; try { thr.handleRequest(req,*resp,{&handler::finalize,this}); } catch(exception& ex) { thr.handleError(req,*resp,ex,{&handler::finalize,this}); } }
TEST(StringPoolTest, FlattenUtf8) { StringPool pool; StringPool::Ref ref1 = pool.makeRef(u"hello"); StringPool::Ref ref2 = pool.makeRef(u"goodbye"); StringPool::Ref ref3 = pool.makeRef(sLongString); StringPool::StyleRef ref4 = pool.makeRef(StyleString{ { u"style" }, { Span{ { u"b" }, 0, 1 }, Span{ { u"i" }, 2, 3 } } }); EXPECT_EQ(0u, ref1.getIndex()); EXPECT_EQ(1u, ref2.getIndex()); EXPECT_EQ(2u, ref3.getIndex()); EXPECT_EQ(3u, ref4.getIndex()); BigBuffer buffer(1024); StringPool::flattenUtf8(&buffer, pool); std::unique_ptr<uint8_t[]> data = util::copy(buffer); { android::ResStringPool test; ASSERT_EQ(test.setTo(data.get(), buffer.size()), android::NO_ERROR); EXPECT_EQ(util::getString(test, 0), u"hello"); EXPECT_EQ(util::getString(test, 1), u"goodbye"); EXPECT_EQ(util::getString(test, 2), sLongString); EXPECT_EQ(util::getString(test, 3), u"style"); const ResStringPool_span* span = test.styleAt(3); ASSERT_NE(nullptr, span); EXPECT_EQ(util::getString(test, span->name.index), u"b"); EXPECT_EQ(0u, span->firstChar); EXPECT_EQ(1u, span->lastChar); span++; ASSERT_NE(ResStringPool_span::END, span->name.index); EXPECT_EQ(util::getString(test, span->name.index), u"i"); EXPECT_EQ(2u, span->firstChar); EXPECT_EQ(3u, span->lastChar); span++; EXPECT_EQ(ResStringPool_span::END, span->name.index); } }
//deallocate resources after a request has been completed void cleanup() { server->performanceCounters.totalRequestsFinished++; thr.performanceCounters.totalRequestsFinished++; req.reset(); resp->reset(); thr._responsePool.put(resp); resp=nullptr; sp.clear(); }
TEST(StringPoolTest, AddStyles) { StringPool pool; StyleString str { { u"android" }, { Span{ { u"b" }, 2, 6 } } }; StringPool::StyleRef ref = pool.makeRef(str); EXPECT_EQ(0u, ref.getIndex()); EXPECT_EQ(std::u16string(u"android"), *(ref->str)); ASSERT_EQ(1u, ref->spans.size()); const StringPool::Span& span = ref->spans.front(); EXPECT_EQ(*(span.name), u"b"); EXPECT_EQ(2u, span.firstChar); EXPECT_EQ(6u, span.lastChar); }
void handleStatic(staticPage* Sp) { Response& resp(*this->resp); try { String data=Sp->data; int bufferL = resp.buffer.length(); if(Sp->mime.length()>0)resp.headers["Content-Type"]=Sp->mime; { char* tmps = sp.beginAdd(16); int l = itoa(data.length(), tmps); sp.endAdd(l); resp.headers.insert({"Content-Length", { tmps, l }}); StreamWriter sw(resp.buffer); resp.serializeHeaders(sw); } iov[0]= {resp.buffer.data()+bufferL, (size_t)(resp.buffer.length()-bufferL)}; iov[1]= {data.data(), (size_t)data.length()}; resp.outputStream->writevAll(iov, 2, { &handler::writevCB, this }); } catch(exception& ex) { thr.handleError(req,resp,ex,{&handler::finalize,this}); } }
TypeManager::TypeManager(StringPool &strings) : strings_(strings), voidType_(nullptr), implicitVoidType_(nullptr), uncheckedType_(nullptr), metaFunctionType_(nullptr), overloadedFunctionType_(nullptr), primitiveTypes_(), char_type_(nullptr), char_array_(nullptr), const_char_array_(nullptr), float_type_(nullptr), float3_array_(nullptr), const_float3_array_(nullptr) { atom_String_ = strings.add("String"); atom_Float_ = strings.add("Float"); atom_any_ = strings.add("any"); atom_Function_ = strings.add("Function"); atom_bool_ = strings.add("bool"); }
status_t XMLNode::flatten(const sp<AaptFile>& dest, bool stripComments, bool stripRawValues) const { StringPool strings; Vector<uint32_t> resids; // First collect just the strings for attribute names that have a // resource ID assigned to them. This ensures that the resource ID // array is compact, and makes it easier to deal with attribute names // in different namespaces (and thus with different resource IDs). collect_resid_strings(&strings, &resids); // Next collect all remainibng strings. collect_strings(&strings, &resids, stripComments, stripRawValues); #if 0 // No longer compiles NOISY(printf("Found strings:\n"); const size_t N = strings.size(); for (size_t i=0; i<N; i++) { printf("%s\n", String8(strings.entryAt(i).string).string()); } );
TEST(StringPoolTest, PruneStringsWithNoReferences) { StringPool pool; { StringPool::Ref ref = pool.makeRef(u"wut"); EXPECT_EQ(*ref, u"wut"); EXPECT_EQ(1u, pool.size()); } EXPECT_EQ(1u, pool.size()); pool.prune(); EXPECT_EQ(0u, pool.size()); }
void finalize() { thr.performanceCounters.totalRequestsFinished++; if(resp->closed) { destruct(); return; } req.reset(); resp->reset(); thr._responsePool.put(resp); resp=nullptr; sp.clear(); if(keepAlive) { req.init(s,&sp); if(req.readRequest({&handler::readCB,this})) readCB(true); } else { s.shutdown(SHUT_WR); buf=(uint8_t*)malloc(4096); s.repeatRead(buf,4096,{&handler::sockReadCB,this}); } }
TEST(StringPoolTest, SortAndStillDedupe) { StringPool pool; StringPool::Ref ref = pool.makeRef(u"z"); StringPool::Ref ref2 = pool.makeRef(u"a"); StringPool::Ref ref3 = pool.makeRef(u"m"); pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool { return a.value < b.value; }); StringPool::Ref ref4 = pool.makeRef(u"z"); StringPool::Ref ref5 = pool.makeRef(u"a"); StringPool::Ref ref6 = pool.makeRef(u"m"); EXPECT_EQ(ref4.getIndex(), ref.getIndex()); EXPECT_EQ(ref5.getIndex(), ref2.getIndex()); EXPECT_EQ(ref6.getIndex(), ref3.getIndex()); }
static void append_debug_tables(SmxBuilder *builder, StringPool &pool, RefPtr<SmxNameTable> names, SymbolList &nativeList) { // We use a separate name table for historical reasons that are no longer // necessary. In the future we should just alias this to ".names". RefPtr<SmxNameTable> dbgnames = new SmxNameTable(".dbg.strings"); RefPtr<SmxDebugInfoSection> info = new SmxDebugInfoSection(".dbg.info"); RefPtr<SmxDebugLineSection> lines = new SmxDebugLineSection(".dbg.lines"); RefPtr<SmxDebugFileSection> files = new SmxDebugFileSection(".dbg.files"); RefPtr<SmxDebugSymbolsSection> symbols = new SmxDebugSymbolsSection(".dbg.symbols"); RefPtr<SmxDebugNativesSection> natives = new SmxDebugNativesSection(".dbg.natives"); RefPtr<SmxTagSection> tags = new SmxTagSection(".tags"); stringlist *dbgstrs = get_dbgstrings(); // State for tracking which file we're on. We replicate the original AMXDBG // behavior here which excludes duplicate addresses. ucell prev_file_addr = 0; const char *prev_file_name = nullptr; // Add debug data. for (stringlist *iter = dbgstrs; iter; iter = iter->next) { if (iter->line[0] == '\0') continue; DebugString str(iter->line); switch (str.kind()) { case 'F': { ucell codeidx = str.parse(); if (codeidx != prev_file_addr) { if (prev_file_name) { sp_fdbg_file_t &entry = files->add(); entry.addr = prev_file_addr; entry.name = dbgnames->add(pool, prev_file_name); } prev_file_addr = codeidx; } prev_file_name = str.skipspaces(); break; } case 'L': { sp_fdbg_line_t &entry = lines->add(); entry.addr = str.parse(); entry.line = str.parse(); break; } case 'S': { sp_fdbg_symbol_t sym; sp_fdbg_arraydim_t dims[sDIMEN_MAX]; sym.addr = str.parse(); sym.tagid = str.parse(); str.skipspaces(); str.expect(':'); char *name = str.skipspaces(); char *nameend = str.skipto(' '); Atom *atom = pool.add(name, nameend - name); sym.codestart = str.parse(); sym.codeend = str.parse(); sym.ident = (char)str.parse(); sym.vclass = (char)str.parse(); sym.dimcount = 0; sym.name = dbgnames->add(atom); info->header().num_syms++; str.skipspaces(); if (str.getc() == '[') { info->header().num_arrays++; for (char *ptr = str.skipspaces(); *ptr != ']'; ptr = str.skipspaces()) { dims[sym.dimcount].tagid = str.parse(); str.skipspaces(); str.expect(':'); dims[sym.dimcount].size = str.parse(); sym.dimcount++; } } symbols->add(&sym, sizeof(sym)); symbols->add(dims, sizeof(dims[0]) * sym.dimcount); break; } } } // Add the last file. if (prev_file_name) { sp_fdbg_file_t &entry = files->add(); entry.addr = prev_file_addr; entry.name = dbgnames->add(pool, prev_file_name); } // Build the tags table. for (constvalue *constptr = tagname_tab.next; constptr; constptr = constptr->next) { assert(strlen(constptr->name)>0); sp_file_tag_t &tag = tags->add(); tag.tag_id = constptr->value; tag.name = names->add(pool, constptr->name); } // Finish up debug header statistics. info->header().num_files = files->count(); info->header().num_lines = lines->count(); // Write natives. sp_fdbg_ntvtab_t natives_header; natives_header.num_entries = nativeList.length(); natives->add(&natives_header, sizeof(natives_header)); for (size_t i = 0; i < nativeList.length(); i++) { symbol *sym = nativeList[i]; sp_fdbg_native_t info; info.index = i; info.name = dbgnames->add(pool, sym->name); info.tagid = sym->tag; info.nargs = 0; for (arginfo *arg = sym->dim.arglist; arg->ident; arg++) info.nargs++; natives->add(&info, sizeof(info)); for (arginfo *arg = sym->dim.arglist; arg->ident; arg++) { sp_fdbg_ntvarg_t argout; argout.ident = arg->ident; argout.tagid = arg->tag; argout.dimcount = arg->numdim; argout.name = dbgnames->add(pool, arg->name); natives->add(&argout, sizeof(argout)); for (int j = 0; j < argout.dimcount; j++) { sp_fdbg_arraydim_t dim; dim.tagid = arg->idxtag[j]; dim.size = arg->dim[j]; natives->add(&dim, sizeof(dim)); } } } // Add these in the same order SourceMod 1.6 added them. builder->add(files); builder->add(symbols); builder->add(lines); builder->add(natives); builder->add(dbgnames); builder->add(info); builder->add(tags); }
TEST(StringPoolTest, InsertOneString) { StringPool pool; StringPool::Ref ref = pool.makeRef(u"wut"); EXPECT_EQ(*ref, u"wut"); }
String combinePathChroot(String p1, String p2, StringPool& sp) { char* tmp = sp.beginAdd(p1.length() + p2.length()); int l = combinePathChroot(p1.data(), p2.data(), tmp); sp.endAdd(l); return {tmp,l}; }
static void PatriciaNode::ragnarok() //---------------------------------- { _nodePool.ragnarok(); _stringPool.ragnarok(); }
int VirtualMachine::runFile(ByteCodeFileReader& reader){ int header = reader.readHeader(); if(header != ('E' + 'D' + 'D' + 'I')){ cout << "Not an EDDI compiled file" << endl; return 1; } StringPool pool; int strings = reader.readInt(); cout << "String pool size = " << strings << endl; for(int i = 0; i < strings; i++){ int index = reader.readInt(); string value = reader.readLitteral(); pool.add(index, value); } vector<Instruction> instructions; int current = 0; map<int, int> branches; while(reader.hasMore()){ ByteCode bytecode = reader.readByteCode(); if(bytecode == LABEL){ int branche = reader.readInt(); branches[branche] = current; } else { Instruction instruction; instruction.bytecode = bytecode; if(instruction.bytecode > LABEL && instruction.bytecode <= JUMP_IF_NOT){ instruction.operand = reader.readInt(); } instructions.push_back(instruction); ++current; } } Stack stack; Variables variables; int programCounter = 0; while(true){ Instruction instruction = instructions[programCounter]; ByteCode bytecode = instruction.bytecode; programCounter++; switch(bytecode){ case LDCS: case LDCI: stack.push(instruction.operand); break; case PRINTI: cout << stack.pop() << endl; break; case PRINTS: cout << pool.get(stack.pop()) << endl; break; case SSTORE: case ISTORE:{ unsigned int variable = (unsigned int) instruction.operand; variables.assign(variable, stack.pop()); break; } case SLOAD: case ILOAD:{ unsigned int variable = (unsigned int) instruction.operand; stack.push(variables.get(variable)); break; } case IADD:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs + rhs); break; } case ISUB:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs - rhs); break; } case IMUL:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs * rhs); break; } case IDIV:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs / rhs); break; } case IMOD:{ int rhs = stack.pop(); int lhs = stack.pop(); stack.push(lhs % rhs); break; } case SADD:{ string rhs = pool.get(stack.pop()); string lhs = pool.get(stack.pop()); int index = pool.addNew(lhs + rhs); stack.push(index); break; } case JUMP: { programCounter = branches[instruction.operand]; break; } case JUMP_IF: { int result = stack.pop(); if(result == 1){ programCounter = branches[instruction.operand]; } break; } case JUMP_IF_NOT: { int result = stack.pop(); if(result == 0){ programCounter = branches[instruction.operand]; } break; } case EQUALS: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs == rhs){ stack.push(1); } else { stack.push(0); } break; } case NOT_EQUALS: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs != rhs){ stack.push(1); } else { stack.push(0); } break; } case GREATER_THAN: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs > rhs){ stack.push(1); } else { stack.push(0); } break; } case LESS_THAN: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs < rhs){ stack.push(1); } else { stack.push(0); } break; } case GREATER_THAN_EQUALS: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs >= rhs){ stack.push(1); } else { stack.push(0); } break; } case LESS_THAN_EQUALS: { int rhs = stack.pop(); int lhs = stack.pop(); if(lhs <= rhs){ stack.push(1); } else { stack.push(0); } break; } case END: return 0; } } return 1; }
int main() { StringPool Test; Test.GetId("kvala"); Test.GetId("doom"); Test.GetId("k"); Test.GetId("do"); Test.GetId("fffv"); Test.GetId("fbfdgf"); Test.GetId("dsdfd"); Test.GetId("dosdcd"); Test.GetId("kvfddfdf"); Test.GetId("dfsf"); cout << Test.GetWord(Test.GetId("dsdfd")) << endl; return 0; }