diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..7ba89ec Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index f8faee3..599af29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ data/ cmake-build-debug/ cmake-build-release/ +archive/ +archiveSmall/ +rapidjson/ +TestingDataSet/ .idea/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index aa927f8..c53f12e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,10 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.16.0) project(22s_final_proj) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) + + + +add_executable( 22s_final_proj main.cpp catch_setup.cpp DSAvlTree.h parsingData.cpp parsingData.h wordObject.cpp wordObject.h stemmerGiveUp.h HashTable.h vectorHelper.cpp vectorHelper.h DSDocument.cpp DSDocument.h) + -add_executable(22s_final_proj main.cpp catch_setup.cpp) diff --git a/DSAvlTree.h b/DSAvlTree.h new file mode 100644 index 0000000..e1fc6c3 --- /dev/null +++ b/DSAvlTree.h @@ -0,0 +1,190 @@ +// +// Created by willk on 4/10/2022. +// + +//using code from https://www.programiz.com/dsa/avl-tree + +#ifndef INC_22S_FINAL_PROJ_DSAVLTREE_H +#define INC_22S_FINAL_PROJ_DSAVLTREE_H + +template +struct DSNode { +int height = 0; +DSNode* left = nullptr; +DSNode* right = nullptr; +type data; + +DSNode(type input, DSNode* l, DSNode* r, int h) { + data = input; + left = l; + right = r; + height = h; +} + +DSNode(type d) { + data = d; + left = nullptr; + right = nullptr; + height = 0; +} + + + +}; + +template +class DSTree { + +public: + DSNode* head = nullptr; + int height(DSNode* input) { + if(input == nullptr) + return -1; + return input->height; + } + int getBalance(DSNode* input) { + if(input == nullptr) { + return 0; + } + return (height(input->left) - height(input->right)); + } + + DSNode* findValue(type input) { + return findValue(input, head); + } + + DSNode* findValue(type input, DSNode* head) { + + if(head == nullptr) { + return nullptr; + } + if(head->data == input) { + return head; + } + else if(head->data < input) { + return findValue(input, head->right); + } + else { + return findValue(input, head->left); + } + } + + DSNode* leftLeftRotate(DSNode* input) { + DSNode* leftChild = input->left; + input->right = leftChild->left; + + //input->right = rightChild->left; + //rightChild->left = input; + + } + DSNode* insert(type x) { + return insert(x, head); + + } + DSNode* insert(type& x, DSNode * & top) { + if(top == nullptr) { + top = new DSNode(x); + + + } + else if (x < top->data) + insert(x,top->left); + else if (top->data < x) + insert(x, top->right); + else + { + //do stuff for duplicate + } + balance(top); + + return top; + + } + + int max(int a, int b) { + return (a > b) ? a : b; + } + + void rotateWithLeftChild(DSNode* & k2) { + DSNode* k1 = k2->left; + k2->left = k1->right; + k1->right = k2; + k2->height = max(height(k2->left), height(k2->right)) + 1; + k1->height = max(height(k1->left), k2->height) +1; + k2 = k1; + //not done yet??? + + } + void rotateWithRightChild(DSNode* & k2) { + DSNode* k1 = k2->right; + k2->right = k1->left; + k1->left = k2; + k2->height = max(height(k2->left), height(k2->right))+1; + k1->height = max(height(k1->right), k2->height) + 1; + k2 = k1; + } + + void doubleWithLeftChild( DSNode * & k3 ) + { + rotateWithRightChild( k3->left ); + rotateWithLeftChild( k3 ); + } + + void doubleWithRightChild(DSNode * & k3) { + rotateWithLeftChild( k3->right ); + rotateWithRightChild( k3 ); + } + + void balance(DSNode* & t) { + if(t == nullptr) { + return; + } + if( height( t->left ) - height( t->right ) > 1) { + if(height(t->left->left) >= height(t->left->right)){ + rotateWithLeftChild(t); + } + else { + doubleWithLeftChild(t); + } + } + else if(height( t->right ) - height( t->left ) > 1) { + if(height(t->right->right) >= height(t->right->left)) { + rotateWithRightChild(t); + } + else { + doubleWithRightChild(t); + } + } + t->height = max(height(t->left), height(t->right)) + 1; + } + + ~DSTree() { + recursiveDelete(head); + } + + void recursiveDelete(DSNode* input) { + if(input != nullptr) { + recursiveDelete(input->left); + recursiveDelete(input->right); + delete input; + } + } + vector toVector() { + vector outVector; + recursiveVector(head, &outVector); + return outVector; + + } + + void recursiveVector(DSNode* input, vector* v) { + if(input != nullptr) { + recursiveVector(input->left, v); + recursiveVector(input->right, v); + v->push_back(input->data); + } + } + + +}; + +#endif //INC_22S_FINAL_PROJ_DSAVLTREE_H diff --git a/DSDocument.cpp b/DSDocument.cpp new file mode 100644 index 0000000..4269e5a --- /dev/null +++ b/DSDocument.cpp @@ -0,0 +1,5 @@ +// +// Created by willk on 5/3/2022. +// + +#include "DSDocument.h" diff --git a/DSDocument.h b/DSDocument.h new file mode 100644 index 0000000..1435087 --- /dev/null +++ b/DSDocument.h @@ -0,0 +1,47 @@ +// +// Created by willk on 5/3/2022. +// +#ifndef string +#include +#include +#include "vector" + +#endif + +#ifndef INC_22S_FINAL_PROJ_DSDOCUMENT_H +#define INC_22S_FINAL_PROJ_DSDOCUMENT_H + + + + +class DSDocument { +public: + std::string ID; + std::string text; + bool operator<(const DSDocument& input) const { + return ID putWordsInVec(std::string allWords){ + std::string test = ""; + std::vector v; + for(int i = 0; i>> table[10000]; +// +// +// +//}; + +#include +#include + +using namespace std; + +class HashTable{ +private: + list>>* table; + double tableSize; + int total_elements; + float max_load_factor; + + // Hash function to calculate hash for a value: + int hash(string key) { + std::hash hashString; + int hashed_key = hashString(key); + return abs(hashed_key % (int)total_elements); + } + +public: + // Constructor to create a hash table with 'n' indices: + HashTable(){ + max_load_factor = 0.7; + total_elements = 500; + tableSize = 0; + table = new list>>[total_elements]; + + + } + + // Insert data in the hash table: + void insertElement(string key, vector value){ + pair> temp; + temp.first = key; + temp.second = value; + int hashKey = hash(key); + if(table[hashKey].empty()) { + tableSize++; + } + table[hashKey].push_back(temp); + + + if(tableSize/((double)total_elements) > max_load_factor){ + tableSize = 0; + + list>>* tmpTable; + + + + tmpTable = table; + + total_elements = total_elements * 3; + table = new list>>[total_elements]; + + list>>* oldList; + int hashNum = hash(key); + for(int i = 0; i < total_elements/3; i++){ + oldList = &tmpTable[i]; + + while(!oldList->empty()) { + insertElement(oldList->front().first,oldList->front().second); + oldList->remove(oldList->front()); + } + } + delete[] tmpTable; + + + } + } + + vector find(string key){ + list>> tmpList; + int hashNum = hash(key); + tmpList = table[hashNum]; + while(!tmpList.empty()) { + if(tmpList.front().first==key) { + return tmpList.front().second; + } + tmpList.remove(tmpList.front()); + } + vector empty; + return empty; + } + ///DO NOT USE THIS THING IS BAD! + vector* findPoint(string key) { + list>> tmpList; + int hashNum = hash(key); + tmpList = table[hashNum]; + while(!tmpList.empty()) { + if(tmpList.front().first==key) { + return &tmpList.front().second; + } + tmpList.remove(tmpList.front()); + } + return nullptr; + } + void appendID(string key, string ID) { + int hashNum = hash(key); + std::list>>::iterator it; + for(it = table[hashNum].begin(); it != table[hashNum].end(); it++) { + if(it->first == key) { + it->second.push_back(ID); + } + } + } + + ~HashTable() { + delete[] table; + } + + + + + + // Remove data from the hash table: +// void remove(string key){ +// auto it = find(key); +// if(it != table[hash(key)].end()){ +// table[hash(key)].erase(it); +// total_elements--; +// } +// } + +}; + + + +#endif //INC_22S_FINAL_PROJ_HASHTABLE_H diff --git a/diffs.txt b/diffs.txt new file mode 100644 index 0000000..4988240 --- /dev/null +++ b/diffs.txt @@ -0,0 +1,29418 @@ +' ' +'' '' +'a 'a +'s 's +'aa aa +'as as +''' ' +'a' a +'s' s +'aa' aa +'as' as +a a +a' a' +a'' a' +aa' aa +aback aback +abandon abandon +abandoned abandon +abandoning abandon +abandonment abandon +abandons abandon +abasement abas +abashed abash +abate abat +abated abat +abbey abbey +abbott abbott +abbreviation abbrevi +abdicate abdic +abdicating abdic +abdomen abdomen +abdominal abdomin +abe abe +abear abear +abed abe +abel abel +aberration aberr +abershaw abershaw +abet abet +abettor abettor +abeyance abey +abhorred abhor +abhorrence abhorr +abhorring abhor +abide abid +abiding abid +abilities abil +ability abil +abimee abime +abingdon abingdon +abipones abipon +abject abject +abjectly abject +abjectness abject +abjure abjur +abjured abjur +abl abl +able abl +ablutions ablut +abnegation abneg +abnormal abnorm +abnormality abnorm +abnormally abnorm +aboard aboard +abode abod +abodes abod +abolish abolish +abolished abolish +abolishing abolish +abolition abolit +abominable abomin +abominably abomin +abominated abomin +abomination abomin +aboot aboot +aboriginal aborigin +aboriginally aborigin +aborigines aborigin +abortion abort +abortions abort +abortive abort +abound abound +abounded abound +abounding abound +abounds abound +about about +above abov +aboveboard aboveboard +abraham abraham +abreast abreast +abridge abridg +abridged abridg +abroad abroad +abrogated abrog +abrolhos abrolho +abrupt abrupt +abruptly abrupt +abruptness abrupt +abscess abscess +absence absenc +absent absent +absenting absent +absolute absolut +absolutely absolut +absolve absolv +absolved absolv +absorb absorb +absorbed absorb +absorbent absorb +absorbing absorb +absorbs absorb +absorption absorpt +abstain abstain +abstained abstain +abstaining abstain +abstinence abstin +abstract abstract +abstracted abstract +abstractedly abstract +abstraction abstract +abstracts abstract +abstruse abstrus +absurd absurd +absurdities absurd +absurdity absurd +absurdly absurd +abt abt +abundance abund +abundant abund +abundantly abund +abuse abus +abused abus +abuses abus +abusing abus +abusive abus +abut abut +abuts abut +abutting abut +abyss abyss +abysses abyss +abyssinia abyssinia +ac ac +acacia acacia +acacias acacia +academy academi +acalypha acalypha +acapulco acapulco +accede acced +acceded acced +accedes acced +accelerate acceler +accelerated acceler +accent accent +accents accent +accept accept +acceptable accept +acceptance accept +acceptances accept +acceptation accept +accepted accept +accepting accept +accepts accept +access access +accessible access +accession access +accessories accessori +accessory accessori +accident accid +accidental accident +accidentally accident +accidents accid +acclamations acclam +acclivity accliv +accommodate accommod +accommodated accommod +accommodating accommod +accommodation accommod +accommodations accommod +accompanied accompani +accompanies accompani +accompaniment accompani +accompaniments accompani +accompany accompani +accompanying accompani +accomplice accomplic +accomplices accomplic +accomplish accomplish +accomplished accomplish +accomplishes accomplish +accomplishing accomplish +accomplishment accomplish +accomplishments accomplish +accord accord +accordance accord +accorded accord +according accord +accordingly accord +accosted accost +accosting accost +accoun accoun +account account +accountabilities account +accountability account +accountable account +accountant account +accounted account +accounting account +accounts account +accoutred accoutr +accoutrements accoutr +accredited accredit +accrue accru +accrued accru +accruing accru +accumulate accumul +accumulated accumul +accumulating accumul +accumulation accumul +accumulations accumul +accuracy accuraci +accurate accur +accurately accur +accursed accurs +accusation accus +accusations accus +accuse accus +accused accus +accuser accus +accusers accus +accuses accus +accusing accus +accustom accustom +accustomed accustom +accustoming accustom +ace ace +acerbity acerb +aces ace +ach ach +ache ach +ached ach +aches ach +achieve achiev +achieved achiev +achievement achiev +achievements achiev +achieves achiev +achieving achiev +achilles achill +aching ach +acid acid +acids acid +ack ack +ackney ackney +acknowledge acknowledg +acknowledged acknowledg +acknowledgement acknowledg +acknowledges acknowledg +acknowledging acknowledg +acknowledgment acknowledg +acknowledgments acknowledg +aconcagua aconcagua +acorn acorn +acquaint acquaint +acquaintance acquaint +acquaintances acquaint +acquainted acquaint +acquainting acquaint +acquaints acquaint +acquiesce acquiesc +acquiesced acquiesc +acquiescence acquiesc +acquiescent acquiesc +acquiesces acquiesc +acquiescing acquiesc +acquire acquir +acquired acquir +acquirement acquir +acquirements acquir +acquires acquir +acquiring acquir +acquisition acquisit +acquit acquit +acquittal acquitt +acquitted acquit +acqulred acqulr +acre acr +acres acr +acrid acrid +acrimonious acrimoni +acrimoniously acrimoni +across across +acrydium acrydium +act act +acted act +acting act +actinia actinia +action action +actions action +active activ +actively activ +activity activ +actor actor +actors actor +actress actress +actresses actress +acts act +actual actual +actuality actual +actually actual +actuate actuat +actuated actuat +actuating actuat +acumen acumen +acunha acunha +acut acut +acute acut +acutely acut +acuteness acut +acuter acut +ad ad +ada ada +adage adag +adages adag +adam adam +adamant adam +adams adam +adapt adapt +adaptability adapt +adaptable adapt +adaptation adapt +adapted adapt +adapter adapt +adapting adapt +adapts adapt +adas ada +add add +added ad +adder adder +addicted addict +adding ad +addition addit +additional addit +additionally addit +additions addit +addled addl +address address +addressed address +addresses address +addressing address +adds add +adduced adduc +adducing adduc +adequate adequ +adhere adher +adhered adher +adherence adher +adherent adher +adherents adher +adheres adher +adhering adher +adhesive adhes +adieu adieu +adieux adieux +adimonia adimonia +adios adio +adjacent adjac +adjective adject +adjoined adjoin +adjoining adjoin +adjourned adjourn +adjournment adjourn +adjuration adjur +adjurations adjur +adjured adjur +adjuring adjur +adjust adjust +adjusted adjust +adjusting adjust +adjustment adjust +adjusts adjust +adjutant adjut +administer administ +administered administ +administering administ +administration administr +administrative administr +administrator administr +administrators administr +admirable admir +admirably admir +admiral admir +admiralty admiralti +admiration admir +admire admir +admired admir +admirer admir +admirers admir +admires admir +admiring admir +admiringly admir +admission admiss +admissions admiss +admit admit +admits admit +admittance admitt +admitted admit +admitting admit +admixture admixtur +admonished admonish +admonishes admonish +admonishing admonish +admonition admonit +admonitions admonit +admonitory admonitori +adn adn +ado ado +adopt adopt +adopted adopt +adopting adopt +adoption adopt +adoration ador +adorations ador +adore ador +adored ador +adores ador +adoring ador +adorned adorn +adorning adorn +adornment adorn +adornments adorn +adorns adorn +adrianople adrianopl +adrift adrift +adroit adroit +adulation adul +adulatory adulatori +adult adult +adultery adulteri +advance advanc +advanced advanc +advancement advanc +advances advanc +advancing advanc +advantage advantag +advantageous advantag +advantageously advantag +advantages advantag +advent advent +adventure adventur +adventurer adventur +adventurers adventur +adventures adventur +adventuresses adventuress +adventurous adventur +adventurously adventur +adversaries adversari +adversary adversari +adverse advers +adversity advers +advert advert +adverted advert +adverting advert +advertise advertis +advertised advertis +advertisement advertis +advertisements advertis +advertiser advertis +advertising advertis +advice advic +advisability advis +advisable advis +advise advis +advised advis +advisedly advis +adviser advis +advises advis +advising advis +advocacy advocaci +advocate advoc +advocated advoc +advocating advoc +adwiser adwis +aeqam aeqam +aerial aerial +aeriform aeriform +aeronaut aeronaut +aeronautics aeronaut +aery aeri +aeschylus aeschylus +aesop aesop +aesthetic aesthet +aesthetically aesthet +aesthetics aesthet +aestivation aestiv +afanasy afanasi +afanasyvitch afanasyvitch +afar afar +afeard afeard +afeared afear +afer afer +affability affabl +affable affabl +affably affabl +affair affair +affairs affair +affect affect +affectation affect +affected affect +affectedly affect +affecting affect +affection affect +affectionate affection +affectionately affection +affections affect +affects affect +afferdavid afferdavid +affidavit affidavit +affidavits affidavit +affinity affin +affirm affirm +affirmative affirm +affirmed affirm +affirms affirm +afflict afflict +afflicted afflict +afflicting afflict +affliction afflict +afflictions afflict +affluence affluenc +affluent affluent +afford afford +afforded afford +affording afford +affords afford +affright affright +affrighted affright +affront affront +affronted affront +afield afield +aflicto aflicto +afloat afloat +afoot afoot +afore afor +aforementioned aforement +aforesaid aforesaid +afraid afraid +afresh afresh +africa africa +african african +afrique afriqu +afrosinya afrosinya +afsd afsd +aft aft +after after +afternoon afternoon +afternoons afternoon +afterthought afterthought +afterwards afterward +agai agai +again again +against against +agate agat +agave agav +agaves agav +age age +agean agean +aged age +agency agenc +agent agent +agents agent +agers ager +ages age +aggeravating aggerav +agglomeration agglomer +agglutinated agglutin +aggrandizement aggrandiz +aggravate aggrav +aggravated aggrav +aggravates aggrav +aggravating aggrav +aggravation aggrav +aggravations aggrav +aggregate aggreg +aggregated aggreg +aggression aggress +aggressor aggressor +aggrieved aggriev +aghast aghast +agility agil +agin agin +agitate agit +agitated agit +agitating agit +agitation agit +agitators agit +aglow aglow +agnes agn +ago ago +agonies agoni +agonised agonis +agonising agonis +agonisingly agonis +agonizing agon +agony agoni +agouti agouti +agoutis agouti +agrarian agrarian +agree agre +agreeable agreeabl +agreeably agreeabl +agreed agre +agreeing agre +agreement agreement +agrees agre +agricult agricult +agricultural agricultur +agriculture agricultur +agriculturists agriculturist +aground aground +agua agua +ague agu +agueros aguero +ah ah +aha aha +ahead ahead +ai ai +aid aid +aided aid +aider aider +aiding aid +aids aid +aie aie +ailing ail +ailment ailment +ailments ailment +ails ail +aim aim +aimed aim +aiming aim +aimless aimless +aimlessly aimless +aims aim +ain ain +air air +aired air +airily airili +airing air +airlessness airless +airnest airnest +airs air +airy airi +aisle aisl +aits ait +ajar ajar +ajax ajax +akad akad +ake ake +akeady akeadi +akimbo akimbo +akin akin +al al +alabaster alabast +alacrity alacr +alameda alameda +alarm alarm +alarmed alarm +alarming alarm +alarmingly alarm +alarms alarm +alas ala +alba alba +albania albania +albanians albanian +albans alban +albatross albatross +albeit albeit +albemarle albemarl +albert albert +albertine albertin +albiceps albicep +albicollis albicolli +albicores albicor +albino albino +albion albion +album album +albuminous albumin +albury alburi +alcicornis alcicorni +alcide alcid +alcohol alcohol +alder alder +alderman alderman +aldershot aldershot +aldgate aldgat +ale ale +alehouse alehous +alehouses alehous +aleide aleid +alerce alerc +alert alert +alexander alexand +alexandr alexandr +alexandrovna alexandrovna +alexey alexey +alfalfa alfalfa +alfonso alfonso +alford alford +alfred alfr +algarroba algarroba +algebra algebra +alice alic +alienated alien +alight alight +alighted alight +alighting alight +alights alight +alike alik +alive aliv +all all +allah allah +allan allan +allay allay +allayed allay +allays allay +allegation alleg +allegations alleg +alleged alleg +allegiance allegi +alleging alleg +allegorical allegor +allegories allegori +allegory allegori +allenby allenbi +aller aller +alleviate allevi +alleviated allevi +alley alley +alleys alley +alliance allianc +alliances allianc +allied alli +allies alli +alligators allig +allotted allot +allotting allot +allow allow +allowable allow +allowance allow +allowances allow +allowed allow +allowing allow +allows allow +alloyed alloy +allude allud +alluded allud +alludes allud +alluding allud +allure allur +allured allur +allurement allur +allurements allur +alluring allur +allus allus +allusion allus +allusions allus +alluvial alluvi +alluvium alluvium +ally alli +alma alma +almac almac +almanac almanac +almanacs almanac +almighty almighti +almos almo +almost almost +alms alm +almshouses almshous +aloe alo +aloft aloft +alone alon +along along +alongside alongsid +aloof aloof +aloud aloud +alphabet alphabet +alphabets alphabet +alphonse alphons +alpine alpin +alps alp +already alreadi +also also +alta alta +altar altar +altars altar +alter alter +alteration alter +alterations alter +altercation alterc +altered alter +altering alter +alternate altern +alternately altern +alternating altern +alternation altern +alternations altern +alternative altern +alternatives altern +alters alter +althoug althoug +although although +altisidora altisidora +altitude altitud +alto alto +altogether altogeth +alured alur +alway alway +always alway +alyona alyona +alyoshka alyoshka +am am +ama ama +amalgamate amalgam +amalgamated amalgam +amalgamation amalgam +amalia amalia +amancaes amanca +amang amang +amanuensis amanuensi +amarga amarga +amass amass +amassed amass +amassing amass +amateur amateur +amaze amaz +amazed amaz +amazedly amaz +amazement amaz +amazes amaz +amazing amaz +amazingly amaz +ambassadors ambassador +ambassadress ambassadress +amber amber +ambient ambient +ambiguous ambigu +ambition ambit +ambitious ambiti +amble ambl +ambling ambl +amblyrhynchus amblyrhynchus +ambox ambox +ambuscade ambuscad +ambush ambush +amd amd +amelioration amelior +amen amen +amenable amen +amend amend +amended amend +amendment amend +amendments amend +amends amend +america america +american american +americana americana +americans american +americas america +amerique ameriqu +amethysts amethyst +ami ami +amiabilities amiabl +amiability amiabl +amiable amiabl +amiably amiabl +amicability amic +amicable amic +amicably amic +amid amid +amidst amidst +amiss amiss +amity amiti +ammunition ammunit +amn amn +amoncelees amoncele +among among +amongst amongst +amorites amorit +amorous amor +amost amost +amount amount +amounted amount +amounting amount +amounts amount +amphibious amphibi +amphitheatre amphitheatr +amphitheatrical amphitheatr +ample ampl +amply ampli +ampullariae ampullaria +amputated amput +amputation amput +amuse amus +amused amus +amusement amus +amusements amus +amuses amus +amusing amus +an an +ana ana +anadeers anad +anaemic anaem +analogies analog +analogous analog +analogue analogu +analogy analog +analyse analys +analysed analys +analysing analys +analysis analysi +analyze analyz +analyzed analyz +anarchy anarchi +anas ana +anastasia anastasia +anat anat +anathematising anathematis +anathematizing anathemat +anatolia anatolia +anatomical anatom +anatomists anatomist +anatomy anatomi +ancestor ancestor +ancestors ancestor +ancestral ancestr +ancestress ancestress +ancestry ancestri +anchor anchor +anchorage anchorag +anchored anchor +anchoring anchor +anchors anchor +anchovies anchovi +ancient ancient +anciently ancient +ancients ancient +and and +andalusia andalusia +ande and +andes andes +andle andl +andled andl +andrew andrew +andrews andrew +andrey andrey +anecdote anecdot +anecdotes anecdot +anemone anemon +anew anew +angel angel +angela angela +angelic angel +angelica angelica +angels angel +anger anger +angered anger +angerless angerless +angers anger +angle angl +angler angler +angles angl +anglican anglican +anglicanism anglican +anglified anglifi +angriest angriest +angrily angrili +angry angri +anguish anguish +angula angula +angular angular +anima anima +animadvert animadvert +animal anim +animalcula animalcula +animalcule animalcul +animalized anim +animals anim +animas anima +animate anim +animated anim +animates anim +animating anim +animation anim +animosity animos +aniska aniska +ankle ankl +ankles ankl +ann ann +anna anna +annal annal +annales annal +annals annal +anne ann +annelidous annelid +annette annett +annewum annewum +annexed annex +annie anni +annihilate annihil +annihilated annihil +annihilation annihil +anniversaries anniversari +anniversary anniversari +annoucing annouc +announce announc +announced announc +announcement announc +announcements announc +announces announc +announcing announc +annoy annoy +annoyance annoy +annoyances annoy +annoyed annoy +annoying annoy +annoys annoy +annual annual +annually annual +annuals annual +annuelle annuell +annuity annuiti +annul annul +annum annum +anomalies anomali +anomalous anomal +anomaly anomali +anon anon +anonymous anonym +anoother anooth +another anoth +anson anson +anstice anstic +answer answer +answerable answer +answered answer +answering answer +answers answer +ant ant +antagonism antagon +antagonist antagonist +antagonistic antagonist +antarctic antarct +antarctica antarctica +antarcticus antarcticus +anteater anteat +antecedent anteced +antecedents anteced +antechamber antechamb +antechambers antechamb +antediluvian antediluvian +antelope antelop +antelopes antelop +antennae antenna +antennatus antennatus +anterior anterior +anthem anthem +anthony anthoni +anthus anthus +anti anti +anticipate anticip +anticipated anticip +anticipates anticip +anticipating anticip +anticipation anticip +anticipations anticip +anticipative anticip +antics antic +antilles antill +antipodean antipodean +antipodes antipod +antiquarian antiquarian +antiquaries antiquari +antiquated antiqu +antiques antiqu +antiquities antiqu +antiquity antiqu +antlers antler +antonio antonio +antony antoni +antrum antrum +ants ant +antuco antuco +anxieties anxieti +anxiety anxieti +anxious anxious +anxiously anxious +any ani +anybody anybodi +anyhow anyhow +anymore anymor +anyone anyon +anything anyth +anythink anythink +anyvays anyvay +anyway anyway +anyways anyway +anywhere anywher +anywheres anywher +ap ap +apace apac +apar apar +apart apart +apartment apart +apartments apart +apate apat +apathy apathi +ape ape +apennines apennin +aperient aperi +aperture apertur +apertures apertur +apex apex +aphodius aphodius +apiece apiec +apire apir +apires apir +aplysia aplysia +apollinaris apollinari +apollo apollo +apologetic apologet +apologetically apologet +apologies apolog +apologise apologis +apologised apologis +apologising apologis +apologists apologist +apologize apolog +apologized apolog +apologizes apolog +apologizing apolog +apology apolog +apoplectic apoplect +apoplexy apoplexi +apostle apostl +apostles apostl +apostolica apostolica +apostrophe apostroph +apostrophised apostrophis +apostrophized apostroph +apostrophizing apostroph +apothecaries apothecari +apothecary apothecari +appalled appal +appalling appal +appallingly appal +appanage appanag +apparatus apparatus +apparel apparel +apparent appar +apparently appar +apparition apparit +apparitions apparit +appea appea +appeal appeal +appealed appeal +appealing appeal +appealingly appeal +appeals appeal +appear appear +appearance appear +appearances appear +appeared appear +appearing appear +appears appear +appease appeas +appeased appeas +appellation appel +append append +appendage appendag +appendages appendag +appended append +appendix appendix +appertained appertain +appertaining appertain +apperton apperton +appetite appetit +appetites appetit +appiness appi +applauded applaud +applauding applaud +applause applaus +apple appl +apples appl +appliances applianc +applicable applic +applicant applic +application applic +applications applic +applied appli +applies appli +apply appli +applying appli +appoint appoint +appointed appoint +appointment appoint +appointments appoint +appoints appoint +apportioned apport +appreciable appreci +appreciate appreci +appreciated appreci +appreciates appreci +appreciating appreci +appreciation appreci +apprehend apprehend +apprehended apprehend +apprehending apprehend +apprehension apprehens +apprehensions apprehens +apprehensive apprehens +apprentice apprentic +apprenticed apprent +apprentices apprentic +apprenticeship apprenticeship +apprise appris +apprised appris +apprising appris +approach approach +approached approach +approaches approach +approachin approachin +approaching approach +approbation approb +appropriate appropri +appropriated appropri +appropriately appropri +appropriateness appropri +appropriating appropri +appropriation appropri +approval approv +approve approv +approved approv +approves approv +approving approv +approvingly approv +approximate approxim +approximately approxim +appurtenance appurten +appurtenances appurten +apricots apricot +april april +apron apron +aprons apron +apropos apropo +apt apt +aptenodytes aptenodyt +apteryz apteryz +aptitude aptitud +aptly apt +aptness apt +aptnesses apt +aquatic aquat +aqueous aqueous +aqui aqui +aquiline aquilin +aquilines aquilin +aquinas aquina +ar ar +arab arab +arabian arabian +arabic arab +arachnidae arachnida +arago arago +araucanians araucanian +araucarian araucarian +arauco arauco +arbiter arbit +arbitrarily arbitrarili +arbitrary arbitrari +arborescent arboresc +arbour arbour +arbours arbour +arbutus arbutus +arcade arcad +arcades arcad +arcadia arcadia +arch arch +archaeologists archaeologist +archbishop archbishop +archducal archduc +arched arch +archer archer +archery archeri +arches arch +archest archest +archipelago archipelago +archipelagoes archipelago +architect architect +architects architect +architectural architectur +architecture architectur +archly arch +archness arch +archway archway +archways archway +arctic arctic +ard ard +ardent ardent +ardently ardent +ardness ard +ardour ardour +ards ard +arduous arduous +are are +area area +aready areadi +areas area +areco areco +aren aren +arena arena +arenales arenal +arequipa arequipa +arethusa arethusa +argillaceo argillaceo +argillaceous argillac +argue argu +argued argu +argues argu +arguing argu +argument argument +argumentative argument +arguments argument +argus argus +argyroneta argyroneta +ari ari +arica arica +arid arid +aridity arid +ariel ariel +aright aright +arise aris +arisen arisen +arises aris +arising aris +aristides aristid +aristocracy aristocraci +aristocrat aristocrat +aristocratic aristocrat +aristocrats aristocrat +arithmetic arithmet +arithmetical arithmet +arithmeticians arithmetician +ark ark +arkady arkadi +arm arm +armadillo armadillo +armadilloes armadillo +armadillos armadillo +armado armado +armaments armament +armchair armchair +armchairs armchair +armed arm +armful arm +armhole armhol +armies armi +arming arm +armorial armori +armour armour +armourer armour +arms arm +armstrong armstrong +army armi +arn arn +arnold arnold +arnong arnong +aromatic aromat +arose aros +around around +arouse arous +aroused arous +arqueros arquero +arragonite arragonit +arrange arrang +arranged arrang +arrangement arrang +arrangements arrang +arranges arrang +arranging arrang +arrant arrant +array array +arrayed array +arraying array +arrear arrear +arrears arrear +arrecife arrecif +arrest arrest +arrested arrest +arresting arrest +arriero arriero +arrival arriv +arrivals arriv +arrive arriv +arrived arriv +arrives arriv +arriving arriv +arrngd arrngd +arrogance arrog +arrogant arrog +arrow arrow +arrowing arrow +arrows arrow +arroyo arroyo +arson arson +art art +arter arter +artevelde arteveld +artful art +artfully art +artfulness art +arthur arthur +arthurs arthur +artichoke artichok +artichokes artichok +article articl +articled articl +articles articl +articulate articul +articulated articul +articulately articul +articulating articul +artifice artific +artifices artific +artificial artifici +artificially artifici +artillery artilleri +artilleryman artilleryman +artisan artisan +artist artist +artistic artist +artistical artist +artistically artist +artists artist +artless artless +artlessness artless +arts art +arum arum +as as +ascal ascal +ascend ascend +ascendancy ascend +ascendant ascend +ascended ascend +ascendency ascend +ascending ascend +ascends ascend +ascension ascens +ascent ascent +ascertain ascertain +ascertained ascertain +ascertaining ascertain +ascetic ascet +ascidiae ascidia +ascribable ascrib +ascribe ascrib +ascribed ascrib +ascribes ascrib +ash ash +ashamed asham +asheamed asheam +ashes ash +ashore ashor +ashy ashi +asia asia +asiat asiat +asiatic asiat +asiatiques asiatiqu +aside asid +ask ask +askance askanc +askant askant +asked ask +askew askew +asking ask +askmg askmg +asks ask +aslant aslant +asleep asleep +asparagus asparagus +aspect aspect +aspects aspect +aspen aspen +asperity asper +asphalax asphalax +aspirant aspir +aspirants aspir +aspirate aspir +aspirated aspir +aspiration aspir +aspirations aspir +aspire aspir +aspired aspir +aspires aspir +aspiring aspir +ass ass +assailant assail +assassin assassin +assassinating assassin +assault assault +assaulted assault +assaults assault +assay assay +assayer assay +assemblage assemblag +assemble assembl +assembled assembl +assembles assembl +assemblies assembl +assembling assembl +assembly assembl +assent assent +assented assent +assenting assent +assents assent +assert assert +asserted assert +asserting assert +assertion assert +assertions assert +asserts assert +asses ass +assessor assessor +asset asset +assets asset +asseverations assever +assez assez +assiduity assidu +assiduous assidu +assiduously assidu +assign assign +assignable assign +assigned assign +assignment assign +assigns assign +assimilation assimil +assist assist +assistance assist +assistant assist +assistants assist +assisted assist +assisting assist +assists assist +assize assiz +assizes assiz +assoc assoc +associate associ +associated associ +associates associ +associating associ +association associ +associations associ +assoiled assoil +assort assort +assorted assort +assortment assort +assume assum +assumed assum +assumes assum +assuming assum +assumption assumpt +assumptions assumpt +assurance assur +assurances assur +assure assur +assured assur +assuredly assur +assures assur +assuring assur +astelia astelia +astern astern +asthma asthma +astir astir +astley astley +astonish astonish +astonished astonish +astonishes astonish +astonishinent astonishin +astonishing astonish +astonishingly astonish +astonishment astonish +astounded astound +astounding astound +astray astray +astride astrid +astringent astring +astrolabe astrolab +astronomical astronom +astronomy astronomi +astute astut +asunder asund +asylum asylum +asylums asylum +at at +atacama atacama +ate ate +ated ate +atheists atheist +athenaeum athenaeum +athene athen +athenian athenian +athletic athlet +athos atho +athwart athwart +atlantic atlant +atmosphere atmospher +atmospheric atmospher +atoll atol +atollons atollon +atolls atol +atom atom +atoms atom +atone aton +atonement aton +atra atra +atratus atratus +atrocious atroci +atrocities atroc +attach attach +attache attach +attached attach +attaches attach +attaching attach +attachment attach +attachments attach +attack attack +attacked attack +attacking attack +attacks attack +attagis attagi +attain attain +attainable attain +attained attain +attaining attain +attainment attain +attainments attain +attains attain +attempt attempt +attempted attempt +attempting attempt +attempts attempt +attend attend +attendance attend +attendances attend +attendant attend +attendants attend +attended attend +attending attend +attends attend +attention attent +attentions attent +attentive attent +attentively attent +attenuated attenu +attest attest +attested attest +attesting attest +attic attic +attics attic +attire attir +attired attir +attitude attitud +attitudes attitud +attorney attorney +attorneys attorney +attract attract +attracted attract +attracting attract +attraction attract +attractions attract +attractive attract +attracts attract +attrapped attrap +attributable attribut +attribute attribut +attributed attribut +attributes attribut +attrition attrit +atwater atwat +au au +auckland auckland +auction auction +aud aud +audacious audaci +audaciously audaci +audacity audac +audible audibl +audibly audibl +audience audienc +audiences audienc +auditor auditor +auditors auditor +audubon audubon +aug aug +augean augean +augen augen +aught aught +augment augment +augmentation augment +augmented augment +augmenting augment +augments augment +augur augur +augured augur +auguries auguri +augurs augur +august august +augusta augusta +auguste august +augustus augustus +auk auk +auks auk +auld auld +aunt aunt +aunts aunt +aura aura +aureole aureol +auriferous aurifer +aus aus +auspices auspic +auspicious auspici +austell austel +austere auster +austerity auster +australes austral +australey australey +australia australia +australian australian +australians australian +austrian austrian +authentic authent +authentically authent +authenticated authent +authenticity authent +author author +authoress authoress +authoritative authorit +authoritatively authorit +authorities author +authority author +authorized author +authors author +authorship authorship +autobiographies autobiographi +autocratic autocrat +autograph autograph +autographs autograph +automaton automaton +autour autour +autre autr +autres autr +autumn autumn +autumnal autumn +auvergne auvergn +aux aux +auxiliaries auxiliari +auxiliary auxiliari +ava ava +avail avail +available avail +availed avail +availing avail +avails avail +avarice avaric +avaricious avarici +avatar avatar +avatars avatar +avaunt avaunt +avdotya avdotya +ave ave +avenge aveng +avenger aveng +avenges aveng +avenging aveng +avenue avenu +avenues avenu +average averag +averaging averag +averred aver +averring aver +avers aver +averse avers +aversion avers +aversions avers +avert avert +averted avert +averting avert +avestruz avestruz +aviary aviari +avicularia avicularia +avidity avid +avignon avignon +avocations avoc +avoid avoid +avoidable avoid +avoidance avoid +avoided avoid +avoiding avoid +avoids avoid +avoient avoient +avons avon +avow avow +avowal avow +avowed avow +avowedly avow +avowing avow +awa awa +await await +awaited await +awaiting await +awaits await +awake awak +awaken awaken +awakened awaken +awakening awaken +awakens awaken +awakes awak +awaking awak +aware awar +away away +awe awe +awed awe +awful aw +awfullest awfullest +awfully aw +awhile awhil +awhiles awhil +awkward awkward +awkwardly awkward +awkwardness awkward +awl awl +awoided awoid +awoke awok +awry awri +axe axe +axes axe +axiom axiom +axis axi +axles axl +ay ay +ayant ayant +aye aye +ayres ayr +azalea azalea +azara azara +azarae azara +azingly aze +azores azor +azucar azucar +azure azur +b b +ba ba +babble babbl +babbled babbl +babbling babbl +babby babbi +babe babe +babel babel +babes babe +babies babi +baboon baboon +babushkin babushkin +baby babi +babylon babylon +bac bac +bacchus bacchus +bachapins bachapin +bachelor bachelor +bachelorship bachelorship +bachman bachman +back back +backbone backbon +backed back +backer backer +backers backer +backgammon backgammon +background background +backing back +backs back +backsheesh backsheesh +backslidings backslid +backward backward +backwardness backward +backwards backward +backyard backyard +bacon bacon +bad bad +bade bade +baden baden +badge badg +badger badger +badgered badger +badges badg +badinage badinag +badly bad +badness bad +baffled baffl +bag bag +bagatelle bagatell +baggage baggag +bagnet bagnet +bagnets bagnet +bags bag +baguet baguet +bah bah +bahama bahama +bahia bahia +bail bail +bailed bail +bailey bailey +bailiff bailiff +baillie bailli +bairn bairn +bairns bairn +bait bait +baited bait +baize baiz +bajada bajada +bakaleyev bakaleyev +baked bake +baker baker +bakers baker +baking bake +balalaika balalaika +balance balanc +balanced balanc +balancing balanc +balandra balandra +balbi balbi +balcarce balcarc +balci balci +balconies balconi +balcony balconi +bald bald +bale bale +baleful bale +bales bale +balked balk +balking balk +balks balk +ball ball +ballad ballad +ballast ballast +balled ball +ballenagh ballenagh +ballenar ballenar +ballet ballet +balloon balloon +balloons balloon +ballot ballot +balls ball +balm balm +balmy balmi +balsam balsam +balusters balust +balustrade balustrad +balustrades balustrad +bamboo bamboo +bamboos bamboo +bamford bamford +banana banana +bananas banana +banc banc +band band +banda banda +bandage bandag +bandages bandag +bandbox bandbox +bandboxes bandbox +bandied bandi +bandit bandit +banditti banditti +bandmaster bandmast +bands band +bandy bandi +bandying bandi +bane bane +baneful bane +bang bang +banged bang +banging bang +banish banish +banishe banish +banished banish +banishes banish +banishing banish +banishment banish +banisters banist +bank bank +banked bank +banker banker +bankers banker +banking bank +banknotes banknot +bankrupt bankrupt +bankruptcies bankruptci +bankruptcy bankruptci +bankrupts bankrupt +banks bank +banner banner +banners banner +banns bann +banquet banquet +banqueting banquet +banquetings banquet +banquets banquet +banshee banshe +bantam bantam +banter banter +bantering banter +banters banter +baptism baptism +baptismal baptism +baptistery baptisteri +baptized baptiz +baptizing baptiz +bar bar +barbare barbar +barbarian barbarian +barbarians barbarian +barbarism barbar +barbarous barbar +barbary barbari +barbauld barbauld +barbecued barbecu +barber barber +barbs barb +barbuda barbuda +barcaroles barcarol +bard bard +bare bare +bared bare +barefaced barefac +barefoot barefoot +barefooted barefoot +bareheaded barehead +barely bare +barest barest +bargain bargain +bargained bargain +bargaining bargain +bargains bargain +barge barg +barges barg +baring bare +bark bark +barker barker +barking bark +barks bark +barley barley +barmaid barmaid +barmherzige barmherzig +barn barn +barnacles barnacl +barnard barnard +barnet barnet +barnevelts barnevelt +barnton barnton +barometer baromet +baron baron +baroness baro +baronesses baro +baronet baronet +baronetcy baronetci +baronets baronet +baronial baroni +barons baron +barouche barouch +barrack barrack +barracks barrack +barre barr +barred bar +barrel barrel +barrels barrel +barren barren +barrenness barren +barrett barrett +barricade barricad +barricaded barricad +barrier barrier +barriers barrier +barrington barrington +barrister barrist +barristers barrist +barrows barrow +bars bar +bart bart +barter barter +bartholomew bartholomew +barton barton +bas bas +basa basa +basal basal +basalt basalt +basalti basalti +basaltic basalt +base base +based base +basely base +basement basement +basements basement +baseness base +baser baser +bases base +basest basest +bashful bash +bashfully bash +bashfulness bash +basilisk basilisk +basin basin +basins basin +basis basi +bask bask +basked bask +basket basket +basketful basket +baskets basket +basking bask +basks bask +basque basqu +bass bass +bassoon bassoon +bastard bastard +bat bat +batch batch +bate bate +bath bath +bathe bath +bathed bath +bathers bather +bathes bath +bathing bath +baths bath +bathurst bathurst +batrachian batrachian +bats bat +battalion battalion +batter batter +battered batter +battering batter +battery batteri +battle battl +battled battl +battlefield battlefield +battlements battlement +battles battl +bauble baubl +baubles baubl +baudi baudi +bawl bawl +bawled bawl +bawling bawl +bawls bawl +bay bay +bayard bayard +bayham bayham +baying bay +baynoe bayno +bayonet bayonet +bays bay +bazaar bazaar +be be +bea bea +beach beach +beaches beach +beachheads beachhead +beacon beacon +beacons beacon +bead bead +beaded bead +beadle beadl +beadles beadl +beads bead +beagle beagl +beak beak +beaks beak +beam beam +beamed beam +beaming beam +beamingly beam +beams beam +bean bean +beans bean +bear bear +beard beard +bearded beard +beardless beardless +beards beard +bearer bearer +bearers bearer +bearing bear +bearings bear +bearish bearish +bears bear +beast beast +beastliness beastli +beastly beast +beasts beast +beat beat +beaten beaten +beaters beater +beating beat +beatings beat +beats beat +beatson beatson +beatten beatten +beau beau +beauchamp beauchamp +beaufort beaufort +beauteous beauteous +beauties beauti +beautiful beauti +beautifullest beautifullest +beautifully beauti +beauty beauti +beaux beaux +beaver beaver +becalmed becalm +became becam +because becaus +beck beck +beckon beckon +beckoned beckon +beckoning beckon +beckons beckon +become becom +becomes becom +becoming becom +bed bed +bedabbled bedabbl +bedaubed bedaub +bedchamber bedchamb +bedchambers bedchamb +bedclothes bedcloth +bedding bed +bedecked bedeck +bedecks bedeck +bedevilment bedevil +bedfellows bedfellow +bedlam bedlam +bedridden bedridden +bedroom bedroom +bedrooms bedroom +beds bed +bedside bedsid +bedstead bedstead +bedsteads bedstead +bedtime bedtim +bee bee +beech beech +beechey beechey +beef beef +beefsteak beefsteak +beehive beehiv +been been +beer beer +bees bee +beeswax beeswax +beeswaxes beeswax +beetle beetl +beetles beetl +befall befal +befallen befallen +befell befel +befillaire befillair +befit befit +befits befit +befitting befit +befogged befog +before befor +beforehand beforehand +befriend befriend +befriended befriend +befriending befriend +beg beg +bega bega +began began +begat begat +beget beget +beggar beggar +beggared beggar +beggarly beggar +beggars beggar +beggary beggari +begged beg +begging beg +begin begin +beginning begin +beginnings begin +begins begin +begludship begludship +begone begon +begotten begotten +begrimed begrim +begrimes begrim +begrudge begrudg +begrudged begrudg +begs beg +beguile beguil +beguiled beguil +begun begun +behalf behalf +behave behav +behaved behav +behaves behav +behaving behav +behavior behavior +behaviour behaviour +beheaded behead +beheld beheld +behest behest +behests behest +behind behind +behindhand behindhand +behold behold +beholden beholden +beholder behold +beholders behold +beholding behold +beholds behold +behoof behoof +behoved behov +behoves behov +behring behr +being be +beings be +beknown beknown +belated belat +belauded belaud +beldame beldam +belfry belfri +belgrave belgrav +belgravia belgravia +belgravian belgravian +belie beli +belied beli +belief belief +beliefs belief +believe believ +believed believ +believer believ +believers believ +believes believ +believest believest +believeth believeth +believing believ +bell bell +bellavista bellavista +belle bell +belled bell +bellies belli +belligerents belliger +belling bell +bellmen bellmen +bellow bellow +bellower bellow +bellowing bellow +bellows bellow +bells bell +belly belli +belong belong +belonged belong +belonging belong +belongings belong +belongs belong +beloved belov +below below +belt belt +belts belt +belvawney belvawney +belvedere belveder +bemoaned bemoan +ben ben +bench bench +bencher bencher +benchers bencher +benches bench +benchuca benchuca +bend bend +bended bend +bending bend +bends bend +beneath beneath +benedict benedict +benediction benedict +benefactor benefactor +benefactors benefactor +beneficent benefic +beneficently benefic +beneficial benefici +benefit benefit +benefited benefit +benefiting benefit +benefits benefit +benet benet +benevolence benevol +benevolent benevol +bengal bengal +benguela benguela +benighted benight +benign benign +benignant benign +benignantly benign +benignity benign +benignly benign +benito benito +bennet bennet +bennett bennett +benson benson +bent bent +benumbed benumb +bequeath bequeath +bequeathed bequeath +bequeathing bequeath +bequest bequest +berardi berardi +bereaved bereav +bereft bereft +berg berg +berkele berkel +berkeley berkeley +berlin berlin +bermudas bermuda +bernantio bernantio +beroe bero +berquelo berquelo +berrid berrid +berried berri +berries berri +berrin berrin +berry berri +berryin berryin +berteroii berteroii +berth berth +berthelot berthelot +bertram bertram +beryl beryl +berzelius berzelius +beseech beseech +beseeches beseech +beseeching beseech +beseechingly beseech +beseeltes beseelt +beseems beseem +beset beset +besetting beset +beside besid +besides besid +besieged besieg +besmeared besmear +besought besought +bespattered bespatt +bespeak bespeak +bespeaking bespeak +bespeaks bespeak +bespeckled bespeckl +bespoke bespok +besprinkled besprinkl +best best +bestest bestest +bestir bestir +bestow bestow +bestowal bestow +bestowed bestow +bestowing bestow +bestows bestow +bet bet +betake betak +betaken betaken +bethany bethani +bethel bethel +bethlehem bethlehem +bethought bethought +betimes betim +betokened betoken +betokening betoken +betook betook +betray betray +betrayal betray +betrayed betray +betraying betray +betrays betray +betrothed betroth +bets bet +better better +betters better +betther betther +betting bet +betty betti +betuloides betuloid +betwee betwe +between between +betwixt betwixt +beudant beudant +bevan bevan +beverage beverag +beverley beverley +bewail bewail +bewailed bewail +bewailing bewail +beware bewar +bewilder bewild +bewildered bewild +bewildering bewild +bewilderment bewilder +bewitched bewitch +bewitching bewitch +beyond beyond +bezants bezant +bezzemelny bezzemelni +bianchini bianchini +bias bias +bible bibl +bibo bibo +bibron bibron +bid bid +biddable biddabl +bidden bidden +bidder bidder +bidding bid +biddy biddi +bide bide +biding bide +bids bid +bien bien +biffin biffin +bifurcating bifurc +bifurcation bifurc +big big +bigamy bigami +bigger bigger +biggest biggest +bigness big +bigoted bigot +bigotry bigotri +bile bile +bileing bile +bilious bilious +bill bill +billed bill +billet billet +billeted billet +billiard billiard +billiards billiard +billing bill +billows billow +bills bill +bin bin +bind bind +binding bind +bindings bind +bindloes bindlo +binds bind +bingley bingley +binn binn +biographical biograph +biography biographi +bios bio +biped bipe +birch birch +bird bird +birdcage birdcag +birds bird +birgos birgo +birmingham birmingham +birth birth +birthday birthday +birthdays birthday +birthplace birthplac +birthright birthright +births birth +biscuit biscuit +biscuits biscuit +bisecting bisect +bisection bisect +bishop bishop +bishopgate bishopg +bishopric bishopr +bishops bishop +bishopsgate bishopsg +bismarcks bismarck +bisness bis +bit bit +bitch bitch +bite bite +bites bite +biting bite +bits bit +bitted bit +bitten bitten +bitter bitter +bitterer bitter +bitterest bitterest +bitterly bitter +bitterness bitter +bivalves bivalv +bivouac bivouac +bivouacked bivouack +bivouacking bivouack +bizcacha bizcacha +bizcachas bizcacha +blab blab +black black +blackamoor blackamoor +blackberries blackberri +blackberry blackberri +blackbird blackbird +blacken blacken +blackened blacken +blackens blacken +blacker blacker +blackest blackest +blackfriars blackfriar +blackguard blackguard +blackguardly blackguard +blackguards blackguard +blackhaired blackhair +blackheath blackheath +blacking black +blackish blackish +blacklead blacklead +blackleg blackleg +blacks black +blacksmith blacksmith +blacksmiths blacksmith +blackstone blackston +blackwall blackwal +bladder bladder +bladders bladder +blade blade +bladed blade +blades blade +blain blain +blamable blamabl +blame blame +blameable blameabl +blamed blame +blameless blameless +blamelessness blameless +blames blame +blaming blame +blanc blanc +blanca blanca +blanche blanch +blanched blanch +blanco blanco +bland bland +blandest blandest +blandishments blandish +blandly bland +blank blank +blanket blanket +blankets blanket +blankly blank +blankness blank +blanks blank +blas blas +blasphemer blasphem +blasphemy blasphemi +blast blast +blasted blast +blasts blast +blatta blatta +blaze blaze +blazing blaze +blazoned blazon +bleached bleach +bleak bleak +bleakness bleak +blear blear +bleared blear +bled bled +bleed bleed +bleeding bleed +blemish blemish +blemishes blemish +blench blench +blended blend +blending blend +blends blend +bless bless +blessed bless +blessedness blessed +blesses bless +blessing bless +blessings bless +blest blest +blew blew +blight blight +blighted blight +blighting blight +blights blight +blind blind +blinded blind +blinder blinder +blindfolding blindfold +blinding blind +blindly blind +blindness blind +blindnesses blind +blinds blind +blink blink +blinkers blinker +blinking blink +blinks blink +bliss bliss +blissful bliss +blister blister +blistered blister +blistering blister +blithe blith +blitheness blith +blo blo +bloated bloat +block block +blockade blockad +blockaded blockad +blocked block +blockhead blockhead +blockheads blockhead +blocking block +blocks block +blockson blockson +blood blood +blooded blood +bloodhound bloodhound +bloodless bloodless +bloodlessness bloodless +bloods blood +bloodshed bloodsh +bloodshot bloodshot +bloodthirsty bloodthirsti +bloody bloodi +bloom bloom +bloometh bloometh +blooming bloom +bloomsbury bloomsburi +blossom blossom +blossomed blossom +blossoming blossom +blossoms blossom +blot blot +blotches blotch +blotchy blotchi +blots blot +blotted blot +blotting blot +blow blow +blowed blow +blower blower +blowers blower +blowing blow +blown blown +blowpipe blowpip +blows blow +blubber blubber +blubbered blubber +bludgeon bludgeon +bludgeons bludgeon +blue blue +bluebells bluebel +blues blue +bluff bluff +bluffy bluffi +bluid bluid +bluish bluish +blulfy blulfi +blunder blunder +blunderbore blunderbor +blunderbus blunderbus +blunderbuss blunderbuss +blundered blunder +blundering blunder +blunders blunder +blunt blunt +blunted blunt +bluntly blunt +bluntness blunt +blur blur +blurs blur +blurt blurt +blurted blurt +blurting blurt +blurts blurt +blush blush +blushed blush +blushes blush +blushing blush +blushingly blush +bluster bluster +blusterers bluster +blustering bluster +bo bo +boa boa +boan boan +boans boan +boar boar +board board +boarded board +boarder boarder +boarders boarder +boarding board +boards board +boars boar +boas boa +boast boast +boasted boast +boastful boast +boastfully boast +boastfulness boast +boasting boast +boasts boast +boat boat +boating boat +boats boat +bob bob +bobbed bob +bobbing bob +bobbish bobbish +bobs bob +bobster bobster +bod bod +boddy boddi +bodice bodic +bodied bodi +bodies bodi +bodilessness bodiless +bodily bodili +boding bode +bodkins bodkin +body bodi +boer boer +boffin boffin +boffinites boffinit +bog bog +bogg bogg +bogsby bogsbi +boguey boguey +bohemianism bohemian +bohemond bohemond +boil boil +boiled boil +boiler boiler +boilers boiler +boiling boil +boils boil +bois boi +boisterous boister +boisterously boister +bolabola bolabola +bolas bola +bold bold +bolder bolder +boldest boldest +boldly bold +boldness bold +bole bole +boles bole +bolivia bolivia +bolivian bolivian +bolster bolster +bolt bolt +bolted bolt +bolter bolter +bolting bolt +bolts bolt +bomb bomb +bombarding bombard +bombs bomb +bon bon +bona bona +bond bond +bondage bondag +bonds bond +bone bone +boned bone +bones bone +bonfires bonfir +bonitos bonito +bonjour bonjour +bonn bonn +bonne bonn +bonnet bonnet +bonnets bonnet +bonney bonney +bonny bonni +bonpland bonpland +bons bon +bony boni +booby boobi +boodle boodl +boody boodi +book book +bookcase bookcas +booked book +booker booker +booking book +bookish bookish +books book +bookseller booksel +booksellers booksel +bookstall bookstal +bookworms bookworm +boom boom +boomerang boomerang +boon boon +boorioboola boorioboola +boorly boor +boost boost +boot boot +booth booth +booths booth +boots boot +bootuns bootun +booty booti +boozed booz +boozums boozum +bor bor +bord bord +border border +bordered border +bordering border +borders border +bore bore +boreali boreali +boreas borea +bored bore +boredom boredom +bores bore +boring bore +born born +borne born +borneo borneo +borough borough +boroughbridge boroughbridg +boroughmongering boroughmong +boroughs borough +borreria borreria +borrioboola borrioboola +borrioboolan borrioboolan +borriohoola borriohoola +borrow borrow +borrowed borrow +borrower borrow +borrowers borrow +borrowing borrow +borrows borrow +borum borum +bory bori +bos bos +bosh bosh +bosom bosom +bosomer bosom +bosoms bosom +bosses boss +boston boston +bot bot +botanic botan +botanical botan +botanist botanist +botanists botanist +botanizing botan +botany botani +both both +bother bother +botheration bother +bothered bother +bothering bother +botofogo botofogo +bott bott +bottin bottin +bottinney bottinney +bottle bottl +bottled bottl +bottles bottl +bottom bottom +bottomed bottom +bottomless bottomless +bottoms bottom +boudoir boudoir +bougainville bougainvill +boughs bough +bought bought +boulder boulder +boulders boulder +boulevard boulevard +bouleversees bouleverse +boulogne boulogn +boulong boulong +bounced bounc +bouncing bounc +bound bound +boundaries boundari +boundary boundari +bounde bound +bounded bound +bounden bounden +bounding bound +boundless boundless +bounds bound +boung boung +boungites boungit +bountiful bounti +bounty bounti +bouquet bouquet +bouquets bouquet +bourbon bourbon +bourgeois bourgeoi +bourne bourn +bout bout +bow bow +bowed bow +bowels bowel +bower bower +bowered bower +bowers bower +bowery boweri +bowing bow +bowl bowl +bowled bowl +bowling bowl +bowls bowl +bows bow +box box +boxed box +boxes box +boxing box +boy boy +boyhood boyhood +boyish boyish +boys boy +boytborn boytborn +boythorn boythorn +brabantio brabantio +brace brace +braced brace +bracelet bracelet +bracelets bracelet +braces brace +brachelytra brachelytra +brachiotis brachioti +brachyptera brachyptera +bracing brace +brackish brackish +bradshaw bradshaw +brag brag +braggadocio braggadocio +braggart braggart +bragging brag +braid braid +braided braid +braids braid +brain brain +brained brain +brainless brainless +brains brain +brak brak +brake brake +brakes brake +bramador bramador +brambles brambl +bran bran +branc branc +branch branch +branched branch +branches branch +branchiae branchia +branchial branchial +branching branch +brand brand +branded brand +branding brand +brandished brandish +brandishing brandish +brandon brandon +brandons brandon +brandy brandi +brash brash +brasiliensis brasiliensi +brass brass +brasses brass +brat brat +brats brat +bravado bravado +bravard bravard +bravassa bravassa +brave brave +braved brave +bravely brave +bravery braveri +bravest bravest +braving brave +bravo bravo +brawl brawl +brawler brawler +brawling brawl +brawny brawni +braxon braxon +bray bray +braying bray +brazen brazen +brazened brazen +brazil brazil +brazilian brazilian +brazilians brazilian +brazils brazil +breach breach +breached breach +breaches breach +bread bread +breads bread +breadth breadth +break break +breaker breaker +breakers breaker +breakfast breakfast +breakfasted breakfast +breakfasting breakfast +breakfasts breakfast +breakin breakin +breaking break +breaks break +breakwater breakwat +breakwaters breakwat +breast breast +breasted breast +breasts breast +breastwork breastwork +breath breath +breathe breath +breathed breath +breathes breath +breathing breath +breathings breath +breathless breathless +breathlessly breathless +breathlessness breathless +breaths breath +breccia breccia +bred bred +bree bree +breeches breech +breed breed +breeder breeder +breeding breed +breeds breed +breeze breez +breezes breez +breezy breezi +brethren brethren +brevity breviti +brew brew +brewed brew +brewer brewer +brewers brewer +brewery breweri +brewing brew +brewster brewster +bribe bribe +bribed bribe +bribery briberi +bribes bribe +bribing bribe +brick brick +bricked brick +bricklayers bricklay +brickmaker brickmak +brickmakers brickmak +bricks brick +brickwork brickwork +bridal bridal +bride bride +bridegroom bridegroom +bridesmaid bridesmaid +bridesmaids bridesmaid +bridge bridg +bridged bridg +bridges bridg +bridle bridl +bridling bridl +brief brief +briefly briefli +briefs brief +brier brier +briers brier +brig brig +brigade brigad +brigand brigand +brigands brigand +bright bright +brighten brighten +brightened brighten +brightening brighten +brightens brighten +brighter brighter +brightest brightest +brightly bright +brightness bright +brighton brighton +brigs brig +brilliance brillianc +brilliancy brillianc +brilliant brilliant +brilliantly brilliant +brim brim +brimful brim +brimless brimless +brimmed brim +brimming brim +brimmy brimmi +brims brim +brimstone brimston +brindle brindl +brine brine +bring bring +bringing bring +brings bring +brink brink +briny brini +brisk brisk +brisker brisker +briskly brisk +briskness brisk +bristle bristl +bristled bristl +bristles bristl +bristly brist +bristol bristol +brit brit +britain britain +britannia britannia +british british +briton briton +brittann brittann +brittle brittl +broach broach +broached broach +broad broad +broadcast broadcast +broadened broaden +broader broader +broadly broad +broadside broadsid +broadsides broadsid +broadsword broadsword +broadwise broadwis +brocade brocad +brochure brochur +brock brock +brogden brogden +broide broid +broiled broil +broiling broil +broke broke +broken broken +brokenly broken +broker broker +brokers broker +brokken brokken +bromelia bromelia +bromley bromley +brompton brompton +bronchial bronchial +bronchitis bronchiti +bronze bronz +bronzed bronz +broo broo +brooch brooch +brood brood +brooded brood +brooding brood +broodingly brood +brook brook +brooker brooker +brooks brook +broom broom +brooms broom +broomstick broomstick +brooses broos +broth broth +brother brother +brotherhood brotherhood +brotherly brother +brothers brother +brougham brougham +brought brought +broune broun +brout brout +brow brow +browdie browdi +browdies browdi +brown brown +browndock browndock +browne brown +browner browner +browning brown +brownish brownish +browns brown +brows brow +browsed brows +browsing brows +bruce bruce +bruise bruis +bruised bruis +bruises bruis +bruising bruis +brun brun +brunswick brunswick +brunt brunt +brush brush +brushed brush +brushes brush +brushing brush +brushwood brushwood +brusque brusqu +brussels brussel +brutal brutal +brutality brutal +brutally brutal +brute brute +brutes brute +brutish brutish +bryanstone bryanston +bu bu +bubble bubbl +bubbles bubbl +bubblin bubblin +bubbling bubbl +bucaniers bucani +buccaneering buccan +buccaneers buccan +buch buch +buck buck +bucket bucket +bucketful bucket +buckets bucket +buckingham buckingham +buckland buckland +buckle buckl +buckler buckler +buckles buckl +buckram buckram +buckskins buckskin +bud bud +budded bud +budding bud +budge budg +budget budget +budgets budget +buds bud +buena buena +buenos bueno +buey buey +buff buff +buffer buffer +buffet buffet +buffeting buffet +buffetings buffet +buffets buffet +buffon buffon +buffoon buffoon +buffoonery buffooneri +buffoons buffoon +buffy buffi +bug bug +bugged bug +bugle bugl +bugs bug +buil buil +build build +builder builder +buildin buildin +building build +buildings build +builds build +built built +bulbous bulbous +bulgaria bulgaria +bulged bulg +bulimus bulimus +bulk bulk +bulkeley bulkeley +bulky bulki +bull bull +bulldog bulldog +bullen bullen +bullet bullet +bulletin bulletin +bulletins bulletin +bullets bullet +bullfinch bullfinch +bullied bulli +bullies bulli +bullion bullion +bullock bullock +bullocks bullock +bulls bull +bully bulli +bullying bulli +bulph bulph +bulwarks bulwark +bump bump +bumped bump +bumper bumper +bumpers bumper +bumping bump +bun bun +bunch bunch +bunches bunch +buncombe buncomb +bundle bundl +bundled bundl +bundles bundl +bung bung +bungay bungay +bungays bungay +bungle bungl +bungling bungl +buns bun +bunting bunt +buoy buoy +buoyancy buoyanc +buoyant buoyant +buoyantly buoyant +buoyed buoy +burchell burchel +burchess burchess +burden burden +burdened burden +burdening burden +burdens burden +burdensome burdensom +bureau bureau +burglars burglar +burgomaster burgomast +burgomeister burgomeist +burial burial +buried buri +buries buri +burlesque burlesqu +burlinghammer burlinghamm +burly bur +burn burn +burned burn +burnet burnet +burning burn +burnings burn +burnished burnish +burnous burnous +burns burn +burnt burnt +burrow burrow +burrowed burrow +burrowing burrow +burrowings burrow +burrows burrow +burst burst +bursting burst +bursts burst +burthen burthen +burton burton +bury buri +burying buri +bus bus +bush bush +bushby bushbi +bushe bush +bushel bushel +bushels bushel +bushes bush +bushy bushi +busied busi +busier busier +busies busi +busily busili +business busi +businesslike businesslik +buskin buskin +bust bust +busted bust +bustle bustl +bustled bustl +bustling bustl +busts bust +busy busi +busybody busybodi +busying busi +but but +butcher butcher +butchered butcher +butchers butcher +butler butler +buts but +butt butt +butter butter +buttered butter +butterflies butterfli +butterfly butterfli +butterman butterman +butther butther +butting but +button button +buttoned button +buttonhole buttonhol +buttoning button +buttons button +buttresses buttress +butts butt +buxom buxom +buy buy +buyers buyer +buying buy +buyings buy +buys buy +buzz buzz +buzzard buzzard +buzzed buzz +buzzing buzz +bwoken bwoken +by by +bye bye +byelinsky byelinski +bygone bygon +bygones bygon +bynoe byno +byron byron +bystanders bystand +byways byway +byzantine byzantin +c c +ca ca +cab cab +cabalistic cabalist +caballed cabal +cabals cabal +cabbage cabbag +cabbages cabbag +cabbery cabberi +cabeza cabeza +cabin cabin +cabinet cabinet +cabinets cabinet +cabins cabin +cable cabl +cables cabl +cabman cabman +cabooses caboos +cabriolet cabriolet +cabriolets cabriolet +cabs cab +cachapual cachapu +cacique caciqu +caciques caciqu +cackle cackl +cackled cackl +cacti cacti +cactornis cactorni +cactus cactus +cactuses cactus +cad cad +cadaverous cadaver +caddy caddi +cadesses cadess +cadet cadet +cadets cadet +cadogan cadogan +cads cad +caesar caesar +cafe cafe +caffer caffer +caffre caffr +caffres caffr +cage cage +caged cage +cages cage +cajoled cajol +cajoling cajol +cake cake +cakes cake +calabria calabria +calais calai +calamities calam +calamitous calamit +calamity calam +calandria calandria +calcareo calcareo +calcareous calcar +calculate calcul +calculated calcul +calculates calcul +calculating calcul +calculation calcul +calculations calcul +calculus calculus +caldcleugh caldcleugh +caldeleugh caldeleugh +caldrons caldron +caledonia caledonia +caledonian caledonian +calendar calendar +calendars calendar +calf calf +calibre calibr +calico calico +california california +call call +callao callao +calle call +called call +callems callem +calling call +callings call +callous callous +callousness callous +calls call +calm calm +calmed calm +calmer calmer +calmest calmest +calming calm +calmly calm +calmness calm +calms calm +caln caln +calodera calodera +calomel calomel +calosoma calosoma +calumniated calumni +calumnies calumni +calumniously calumni +calumny calumni +calve calv +calves calv +camarhynchus camarhynchus +camberwell camberwel +cambric cambric +cambridge cambridg +cambridgeshire cambridgeshir +came came +camel camel +camels camel +camlet camlet +camp camp +campaign campaign +campana campana +campany campani +campestris campestri +camphor camphor +campo campo +campos campo +can can +canada canada +canal canal +canals canal +canaries canari +canary canari +cancan cancan +cancellaria cancellaria +cancelled cancel +cancelling cancel +cancer cancer +candid candid +candidate candid +candidates candid +candidateship candidateship +candidature candidatur +candidly candid +candle candl +candlelight candlelight +candles candl +candlestick candlestick +candlesticks candlestick +candour candour +cane cane +caned cane +canelones canelon +canes cane +cangrejales cangrejal +canis cani +canister canist +cannibal cannib +cannibalism cannib +cannibals cannib +canning canning +canno canno +cannon cannon +cannons cannon +cannot cannot +canoe cano +canoes cano +canons canon +canopy canopi +cant cant +cantal cantal +canter canter +canterbury canterburi +cantered canter +canting cant +cantrip cantrip +cantrips cantrip +canvas canva +canvass canvass +canvassed canvass +canvassing canvass +cap cap +capabilities capabl +capability capabl +capable capabl +capacious capaci +capacities capac +capacity capac +cape cape +capella capella +capers caper +capita capita +capital capit +capitalist capitalist +capitalists capitalist +capitally capit +capitals capit +capitol capitol +capitulate capitul +capped cap +capping cap +caprice capric +caprices capric +capricious caprici +capriciously caprici +capricorn capricorn +caps cap +capsicum capsicum +capstans capstan +capsule capsul +capt capt +captain captain +captains captain +captious captious +captivate captiv +captivated captiv +captivater captivat +captivating captiv +captivator captiv +captive captiv +captives captiv +captivity captiv +capture captur +captured captur +capybara capybara +capybaras capybara +carabidae carabida +caracara caracara +caracaras caracara +caracter caract +caravan caravan +caravansary caravansari +caravanserai caravanserai +caravels caravel +carbine carbin +carbonaceous carbonac +carbonate carbon +carboniferous carbonifer +carboy carboy +carbury carburi +carcase carcas +carcass carcass +carcasses carcass +card card +cardinal cardin +cardoon cardoon +cards card +cardui cardui +cardunculus cardunculus +care care +cared care +career career +careers career +careful care +carefully care +carefulness care +careless careless +carelessly careless +carelessness careless +cares care +caress caress +caressed caress +caresses caress +caressing caress +caressingly caress +careworn careworn +cargo cargo +cargoes cargo +caricature caricatur +caricatures caricatur +caring care +carizal cariz +carking cark +carlos carlo +carlton carlton +carmen carmen +carmichael carmichael +carmine carmin +carnage carnag +carnation carnat +carne carn +carnegie carnegi +carnivorous carnivor +caroline carolin +carolling carol +carp carp +carpacho carpacho +carpenter carpent +carpenters carpent +carpet carpet +carpeted carpet +carpeting carpet +carpetless carpetless +carpets carpet +carping carp +carrancha carrancha +carranchas carrancha +carriage carriag +carriages carriag +carrie carri +carried carri +carrier carrier +carries carri +carrion carrion +carrot carrot +carrots carrot +carry carri +carrying carri +carse cars +carstone carston +cart cart +carte cart +cartel cartel +carthagena carthagena +cartload cartload +cartloads cartload +cartridge cartridg +cartridges cartridg +carts cart +carve carv +carved carv +carving carv +carvings carv +casara casara +casarita casarita +cascade cascad +cascades cascad +case case +casement casement +casements casement +cases case +cash cash +cashmere cashmer +cashup cashup +cask cask +casket casket +caskets casket +casks cask +casma casma +caspian caspian +cassada cassada +cassio cassio +cast cast +castanet castanet +castaway castaway +caste cast +castigate castig +castigation castig +casting cast +castle castl +castles castl +castor castor +castrated castrat +castro castro +casts cast +casual casual +casually casual +casualties casualti +casuarina casuarina +casucha casucha +casuchas casucha +casuistry casuistri +casuists casuist +cat cat +catacomb catacomb +cataleptic catalept +catalogue catalogu +catalogued catalogu +catalonian catalonian +catamaran catamaran +cataract cataract +cataracts cataract +catastrophe catastroph +catastrophes catastroph +catch catch +catched catch +catchers catcher +catches catch +catching catch +catchings catch +catechism catech +categories categori +category categori +caterpillar caterpillar +caterpillars caterpillar +catgut catgut +cathartes cathart +cathedral cathedr +cathedrals cathedr +catherine catherin +catholic cathol +catholics cathol +cats cat +cattle cattl +caucahue caucahu +caught caught +cauldron cauldron +cauliflowers cauliflow +cauquenes cauquen +caus caus +cause caus +caused caus +causeless causeless +causes caus +causing caus +caustic caustic +caution caution +cautioned caution +cautioning caution +cautions caution +cautious cautious +cautiously cautious +cavalry cavalri +cave cave +caveat caveat +cavendish cavendish +cavern cavern +cavernous cavern +caverns cavern +caves cave +cavia cavia +cavies cavi +cavil cavil +cavillers cavil +cavities caviti +cavity caviti +cavy cavi +caw caw +cawa cawa +cawing caw +cayanus cayanus +cayenne cayenn +caylen caylen +cease ceas +ceased ceas +ceaseless ceaseless +ceaselessly ceaseless +ceases ceas +ceasing ceas +cebrionidae cebrionida +cecilia cecilia +cedar cedar +cedars cedar +ceedingly ceed +ceiling ceil +ceilings ceil +ceillhg ceillhg +cel cel +celebes celeb +celebrate celebr +celebrated celebr +celebration celebr +celebrity celebr +celery celeri +celestial celesti +cell cell +cellar cellar +cellarage cellarag +cellaria cellaria +cellars cellar +cells cell +cellular cellular +cement cement +cemented cement +cementing cement +cemetery cemeteri +cenotherae cenothera +censorious censori +censorship censorship +censure censur +censured censur +censures censur +censuring censur +census census +cent cent +centaurs centaur +centered center +centra centra +central central +centre centr +centred centr +centres centr +centrifugal centrifug +centring centr +cents cent +centuries centuri +century centuri +cependent cepend +cephalopoda cephalopoda +cereal cereal +ceremonial ceremoni +ceremonies ceremoni +ceremonious ceremoni +ceremoniously ceremoni +ceremony ceremoni +cerro cerro +certain certain +certainl certainl +certainly certain +certainties certainti +certainty certainti +certhia certhia +certhidea certhidea +certificate certif +certificates certif +certified certifi +certifiket certifiket +certify certifi +certifying certifi +cervicem cervicem +cervus cervus +ceryle ceryl +ces ces +cesenate cesen +cessation cessat +cesspool cesspool +cesspools cesspool +cetaceous cetac +cetera cetera +ceteras cetera +cetrer cetrer +chacao chacao +chacun chacun +chadband chadband +chadbands chadband +chafe chafe +chafed chafe +chafes chafe +chaff chaff +chaffers chaffer +chaffinch chaffinch +chafing chafe +chagos chago +chagrin chagrin +chai chai +chain chain +chained chain +chains chain +chair chair +chairing chair +chairman chairman +chairs chair +chaise chais +chalk chalk +chalked chalk +chalking chalk +challenge challeng +challenged challeng +challenger challeng +challenging challeng +chalr chalr +chama chama +chamber chamber +chamberlain chamberlain +chambers chamber +chambre chambr +chameleon chameleon +chamisso chamisso +chamois chamoi +champagne champagn +champion champion +champions champion +chance chanc +chanced chanc +chancellor chancellor +chancellors chancellor +chancelor chancelor +chancery chanceri +chances chanc +chancing chanc +chandelier chandeli +chandeliers chandeli +chandler chandler +chaneral chaner +change chang +changeable changeabl +changed chang +changeling changel +changes chang +changing chang +channel channel +channels channel +chantant chantant +chanted chant +chanting chant +chants chant +chanuncillo chanuncillo +chaos chao +chaotic chaotic +chap chap +chapel chapel +chapels chapel +chaperon chaperon +chaperone chaperon +chaperons chaperon +chaplain chaplain +chaps chap +chapter chapter +chapters chapter +chaquaio chaquaio +character charact +characteristic characterist +characteristically characterist +characteristics characterist +characterize character +characterized character +characterizes character +characterizing character +characters charact +charade charad +charcoal charcoal +charcoaled charcoal +charge charg +chargeable chargeabl +charged charg +chargers charger +charges charg +charging charg +chariey chariey +charing chare +chariot chariot +chariots chariot +charitable charit +charitably charit +charities chariti +charity chariti +charlatanism charlatan +charles charl +charley charley +charlie charli +charlotte charlott +charm charm +charmed charm +charmer charmer +charmers charmer +charming charm +charmingly charm +charms charm +charnel charnel +charon charon +charqui charqui +charred char +chart chart +chartered charter +chartism chartism +chartist chartist +charts chart +charwoman charwoman +chary chari +chase chase +chased chase +chases chase +chasing chase +chasm chasm +chasms chasm +chaste chast +chastened chasten +chastening chasten +chastise chastis +chastisement chastis +chastity chastiti +chat chat +chateau chateau +chatham chatham +chatted chat +chattels chattel +chatter chatter +chatterbox chatterbox +chattered chatter +chatterer chatter +chattering chatter +chatters chatter +chatting chat +chatty chatti +chaunt chaunt +cheap cheap +cheaper cheaper +cheapest cheapest +cheaply cheapli +cheapside cheapsid +cheat cheat +cheated cheat +cheating cheat +cheats cheat +chec chec +check check +checked check +checking check +checks check +cheek cheek +cheeked cheek +cheeks cheek +cheer cheer +cheered cheer +cheerful cheer +cheerfully cheer +cheerfulness cheer +cheerily cheerili +cheeriness cheeri +cheering cheer +cheerless cheerless +cheers cheer +cheery cheeri +cheeryble cheerybl +cheerybles cheerybl +cheese chees +cheeseming cheesem +chefs chef +chelsea chelsea +cheltenham cheltenham +chem chem +chemical chemic +chemins chemin +chemise chemis +chemist chemist +chemistry chemistri +chemists chemist +chenille chenill +chepones chepon +cheque chequ +chequered chequer +cheques chequ +cher cher +chere chere +cherish cherish +cherished cherish +cherishes cherish +cherishing cherish +cherizette cherizett +cherries cherri +cherry cherri +cherryble cherrybl +cherrybles cherrybl +cherty cherti +cherubim cherubim +cheshires cheshir +chesney chesney +chess chess +chest chest +chested chest +chesterfield chesterfield +chestnut chestnut +chestnuts chestnut +chests chest +cheucau cheucau +cheval cheval +chevaux chevaux +chevy chevi +chew chew +chewed chew +chewing chew +chichester chichest +chichi chichi +chick chick +chicken chicken +chickens chicken +chiduco chiduco +chief chief +chiefest chiefest +chiefly chiefli +chiefs chief +chiel chiel +chiens chien +child child +childhood childhood +childish childish +childishly childish +childishness childish +childless childless +childlike childlik +children children +chile chile +chilean chilean +chileno chileno +chilenos chileno +chilian chilian +chilicauquen chilicauquen +chilipa chilipa +chill chill +chilled chill +chilling chill +chills chill +chilly chilli +chiloe chilo +chilotan chilotan +chilotans chilotan +chiltern chiltern +chimango chimango +chimbley chimbley +chimborazo chimborazo +chimes chime +chimie chimi +chimney chimney +chimneypiece chimneypiec +chimneys chimney +chin chin +china china +chinas china +chinchilloides chinchilloid +chinese chines +chink chink +chinking chink +chinks chink +chins chin +chintz chintz +chionis chioni +chip chip +chipping chip +chirp chirp +chirped chirp +chirping chirp +chirps chirp +chirrup chirrup +chirruped chirrup +chirruping chirrup +chisel chisel +chiselled chisel +chit chit +chitons chiton +chivalrous chivalr +chivalrously chivalr +chivalry chivalri +chivied chivi +chivying chivi +chizzle chizzl +chlorides chlorid +chock chock +chocolate chocol +choice choic +choiceness choic +choicest choicest +choir choir +choiseul choiseul +choke choke +choked choke +chokes choke +choking choke +cholechel cholechel +cholera cholera +chonchi chonchi +chonos chono +choose choos +chooses choos +choosing choos +chop chop +chopkins chopkin +chopped chop +chopping chop +chops chop +chord chord +chords chord +choristers chorist +chorus chorus +choruses chorus +chose chose +chosen chosen +chowser chowser +christ christ +christabel christabel +christen christen +christendom christendom +christened christen +christening christen +christi christi +christian christian +christianity christian +christians christian +christmas christma +christopher christoph +chronic chronic +chronicle chronicl +chronicled chronicl +chroniclers chronicl +chronicles chronicl +chronometrical chronometr +chrysalis chrysali +chrysomelidae chrysomelida +chrysopa chrysopa +chubby chubbi +chuck chuck +chucked chuck +chuckle chuckl +chuckled chuckl +chuckling chuckl +chunk chunk +chunks chunk +chupat chupat +church church +churches church +churchgoing churchgo +churchyard churchyard +churchyards churchyard +churlishness churlish +churls churl +churned churn +churning churn +chut chut +chuzo chuzo +chuzos chuzo +chy chi +cicadae cicada +cicadas cicada +cicidae cicida +cider cider +cigar cigar +cigarette cigarett +cigarettes cigarett +cigaritos cigarito +cigars cigar +ciliae cilia +cimabue cimabu +cincindela cincindela +cincinnatus cincinnatus +cincinnatuses cincinnatus +cinder cinder +cinderella cinderella +cinders cinder +cindery cinderi +cinereus cinereus +cinnamon cinnamon +cinq cinq +ciphering cipher +cir cir +circle circl +circles circl +circling circl +circuit circuit +circuitous circuit +circuits circuit +circular circular +circulars circular +circulated circul +circulates circul +circulating circul +circulation circul +circumambient circumambi +circumference circumfer +circumjacent circumjac +circumlocution circumlocut +circumnavigate circumnavig +circumnavigation circumnavig +circumscribed circumscrib +circumspect circumspect +circumstance circumst +circumstanced circumstanc +circumstances circumst +circumstantial circumstanti +circumstantially circumstanti +circus circus +cistern cistern +cisterns cistern +citadel citadel +citation citat +cite cite +cited cite +cities citi +citigrade citigrad +citizen citizen +citizens citizen +city citi +cive cive +civil civil +civilian civilian +civilians civilian +civilised civilis +civilities civil +civility civil +civilization civil +civilized civil +civilly civilli +clad clad +cladonia cladonia +claim claim +claimant claimant +claimed claim +claiming claim +claims claim +clairvoyante clairvoyant +clambered clamber +clamorous clamor +clamour clamour +clamouring clamour +clandestinely clandestin +clang clang +clanging clang +clangour clangour +clank clank +clanking clank +clanks clank +clap clap +clapped clap +clapping clap +clappings clap +claps clap +clara clara +clare clare +claret claret +clarionet clarionet +clark clark +clarke clark +clash clash +clashed clash +clashes clash +clashing clash +clasp clasp +clasped clasp +clasping clasp +claspknife claspknif +clasps clasp +class class +classed class +classes class +classic classic +classical classic +classicality classic +classify classifi +clatter clatter +clattered clatter +clattering clatter +clause claus +clausen clausen +clauses claus +clavipes clavip +claw claw +clawing claw +claws claw +clay clay +clayey clayey +claying clay +clayver clayver +clean clean +cleaned clean +cleaner cleaner +cleanest cleanest +cleaning clean +cleanliest cleanliest +cleanliness cleanli +cleanly clean +cleans clean +cleanse cleans +cleanses cleans +cleansing cleans +clear clear +clearance clearanc +cleared clear +clearer clearer +clearest clearest +clearing clear +clearly clear +clearness clear +cleavage cleavag +cleft cleft +clefts cleft +clematis clemati +clemency clemenc +clench clench +clenched clench +clenches clench +clenching clench +cleopatra cleopatra +clergyman clergyman +clergymen clergymen +clerical cleric +clerk clerk +clerkenwell clerkenwel +clerkly clerk +clerks clerk +clerkship clerkship +cleveland cleveland +clever clever +cleverer clever +cleverest cleverest +cleverly clever +cleverness clever +click click +clicked click +clicking click +client client +clients client +cliff cliff +clifford clifford +cliffs cliff +clifton clifton +clima clima +climate climat +climates climat +climax climax +climb climb +climbed climb +climbers climber +climbing climb +clime clime +climes clime +clinched clinch +cling cling +clinging cling +clings cling +clink clink +clinked clink +clinking clink +clip clip +clipped clip +clippers clipper +clipping clip +cliquot cliquot +clks clks +cloak cloak +cloaks cloak +clock clock +clocks clock +clods clod +cloe cloe +clogged clog +cloister cloister +cloistered cloister +cloisterly cloister +cloisters cloister +close close +closed close +closely close +closeness close +closer closer +closes close +closest closest +closet closet +closeted closet +closets closet +closing close +cloth cloth +clothe cloth +clothed cloth +clother clother +clothes cloth +clothing cloth +cloths cloth +clotted clot +cloud cloud +clouded cloud +cloudily cloudili +cloudless cloudless +clouds cloud +cloudy cloudi +clout clout +clove clove +clover clover +cloves clove +clown clown +clt clt +club club +clubs club +cluck cluck +clue clue +clump clump +clumps clump +clumsily clumsili +clumsiness clumsi +clumsy clumsi +clung clung +cluskie cluski +cluster cluster +clustered cluster +clustering cluster +clusters cluster +clutch clutch +clutched clutch +clutches clutch +clutching clutch +clytia clytia +co co +coach coach +coaches coach +coaching coach +coachmaker coachmak +coachman coachman +coachmen coachmen +coachyard coachyard +coadjutor coadjutor +coal coal +coalesced coalesc +coalescing coalesc +coalition coalit +coalitions coalit +coals coal +coalworth coalworth +coarse coars +coarsely coars +coarsened coarsen +coarseness coars +coarser coarser +coarsest coarsest +coast coast +coasts coast +coat coat +coated coat +coating coat +coatings coat +coats coat +coavins coavin +coavinses coavins +coaxed coax +coaxin coaxin +coaxing coax +coaxingly coax +cob cob +cobbey cobbey +cobbler cobbler +cobblesborough cobblesborough +coburg coburg +cobweb cobweb +cobwebs cobweb +cochlogena cochlogena +cochrane cochran +cock cock +cockaded cockad +cockades cockad +cockatoo cockatoo +cocked cock +cocking cock +cockney cockney +cockroaches cockroach +coco coco +cocoa cocoa +cocoon cocoon +cocos coco +cod cod +coddle coddl +coddled coddl +coddling coddl +code code +codes code +codger codger +codicil codicil +codified codifi +codlings codl +coelum coelum +coerced coerc +coercive coerciv +coeur coeur +coeval coeval +coextensive coextens +coffee coffe +coffeehouse coffeehous +coffers coffer +coffin coffin +coffins coffin +cogitated cogit +cogitating cogit +cogitation cogit +cogitations cogit +cognate cognat +cognisant cognis +cognizant cogniz +cognovits cognovit +cogs cog +coherence coher +coherent coher +cohesion cohes +coil coil +coiled coil +coils coil +coin coin +coinage coinag +coincide coincid +coincided coincid +coincidence coincid +coincidences coincid +coincides coincid +coiner coiner +coiners coiner +coining coin +coins coin +coinstantaneous coinstantan +coinstantaneously coinstantan +coke coke +cold cold +colder colder +coldest coldest +coldly cold +coldness cold +coldnesses cold +colds cold +coleman coleman +coleoptera coleoptera +coleridge coleridg +colias colia +colla colla +collapse collaps +collapsed collaps +collapses collaps +collar collar +collars collar +collateral collater +collation collat +colleague colleagu +colleagues colleagu +collect collect +collected collect +collectedly collect +collecting collect +collection collect +collections collect +collectively collect +collector collector +collectors collector +collects collect +college colleg +collier collier +collieries collieri +colliers collier +colliery collieri +collision collis +collnet collnet +collnett collnett +colloquial colloqui +colloquially colloqui +colloquy colloquy +colman colman +colnett colnett +cologne cologn +colonel colonel +colonia colonia +colonies coloni +colonist colonist +colonists colonist +colonize colon +colonized colon +colonnade colonnad +colonnades colonnad +colony coloni +color color +colorado colorado +colored color +colossal coloss +colour colour +coloured colour +colouring colour +colourless colourless +colours colour +colt colt +colts colt +columbus columbus +column column +columnar columnar +columns column +colymbetes colymbet +com com +comb comb +combat combat +combatants combat +combative combat +combativeness combat +combats combat +combatted combat +combed comb +combination combin +combinations combin +combine combin +combined combin +combines combin +combing comb +combining combin +combs comb +combusted combust +combusting combust +combustion combust +come come +comedies comedi +comedy comedi +comeliness comeli +comely come +comer comer +comers comer +comes come +comestibles comest +cometh cometh +comfort comfort +comfortable comfort +comfortabler comfortabl +comfortablest comfortablest +comfortably comfort +comforted comfort +comforter comfort +comforters comfort +comforting comfort +comfortingly comfort +comfortless comfortless +comforts comfort +comic comic +comical comic +comicality comic +comin comin +coming come +comings come +command command +commandant command +commanded command +commander command +commanding command +commands command +comme comm +commemorate commemor +commemorated commemor +commemoration commemor +commemorative commemor +commence commenc +commenced commenc +commencement commenc +commencements commenc +commences commenc +commencing commenc +commend commend +commendable commend +commendation commend +commendations commend +commended commend +commending commend +commendingly commend +commends commend +comment comment +commentary commentari +commented comment +commenting comment +comments comment +commerce commerc +commercial commerci +commiserating commiser +commiseration commiser +commissariat commissariat +commission commiss +commissioned commiss +commissioner commission +commissioners commission +commissions commiss +commit commit +commits commit +committed commit +committee committe +committees committe +committing commit +commixta commixta +commo commo +commodious commodi +commodities commod +commodity commod +commodore commodor +common common +commoner common +commoners common +commonest commonest +commonl commonl +commonly common +commonplace commonplac +commonplaces commonplac +commons common +commonwealth commonwealth +commotion commot +commotions commot +commttted commtt +commune commune +communicant communic +communicate communic +communicated communic +communicates communic +communicating communic +communication communic +communications communic +communicative communic +communing commune +communion communion +communism communism +communities communiti +community communiti +commuted commut +commuuity commuuiti +como como +compact compact +compactness compact +compacts compact +companies compani +companion companion +companions companion +companionship companionship +company compani +comparable compar +comparative compar +comparatively compar +compare compar +compared compar +compares compar +comparing compar +comparison comparison +comparisons comparison +compartments compart +compass compass +compassion compass +compassionate compassion +compassionated compassion +compassionately compassion +compassionating compassion +compatible compat +compatriots compatriot +compel compel +compelled compel +compelling compel +compels compel +compensate compens +compensated compens +compensating compens +compensation compens +compete compet +competency compet +competent compet +competitions competit +competitor competitor +compilers compil +complacency complac +complacent complac +complacently complac +complain complain +complained complain +complaining complain +complainings complain +complains complain +complaint complaint +complaints complaint +complanata complanata +complement complement +complete complet +completed complet +completel completel +completely complet +completeness complet +completes complet +completest completest +completing complet +completion complet +complex complex +complexion complexion +complexioned complexion +complexions complexion +compliance complianc +complicated complic +complication complic +complications complic +complied compli +complies compli +compliment compliment +complimentary complimentari +complimented compliment +complimenting compliment +compliments compliment +comply compli +complying compli +compn compn +component compon +compose compos +composed compos +composedly compos +composer compos +composes compos +composing compos +compositae composita +composite composit +composition composit +compositions composit +composure composur +compound compound +compounded compound +comprehen comprehen +comprehend comprehend +comprehended comprehend +comprehending comprehend +comprehends comprehend +comprehensible comprehens +comprehension comprehens +comprehensive comprehens +compressed compress +compressible compress +compressing compress +compression compress +comprise compris +comprised compris +comprises compris +comprising compris +compromise compromis +compromised compromis +compromises compromis +compromising compromis +compter compter +comptes compt +compulsion compuls +compulsory compulsori +compunction compunct +computation comput +comrade comrad +comrades comrad +con con +concatenation concaten +concave concav +conceal conceal +concealed conceal +concealing conceal +concealment conceal +concealments conceal +concebida concebida +concede conced +conceded conced +concedes conced +conceit conceit +conceited conceit +conceivable conceiv +conceive conceiv +conceived conceiv +conceives conceiv +conceiving conceiv +concentrate concentr +concentrated concentr +concentrating concentr +concentration concentr +concepcion concepcion +conception concept +conceptions concept +concern concern +concerned concern +concerning concern +concerns concern +concert concert +concerted concert +concertina concertina +concerts concert +concession concess +concessions concess +conchalee conchale +conchas concha +conchological concholog +conciliate concili +conciliated concili +conciliation concili +conciliations concili +conciliatory conciliatori +concise concis +conclave conclav +conclaves conclav +conclude conclud +concluded conclud +concludes conclud +concluding conclud +conclusion conclus +conclusions conclus +conclusive conclus +conclusively conclus +concoct concoct +concocted concoct +concord concord +concourse concours +concretions concret +concubine concubin +concur concur +concurrence concurr +concurrent concurr +concurs concur +condemn condemn +condemnation condemn +condemned condemn +condemning condemn +condemns condemn +condense condens +condensed condens +condescend condescend +condescended condescend +condescending condescend +condescendingly condescend +condescends condescend +condescension condescens +condescent condesc +condeseending condeseend +condign condign +condition condit +conditional condit +conditioned condit +conditions condit +condole condol +condoled condol +condolence condol +condolences condol +condor condor +condors condor +conduce conduc +conducive conduc +conduct conduct +conducted conduct +conducting conduct +conductor conductor +conductors conductor +conductress conductress +conducts conduct +conduits conduit +cone cone +conejos conejo +cones cone +confabulation confabul +confabulations confabul +confectioner confection +confederate confeder +confederates confeder +confer confer +conference confer +conferences confer +conferred confer +conferring confer +confers confer +confervae conferva +confess confess +confessed confess +confessedly confess +confessing confess +confession confess +confessions confess +confessor confessor +confidante confidant +confidantes confidant +confide confid +confided confid +confidence confid +confidences confid +confident confid +confidential confidenti +confidentially confidenti +confidently confid +confides confid +confiding confid +confidingly confid +configuration configur +confine confin +confined confin +confinement confin +confines confin +confining confin +confirm confirm +confirmation confirm +confirmatory confirmatori +confirmed confirm +confirming confirm +confirms confirm +confiscate confisc +confiscation confisc +conflagrations conflagr +conflict conflict +conflicting conflict +conform conform +conforming conform +conformity conform +confound confound +confounded confound +confoundedly confound +confounding confound +confront confront +confronted confront +confronting confront +confronts confront +confuse confus +confused confus +confusedly confus +confuses confus +confusing confus +confusion confus +confute confut +confuting confut +congealed congeal +congelation congel +congeners congen +congenial congeni +congenially congeni +conglomerate conglomer +conglomeration conglomer +congo congo +congratulate congratul +congratulated congratul +congratulating congratul +congratulation congratul +congratulations congratul +congratulatory congratulatori +congregate congreg +congregated congreg +congregation congreg +congruous congruous +conica conica +conical conic +conjecture conjectur +conjectured conjectur +conjectures conjectur +conjecturing conjectur +conjoint conjoint +conjointly conjoint +conjugal conjug +conjunction conjunct +conjuncture conjunctur +conjuration conjur +conjure conjur +conjured conjur +conjures conjur +conjuring conjur +conjuror conjuror +connect connect +connected connect +connecting connect +connection connect +connections connect +connects connect +connexion connexion +connexions connexion +conning con +connivance conniv +connoisseur connoisseur +connubialities connubi +conquer conquer +conquerable conquer +conquered conquer +conquering conquer +conqueror conqueror +conquerors conqueror +conquest conquest +consanguinity consanguin +consarn consarn +conscience conscienc +consciences conscienc +conscientious conscienti +conscientiously conscienti +conscientiousness conscienti +conscious conscious +consciously conscious +consciousness conscious +consecrated consecr +consecrating consecr +consecutive consecut +consecutively consecut +consent consent +consented consent +consenting consent +consents consent +consequence consequ +consequences consequ +consequent consequ +consequential consequenti +consequently consequ +conservatism conservat +conservative conserv +conservatives conserv +conservatories conservatori +conservatory conservatori +conserved conserv +consider consid +considerable consider +considerably consider +considerate consider +considerately consider +consideration consider +considerations consider +considered consid +considering consid +considers consid +consign consign +consigned consign +consigning consign +consignment consign +consist consist +consisted consist +consistency consist +consistent consist +consistently consist +consisting consist +consists consist +consolation consol +consolations consol +consolatory consolatori +console consol +consoled consol +consoles consol +consolidate consolid +consolidated consolid +consolidating consolid +consoling consol +consolingly consol +consols consol +consonant conson +consort consort +consorted consort +consorting consort +conspicuous conspicu +conspicuously conspicu +conspiracy conspiraci +conspirator conspir +conspirators conspir +conspire conspir +conspired conspir +conspiring conspir +constable constabl +constables constabl +constance constanc +constancy constanc +constant constant +constantinople constantinopl +constantly constant +constellations constel +consternation constern +constitootion constitoot +constituencies constitu +constituency constitu +constituent constitu +constituents constitu +constitute constitut +constituted constitut +constitutes constitut +constituting constitut +constitution constitut +constitutional constitut +constitutionally constitut +constrain constrain +constrained constrain +constraining constrain +constrains constrain +constraint constraint +construct construct +constructed construct +constructing construct +construction construct +constructions construct +construe constru +consul consul +consult consult +consultation consult +consultations consult +consulted consult +consulting consult +consults consult +consume consum +consumed consum +consumedly consum +consumers consum +consuming consum +consummate consumm +consummation consumm +consumption consumpt +consumptive consumpt +contact contact +contagion contagion +contagious contagi +contain contain +contained contain +containing contain +contains contain +contaminated contamin +contaminating contamin +contamination contamin +contemned contemn +contemning contemn +contemns contemn +contemplate contempl +contemplated contempl +contemplates contempl +contemplating contempl +contemplation contempl +contemplations contempl +contemplative contempl +contemporaneous contemporan +contemporaneously contemporan +contemporaneousness contemporan +contemporaries contemporari +contempt contempt +contemptible contempt +contemptuous contemptu +contemptuously contemptu +conten conten +contend contend +contended contend +contending contend +contends contend +content content +contented content +contentedly content +contenting content +contention content +contentions content +contentious contenti +contentment content +contents content +contest contest +contested contest +contests contest +continent contin +continental continent +continents contin +contingencies conting +contingency conting +contingent conting +continney continney +continual continu +continually continu +continuance continu +continuation continu +continue continu +continued continu +continues continu +continuing continu +continuous continu +continuously continu +contorted contort +contorting contort +contortions contort +contra contra +contract contract +contracted contract +contracting contract +contraction contract +contractors contractor +contracts contract +contradict contradict +contradicted contradict +contradicting contradict +contradiction contradict +contradictions contradict +contradictory contradictori +contradicts contradict +contradistinction contradistinct +contrairy contrairi +contralto contralto +contrarieties contrarieti +contrary contrari +contrast contrast +contrasted contrast +contrasting contrast +contrasts contrast +contrees contre +contribute contribut +contributed contribut +contributes contribut +contributing contribut +contribution contribut +contributions contribut +contributors contributor +contrite contrit +contrition contrit +contrivance contriv +contrivances contriv +contrive contriv +contrived contriv +contriving contriv +control control +controlled control +controlling control +controls control +controvert controvert +controverted controvert +contumelious contumeli +contumely contum +contusion contus +conundrums conundrum +conurus conurus +convalescence convalesc +convalescent convalesc +convened conven +convenience conveni +convenient conveni +conveniently conveni +convent convent +convention convent +conventional convent +conventionalities convent +conventionality convent +conventionally convent +conventions convent +convents convent +conventual conventu +converge converg +converged converg +convergent converg +conversant convers +conversation convers +conversational convers +conversationally convers +conversations convers +converse convers +conversed convers +converses convers +conversing convers +conversion convers +convert convert +converted convert +convertible convert +converting convert +convertion convert +converts convert +convex convex +convey convey +conveyance convey +conveyancer conveyanc +conveyances convey +conveyed convey +conveying convey +conveys convey +convict convict +convicted convict +conviction convict +convictions convict +convicts convict +convince convinc +convinced convinc +convinces convinc +convincing convinc +convivial convivi +conviviality convivi +convolvulus convolvulus +convulsed convuls +convulsion convuls +convulsions convuls +convulsive convuls +convulsively convuls +conwenient conweni +conwulsions conwuls +coodle coodl +coodleites coodleit +cooing coo +cook cook +cooked cook +cookery cookeri +cooking cook +cookites cookit +cooks cook +cookshop cookshop +cool cool +cooled cool +cooler cooler +coolest coolest +cooling cool +coolly coolli +coolness cool +coom coom +coomin coomin +cooms coom +coop coop +cooped coop +coorch coorch +coot coot +cope cope +copeck copeck +copecks copeck +cophias cophia +copiapo copiapo +copied copi +copies copi +coping cope +copious copious +copiously copious +copper copper +coppers copper +coppery copperi +coppice coppic +copse cops +copy copi +copying copi +coquetry coquetri +coquette coquett +coquettish coquettish +coquille coquill +coquimbo coquimbo +cora cora +coral coral +coralline corallin +corallines corallin +corals coral +corcovado corcovado +cord cord +cordage cordag +corded cord +cordial cordial +cordiality cordial +cordially cordial +cordials cordial +cordillera cordillera +cords cord +corduroy corduroy +core core +corfield corfield +coriaceous coriac +coriolanus coriolanus +cork cork +corks cork +corkscrew corkscrew +corkscrewed corkscrew +cormoran cormoran +cormorant cormor +cormorants cormor +corn corn +corned corn +cornelia cornelia +cornelian cornelian +corner corner +cornered corner +corners corner +cornerstone cornerston +cornfield cornfield +cornice cornic +cornish cornish +corns corn +cornwall cornwal +coronal coron +coroner coron +coroners coron +coronet coronet +coronets coronet +corporal corpor +corporation corpor +corporations corpor +corporeal corpor +corps corp +corpse corps +corpses corps +corpulence corpul +corpulent corpul +corpus corpus +corral corral +corrales corral +corrals corral +correct correct +corrected correct +correcting correct +correction correct +corrective correct +correctly correct +correctness correct +corrects correct +correndera correndera +correspond correspond +corresponded correspond +correspondence correspond +correspondent correspond +correspondents correspond +corresponding correspond +correspondingly correspond +corridor corridor +corrientes corrient +corrobery corroberi +corroborate corrobor +corroborated corrobor +corroboration corrobor +corroborative corrobor +corroboratory corroboratori +corroded corrod +corroding corrod +corrugated corrug +corrupt corrupt +corrupted corrupt +corrupting corrupt +corruption corrupt +corrupts corrupt +corse cors +cortez cortez +corunda corunda +corynetes corynet +cos cos +cosa cosa +coseguina coseguina +cosgrave cosgrav +cosily cosili +cosmopolitan cosmopolitan +cost cost +costal costal +costermongers costermong +costlier costlier +costliest costliest +costly cost +costs cost +costume costum +costumes costum +cosy cosi +cot cot +cote cote +cottage cottag +cottager cottag +cottagers cottag +cottages cottag +cotton cotton +cottoned cotton +cottons cotton +couch couch +couched couch +couches couch +cough cough +coughed cough +coughing cough +coughs cough +could could +couldn couldn +couldst couldst +council council +councillor councillor +councillors councillor +councils council +counsel counsel +counselled counsel +counsellor counsellor +counsellors counsellor +counsels counsel +count count +counted count +countenance counten +countenanced countenanc +countenances counten +counter counter +counteract counteract +counteracted counteract +counterbalance counterbal +counterbalanced counterbalanc +counterfeit counterfeit +counterfeited counterfeit +counterfeiting counterfeit +counterfeits counterfeit +counterpane counterpan +counterpart counterpart +counterplot counterplot +counterpoise counterpois +counters counter +countess countess +countesses countess +counties counti +counting count +countless countless +countree countre +countries countri +countrified countrifi +country countri +countryman countryman +countrymen countrymen +countryrmen countryrmen +countrywomen countrywomen +counts count +county counti +coup coup +couple coupl +coupled coupl +couples coupl +coupling coupl +courage courag +courageous courag +courageously courag +courcy courci +courcys courci +courier courier +course cours +coursed cours +coursers courser +courses cours +coursing cours +court court +courted court +courteous courteous +courteously courteous +courtesies courtesi +courtesy courtesi +courtier courtier +courtiers courtier +courting court +courtly court +courts court +courtship courtship +courtships courtship +courtyard courtyard +courtyards courtyard +cousin cousin +cousinly cousin +cousins cousin +cousinship cousinship +couthouy couthouy +cove cove +covenanted coven +covent covent +coventry coventri +cover cover +covered cover +covering cover +coverings cover +coverlet coverlet +coverley coverley +covers cover +covert covert +covertly covert +coverts covert +coverture covertur +coves cove +covet covet +coveted covet +covetous covet +covetousness covet +coveys covey +cow cow +coward coward +cowardice cowardic +cowardly coward +cowards coward +cowboy cowboy +cowcumber cowcumb +cowed cow +cower cower +cowered cower +cowering cower +cowers cower +cowl cowl +cowley cowley +cows cow +cowshed cowsh +cowslip cowslip +cowslips cowslip +cox cox +coxcomb coxcomb +coxcombical coxcomb +coxcombs coxcomb +coxswain coxswain +coy coy +coyness coy +coypus coypus +cozened cozen +cozily cozili +crab crab +crabbe crabb +crabbed crab +crabberies crabberi +crabs crab +crack crack +cracked crack +cracking crack +crackle crackl +crackled crackl +crackling crackl +cracks crack +cradle cradl +cradles cradl +craft craft +craftier craftier +craftiest craftiest +crafts craft +crafty crafti +crags crag +cram cram +cramble crambl +crammed cram +cramming cram +cramp cramp +cramped cramp +cramping cramp +cranberry cranberri +crancrivora crancrivora +cranes crane +craning crane +cranks crank +crannies cranni +crape crape +crash crash +crashed crash +crashing crash +crater crater +crateriform crateriform +craters crater +cravat cravat +cravats cravat +crave crave +craved crave +craven craven +craving crave +craw craw +crawl crawl +crawled crawl +crawling crawl +crawls crawl +craws craw +cray cray +crayons crayon +craze craze +crazed craze +crazy crazi +creak creak +creaked creak +creaking creak +cream cream +crease creas +creases creas +creasing creas +create creat +created creat +creating creat +creation creation +creations creation +creative creativ +creator creator +creature creatur +creatures creatur +credence credenc +credentials credenti +credibility credibl +credible credibl +credibly credibl +credit credit +creditable credit +creditably credit +credited credit +crediting credit +creditor creditor +creditors creditor +credulity credul +credulous credul +cree cree +creed creed +creek creek +creeks creek +creep creep +creeper creeper +creepers creeper +creeping creep +creeps creep +creetur creetur +creeturs creetur +creevy creevi +crepitans crepitan +crept crept +crescent crescent +crest crest +crested crest +crestfallen crestfallen +crests crest +crevez crevez +crevice crevic +crevices crevic +crew crew +crib crib +cribs crib +crichton crichton +cricket cricket +crickets cricket +cried cri +crier crier +criers crier +cries cri +crime crime +crimes crime +criminal crimin +criminality crimin +criminals crimin +criminate crimin +criminations crimin +crimson crimson +crimsoned crimson +cringe cring +cringing cring +cringingly cring +crinoline crinolin +cripple crippl +crippled crippl +crippler crippler +crisia crisia +crisis crisi +crisp crisp +cristal cristal +cristatus cristatus +cristiandad cristiandad +cristianos cristiano +criterion criterion +critic critic +critical critic +criticise criticis +criticised criticis +criticism critic +criticisms critic +criticize critic +criticizing critic +critics critic +critique critiqu +critturs crittur +croak croak +croaked croak +croaking croak +croaks croak +crockery crockeri +crockford crockford +crocking crock +crocodile crocodil +crocodiles crocodil +croesus croesus +crois croi +crook crook +crooked crook +crookedly crook +crooks crook +crop crop +cropley cropley +crops crop +cros cros +cross cross +crosse cross +crossed cross +crosses cross +crossgrained crossgrain +crossin crossin +crossing cross +crossings cross +crossly crossli +crost crost +crotchet crotchet +crotchets crotchet +crouched crouch +crouches crouch +crouching crouch +croup croup +crow crow +crowbar crowbar +crowd crowd +crowded crowd +crowding crowd +crowds crowd +crowed crow +crowin crowin +crowing crow +crowl crowl +crown crown +crowned crown +crowning crown +crowns crown +crowquill crowquil +crows crow +crucified crucifi +crucify crucifi +crucifying crucifi +crude crude +crudely crude +crudest crudest +cruel cruel +cruellest cruellest +cruelly cruelli +cruelties cruelti +cruelty cruelti +cruenta cruenta +cruet cruet +cruise cruis +cruises cruis +crumb crumb +crumber crumber +crumble crumbl +crumbled crumbl +crumbling crumbl +crumbs crumb +crumlinwallinwer crumlinwallinw +crummles crumml +crummleses crummles +crumpet crumpet +crumpets crumpet +crumpled crumpl +crumpling crumpl +crumpy crumpi +crupper crupper +crusade crusad +crusader crusad +crusaders crusad +crusades crusad +crusading crusad +crush crush +crushed crush +crushes crush +crushing crush +crusoe cruso +crust crust +crustacea crustacea +crustaceous crustac +crusts crust +crusty crusti +crutches crutch +cruz cruz +cry cri +crying cri +crypt crypt +cryptogamic cryptogam +crystal crystal +crystalline crystallin +crystallization crystal +crystallized crystal +crystals crystal +crystial crystial +ct ct +ctenomys ctenomi +cu cu +cubes cube +cubic cubic +cubs cub +cucao cucao +cuchilla cuchilla +cuckoo cuckoo +cuckoos cuckoo +cucumber cucumb +cucumbers cucumb +cudgel cudgel +cudgelled cudgel +cudgels cudgel +cudico cudico +cue cue +cuentas cuenta +cuero cuero +cues cue +cueva cueva +cuff cuff +cuffs cuff +cuffy cuffi +cufre cufr +cul cul +culpability culpabl +culpeu culpeu +culprit culprit +cultivate cultiv +cultivated cultiv +cultivating cultiv +cultivation cultiv +culture cultur +culver culver +cum cum +cumber cumber +cumberland cumberland +cumbre cumbr +cumbrously cumbrous +cumfbler cumfbler +cumin cumin +cuming cume +cummin cummin +cumnor cumnor +cums cum +cumuli cumuli +cunicularia cunicularia +cunicularius cunicularius +cunning cun +cunningest cunningest +cunningly cun +cup cup +cupboard cupboard +cupboards cupboard +cupid cupid +cupidity cupid +cupids cupid +cupola cupola +cups cup +cur cur +cura cura +curacy curaci +curate curat +curb curb +curbed curb +curdle curdl +curds curd +cure cure +cured cure +cures cure +curing cure +curiosities curios +curiosity curios +curious curious +curiously curious +curl curl +curled curl +curlew curlew +curling curl +curlings curl +curls curl +curly cur +curmudgeon curmudgeon +curragh curragh +currant currant +currants currant +currency currenc +current current +currently current +currents current +curricle curricl +curries curri +curry curri +curs cur +curse curs +cursed curs +curses curs +cursing curs +cursitor cursitor +cursory cursori +curt curt +curtain curtain +curtained curtain +curtaining curtain +curtains curtain +curtness curt +curtsey curtsey +curtseyed curtsey +curtseying curtsey +curtseys curtsey +curtsied curtsi +curtsy curtsi +curtsying curtsi +curtsys curtsi +curvature curvatur +curve curv +curved curv +curves curv +curvidens curviden +curving curv +cushion cushion +cushioned cushion +cushioning cushion +cushions cushion +custodian custodian +custodians custodian +custody custodi +custom custom +customarily customarili +customary customari +customer custom +customers custom +customs custom +cut cut +cutaneous cutan +cute cute +cutlass cutlass +cutler cutler +cutlery cutleri +cutlets cutlet +cuts cut +cutter cutter +cutters cutter +cutthroat cutthroat +cutting cut +cuttle cuttl +cuvier cuvier +cycle cycl +cycles cycl +cyclopean cyclopean +cylinder cylind +cylinders cylind +cylindrical cylindr +cymbal cymbal +cymindis cymindi +cynara cynara +cynic cynic +cynical cynic +cynicism cynic +cynucus cynucus +cyperus cyperus +cypress cypress +cyprus cyprus +cyrus cyrus +cyttaria cyttaria +d d +da da +daark daark +dab dab +dabber dabber +dabbing dab +dabbled dabbl +dabblers dabbler +dabbling dabbl +dabs dab +dacelo dacelo +dacia dacia +dadass dadass +daft daft +dagestan dagestan +dagger dagger +daggers dagger +dail dail +daily daili +dainties dainti +daintily daintili +dainty dainti +dairy dairi +dais dai +daisy daisi +dale dale +dalliance dallianc +dallied dalli +dally dalli +damage damag +damaged damag +damages damag +damaging damag +damask damask +dame dame +dames dame +damme damm +dammed dam +damn damn +damnable damnabl +damnably damnabl +damnation damnat +damnatory damnatori +damned damn +damp damp +damped damp +damper damper +dampest dampest +dampier dampier +damping damp +dampness damp +damsel damsel +damsels damsel +dan dan +dance danc +danced danc +dancer dancer +dancers dancer +dances danc +dancing danc +dancings danc +dandified dandifi +dandling dandl +dandy dandi +dandyism dandyism +dang dang +danger danger +dangerous danger +dangerously danger +dangers danger +dangle dangl +dangling dangl +daniel daniel +daniell daniel +dank dank +danke dank +dans dan +danse dans +dante dant +dapibus dapibus +darby darbi +dare dare +dared dare +daren daren +dares dare +daresay daresay +daring dare +dark dark +darken darken +darkened darken +darkening darken +darkens darken +darker darker +darkest darkest +darkly dark +darkness dark +darling darl +darlings darl +darn darn +darned darn +darning darn +dart dart +darted dart +darting dart +darts dart +darwin darwin +darwinian darwinian +darwinii darwinii +darya darya +das das +dash dash +dashed dash +dashes dash +dashing dash +dastard dastard +dastardly dastard +dasypus dasypus +data data +date date +dated date +dates date +dating date +daubed daub +daubeny daubeni +daubney daubney +daughter daughter +daughters daughter +daunt daunt +daunted daunt +daverous daver +david david +davies davi +davis davi +davy davi +dawdle dawdl +dawdling dawdl +dawlish dawlish +dawn dawn +dawned dawn +dawning dawn +dawns dawn +day day +daybreak daybreak +daylight daylight +days day +daytime daytim +dayvle dayvl +dazed daze +dazzle dazzl +dazzled dazzl +dazzler dazzler +dazzling dazzl +dcar dcar +de de +dea dea +dead dead +deaden deaden +deadened deaden +deadens deaden +deadliest deadliest +deadlock deadlock +deadly dead +deadwood deadwood +deaf deaf +deafen deafen +deafening deafen +deafness deaf +deal deal +dealer dealer +dealers dealer +dealing deal +dealings deal +dealt dealt +dean dean +deane dean +deans dean +dear dear +dearer dearer +dearest dearest +dearly dear +dears dear +dearth dearth +dease deas +death death +deathbed deathb +deathless deathless +deathlike deathlik +deathly death +deaths death +debacle debacl +debar debar +debarred debar +debase debas +debased debas +debasement debas +debasing debas +debate debat +debated debat +debater debat +debates debat +debating debat +debauch debauch +debauchery debaucheri +debilitated debilit +debility debil +debris debri +debt debt +debtor debtor +debtors debtor +debts debt +dec dec +decamp decamp +decamped decamp +decanter decant +decanters decant +decapitated decapit +decay decay +decayed decay +decaying decay +decease deceas +deceased deceas +deceit deceit +deceitful deceit +deceitfulness deceit +deceive deceiv +deceived deceiv +deceivers deceiv +deceives deceiv +deceiving deceiv +december decemb +decencies decenc +decency decenc +decent decent +decently decent +deception decept +deceptions decept +deceptive decept +decide decid +decided decid +decidedly decid +decides decid +deciding decid +deciduous decidu +decimal decim +decimals decim +decipher deciph +deciphered deciph +deciphering deciph +decision decis +decisions decis +decisive decis +decisively decis +deck deck +decked deck +decking deck +declaim declaim +declaimed declaim +declamation declam +declaration declar +declarations declar +declaratory declaratori +declare declar +declared declar +declares declar +declaring declar +decline declin +declined declin +declines declin +declining declin +decompose decompos +decomposed decompos +decomposing decompos +decomposition decomposit +decorate decor +decorated decor +decorates decor +decoration decor +decorations decor +decorative decor +decorous decor +decorously decor +decorum decorum +decoy decoy +decrease decreas +decreased decreas +decreasing decreas +decree decre +decreed decre +decrees decre +decrepit decrepit +decrepitude decrepitud +dedicated dedic +dedlock dedlock +dedlocks dedlock +deduced deduc +deducible deduc +deduct deduct +deducted deduct +deducting deduct +deduction deduct +deductions deduct +dee dee +deead deead +deed deed +deedn deedn +deeds deed +deein deein +deem deem +deemed deem +deeming deem +deems deem +deep deep +deepen deepen +deepened deepen +deepening deepen +deepens deepen +deeper deeper +deepest deepest +deeply deepli +deer deer +deering deer +defacing defac +defalcation defalc +default default +defeat defeat +defeated defeat +defect defect +defection defect +defective defect +defects defect +defence defenc +defenceless defenceless +defend defend +defendant defend +defendants defend +defended defend +defenders defend +defending defend +defer defer +deference defer +deferential deferenti +deferentially deferenti +deferred defer +deferring defer +defers defer +defiance defianc +defiances defianc +defiant defiant +defiantly defiant +deficiencies defici +deficiency defici +deficient defici +defied defi +defies defi +defile defil +defiled defil +defiles defil +define defin +defined defin +defining defin +definite definit +definitely definit +definition definit +definitions definit +definitively definit +deflected deflect +deflecting deflect +deformed deform +deformities deform +deformity deform +defrauded defraud +defrauding defraud +defray defray +defrayed defray +defraying defray +deftly deft +defunct defunct +defy defi +defying defi +degage degag +degenerate degener +degenerated degener +degenerating degener +degeneration degener +degradation degrad +degrade degrad +degraded degrad +degrading degrad +degree degre +degrees degre +degs deg +deified deifi +deigned deign +deigning deign +deinornis deinorni +deity deiti +dejected deject +dejectedly deject +dejection deject +del del +delaval delav +delavals delav +delay delay +delayed delay +delaying delay +delays delay +delectable delect +delegates deleg +deleterious deleteri +deliberate deliber +deliberated deliber +deliberately deliber +deliberating deliber +deliberation deliber +deliberations deliber +delicacies delicaci +delicacy delicaci +delicate delic +delicately delic +delicater delicat +delicious delici +deliciously delici +delight delight +delighted delight +delightful delight +delightfully delight +delighting delight +delights delight +delinquency delinqu +deliquescent deliquesc +delirious deliri +deliriously deliri +delirium delirium +deliver deliv +deliverance deliver +delivered deliv +deliverer deliver +delivering deliv +delivers deliv +delivery deliveri +delude delud +deluded delud +deludes delud +deluding delud +deluge delug +deluges delug +delusion delus +delusions delus +delusive delus +delving delv +dem dem +demagogue demagogu +demand demand +demanded demand +demanding demand +demands demand +demarlii demarlii +demd demd +demder demder +demdest demdest +demeaning demean +demeanour demeanour +demented dement +dementyev dementyev +demerits demerit +demersa demersa +demi demi +demigods demigod +demmit demmit +demneble demnebl +demnebly demnebl +demnition demnit +democracy democraci +democratic democrat +demolished demolish +demolition demolit +demon demon +demoniacs demoniac +demons demon +demonstrate demonstr +demonstrated demonstr +demonstrates demonstr +demonstration demonstr +demonstrations demonstr +demonstrative demonstr +demoralisation demoralis +demoralize demor +demoralized demor +demur demur +demure demur +demurely demur +demurred demur +den den +denial denial +denied deni +denies deni +denizens denizen +denmark denmark +dennison dennison +denominated denomin +denomination denomin +denominations denomin +denote denot +denoted denot +denotes denot +denoting denot +denouement denouement +denounce denounc +denounced denounc +denouncing denounc +dens den +dense dens +densely dens +denser denser +densest densest +density densiti +dent dent +dentist dentist +dentistical dentist +denudation denud +denuded denud +denuding denud +denunciation denunci +denunciations denunci +deny deni +denying deni +deodara deodara +deos deo +depairture depairtur +depart depart +departed depart +departing depart +department depart +departs depart +departure departur +departures departur +depend depend +dependant depend +dependants depend +depended depend +dependence depend +dependencies depend +dependent depend +dependents depend +depending depend +depends depend +depict depict +depicted depict +depicter depict +depicts depict +deplorable deplor +deplorably deplor +deplore deplor +deplored deplor +deploring deplor +deploy deploy +deport deport +deportation deport +deporting deport +deportment deport +depose depos +deposed depos +deposer depos +deposit deposit +deposited deposit +depositing deposit +deposition deposit +depository depositori +deposits deposit +depraved deprav +depraving deprav +depravity deprav +deprecating deprec +deprecation deprec +depreciate depreci +depreciated depreci +depreciating depreci +depreciation depreci +depress depress +depressed depress +depresses depress +depressing depress +depression depress +depressions depress +deprivation depriv +deprive depriv +deprived depriv +deprives depriv +depriving depriv +deptford deptford +depth depth +depths depth +deputation deput +deputations deput +depute deput +deputed deput +deputies deputi +deputy deputi +der der +deranged derang +derangement derang +derby derbi +derided derid +derision deris +derisive deris +derisively deris +derivable deriv +derivation deriv +derive deriv +derived deriv +derives deriv +deriving deriv +dermestes dermest +derogatory derogatori +derwent derwent +des des +desc desc +descanted descant +descanting descant +descen descen +descend descend +descendant descend +descendants descend +descended descend +descendin descendin +descending descend +descends descend +descent descent +describe describ +described describ +describes describ +describing describ +descried descri +descries descri +descrip descrip +description descript +descriptions descript +descriptive descript +descripts descript +descry descri +desert desert +deserted desert +deserting desert +desertion desert +deserts desert +deserve deserv +deserved deserv +deservedly deserv +deserves deserv +deserving deserv +design design +designates design +designation design +designed design +designer design +designing design +designs design +desirable desir +desire desir +desired desir +desires desir +desiring desir +desirous desir +desist desist +desisted desist +desists desist +desk desk +desks desk +desmodus desmodus +desolate desol +desolated desol +desolately desol +desolateness desol +desolation desol +desolee desole +despair despair +despaired despair +despairing despair +despairingly despair +despairs despair +despatch despatch +despatched despatch +desperate desper +desperately desper +desperation desper +despicable despic +despicably despic +despise despis +despised despis +despises despis +despising despis +despite despit +despoblado despoblado +despoil despoil +despoiled despoil +despond despond +desponded despond +despondence despond +despondency despond +despondent despond +despondently despond +desponding despond +despondingly despond +despot despot +despotic despot +despotism despot +dessert dessert +desserts dessert +destination destin +destinction destinct +destined destin +destinies destini +destiny destini +destitute destitut +destitution destitut +destro destro +destroy destroy +destroyed destroy +destroyer destroy +destroyers destroy +destroying destroy +destroys destroy +destruction destruct +destructive destruct +desultory desultori +det det +detach detach +detached detach +detaches detach +detachment detach +detail detail +detailed detail +details detail +detain detain +detained detain +detainer detain +detaining detain +detect detect +detected detect +detecting detect +detection detect +detective detect +detects detect +detenined detenin +detention detent +deter deter +deteriorate deterior +deteriorated deterior +deteriorating deterior +determination determin +determine determin +determined determin +determines determin +determining determin +deterred deter +detest detest +detestable detest +detestation detest +detested detest +detesting detest +dethronement dethron +detour detour +detract detract +detriment detriment +detrimental detriment +detritus detritus +deuce deuc +deuced deuc +deum deum +deus deus +deux deux +devastate devast +devastation devast +develop develop +developed develop +developes develop +developing develop +development develop +develops develop +deviated deviat +deviation deviat +device devic +devices devic +devil devil +devilish devilish +devilry devilri +devils devil +devious devious +devise devis +devised devis +deviser devis +devising devis +devoid devoid +devoir devoir +devolved devolv +devolves devolv +devon devon +devonian devonian +devonport devonport +devonshire devonshir +devote devot +devoted devot +devotedly devot +devotedness devoted +devotes devot +devoting devot +devotion devot +devotions devot +devour devour +devoured devour +devourers devour +devouring devour +devout devout +devoutly devout +dew dew +dewdrop dewdrop +dewdrops dewdrop +deweloping dewelop +dewiness dewi +dews dew +dewy dewi +dexterity dexter +dexterous dexter +dexterously dexter +dey dey +deyvle deyvl +deyvlish deyvlish +di di +diabolical diabol +diabolicus diabolicus +diagnosed diagnos +diagonal diagon +dial dial +dialect dialect +dialects dialect +dialogue dialogu +dialogues dialogu +dials dial +diamanten diamanten +diameter diamet +diametrically diametr +diamond diamond +diamonds diamond +dianaea dianaea +diaphragm diaphragm +diappointments diappoint +diaries diari +diary diari +diatribes diatrib +dibabs dibab +dibabses dibabs +dick dick +dickens dicken +dicks dick +dictate dictat +dictated dictat +dictates dictat +dictating dictat +dictation dictat +dictator dictat +dictatorial dictatori +dictionary dictionari +dictum dictum +did did +diddler diddler +didelphis didelphi +didn didn +didst didst +die die +died die +dieffenbach dieffenbach +diego diego +dieman dieman +diemen diemen +diernan diernan +dies die +diet diet +differ differ +differed differ +difference differ +differences differ +different differ +differently differ +differing differ +differs differ +difficult difficult +difficulties difficulti +difficulty difficulti +diffidence diffid +diffident diffid +diffidently diffid +diffused diffus +diffusing diffus +diffusion diffus +dig dig +digby digbi +diges dige +digest digest +digester digest +digestio digestio +digestion digest +digestive digest +digger digger +digging dig +digitated digit +digitatus digitatus +dignified dignifi +dignities digniti +dignity digniti +digression digress +dilapidated dilapid +dilapidation dilapid +dilatation dilat +dilate dilat +dilated dilat +dilates dilat +dilating dilat +dilatory dilatori +dilemma dilemma +dilettanti dilettanti +diligence dilig +diligent dilig +diligently dilig +diluted dilut +dim dim +dimension dimens +dimensions dimens +diminish diminish +diminished diminish +diminishes diminish +diminishing diminish +diminution diminut +diminutive diminut +dimity dimiti +dimly dim +dimmed dim +dimple dimpl +dimpled dimpl +dimpling dimpl +din din +dine dine +dined dine +dines dine +ding ding +dingey dingey +dingleby dinglebi +dingo dingo +dingy dingi +dining dine +dinner dinner +dinners dinner +dinnot dinnot +dint dint +diocese dioces +diodon diodon +diopaea diopaea +diorgeenes diorgeen +dios dio +dip dip +diplomacy diplomaci +diplomatic diplomat +diplomatical diplomat +diplomats diplomat +dipped dip +dipping dip +dips dip +diptera diptera +dire dire +direcfly direcfli +direct direct +directed direct +directing direct +direction direct +directions direct +directly direct +director director +directors director +directory directori +directress directress +directs direct +direfully dire +dirt dirt +dirtied dirti +dirtier dirtier +dirtiest dirtiest +dirty dirti +disable disabl +disabled disabl +disadvantage disadvantag +disadvantages disadvantag +disagree disagre +disagreeable disagre +disagreeably disagre +disagreed disagre +disagreeing disagre +disagreement disagr +disappear disappear +disappearance disappear +disappeared disappear +disappearing disappear +disappears disappear +disappoint disappoint +disappointed disappoint +disappointing disappoint +disappointment disappoint +disappointments disappoint +disappoints disappoint +disapprobation disapprob +disapproval disapprov +disapprove disapprov +disapproved disapprov +disapproves disapprov +disapproving disapprov +disarm disarm +disarmed disarm +disarming disarm +disarranged disarrang +disarrangement disarrang +disarray disarray +disaster disast +disastrous disastr +disavow disavow +disavowal disavow +disavowals disavow +disband disband +disbelief disbelief +disbelieve disbeliev +disbelieved disbeliev +disbelieving disbeliev +discard discard +discarded discard +discern discern +discerned discern +discernible discern +discerning discern +discernment discern +discharge discharg +discharged discharg +discharges discharg +discharging discharg +disciples discipl +disciplinary disciplinari +discipline disciplin +disciplined disciplin +disciplining disciplin +disclaimed disclaim +disclose disclos +disclosed disclos +disclosing disclos +disclosure disclosur +disclosures disclosur +discoloration discolor +discoloured discolour +discolouring discolour +discomfited discomfit +discomfiture discomfitur +discomfort discomfort +discomforts discomfort +discompose discompos +discomposed discompos +discomposure discomposur +disconcert disconcert +disconcerted disconcert +disconnected disconnect +disconsolate disconsol +disconsolately disconsol +discontended discontend +discontent discont +discontented discont +discontentedly discont +discontinuance discontinu +discontinue discontinu +discontinued discontinu +discord discord +discordant discord +discordantly discord +discords discord +discount discount +discountenanced discountenanc +discounters discount +discounting discount +discourage discourag +discouraged discourag +discouragement discourag +discourages discourag +discouraging discourag +discourse discours +discoursed discours +discourses discours +discoursing discours +discourteous discourt +discourtesy discourtesi +discover discov +discoverable discover +discovered discov +discoverer discover +discoverers discover +discoveries discoveri +discoverin discoverin +discovering discov +discovers discov +discovery discoveri +discredit discredit +discreditable discredit +discreet discreet +discreetest discreetest +discreetly discreet +discretion discret +discriminate discrimin +discrimination discrimin +discursive discurs +discuss discuss +discussed discuss +discusses discuss +discussing discuss +discussion discuss +discussions discuss +disdain disdain +disdained disdain +disdainful disdain +disdainfully disdain +disdaining disdain +disease diseas +diseased diseas +diseases diseas +disembarrassed disembarrass +disenchanted disench +disenchantment disenchant +disengage disengag +disengaged disengag +disengages disengag +disengaging disengag +disentangle disentangl +disentangles disentangl +disestablished disestablish +disfavour disfavour +disfigured disfigur +disfigurement disfigur +disfigurements disfigur +disgorged disgorg +disgorging disgorg +disgrace disgrac +disgraced disgrac +disgraceful disgrac +disgraces disgrac +disgracing disgrac +disguise disguis +disguised disguis +disguises disguis +disguising disguis +disgust disgust +disgusted disgust +disgusting disgust +disgustingly disgust +disgusts disgust +dish dish +dishabille dishabill +disheartened dishearten +disheartening dishearten +dished dish +dishes dish +dishevelled dishevel +dishonest dishonest +dishonestly dishonest +dishonesty dishonesti +dishonour dishonour +dishonourable dishonour +dishonoured dishonour +dishonouring dishonour +disillusion disillus +disillusioned disillus +disinclination disinclin +disinclined disinclin +disinherit disinherit +disinherits disinherit +disintegration disintegr +disinterested disinterest +disinterestedly disinterest +disinterestedness disinterested +disjoin disjoin +disjointed disjoint +disk disk +dislike dislik +disliked dislik +dislikes dislik +disliking dislik +dislocated disloc +dislocation disloc +dislodge dislodg +dismal dismal +dismally dismal +dismantle dismantl +dismantled dismantl +dismay dismay +dismayed dismay +dismiss dismiss +dismissal dismiss +dismissed dismiss +dismisses dismiss +dismissing dismiss +dismount dismount +dismounted dismount +disobedience disobedi +disobedient disobedi +disobey disobey +disobeyed disobey +disorder disord +disordered disord +disorderly disord +disorders disord +disorganization disorgan +disown disown +disowned disown +disparage disparag +disparagement disparag +disparaging disparag +dispassionate dispassion +dispassionately dispassion +dispatch dispatch +dispatched dispatch +dispatching dispatch +dispel dispel +dispelled dispel +dispensation dispens +dispense dispens +dispensed dispens +dispenses dispens +dispensing dispens +disperse dispers +dispersed dispers +disperses dispers +dispersing dispers +dispirited dispirit +displaced displac +displacement displac +displaces displac +displacing displac +display display +displayed display +displaying display +displays display +displease displeas +displeased displeas +displeases displeas +displeasing displeas +displeasure displeasur +disposal dispos +dispose dispos +disposed dispos +disposes dispos +disposing dispos +disposition disposit +dispositions disposit +dispossess dispossess +dispossessed dispossess +dispraise disprais +disproof disproof +disproportionate disproportion +disproportionately disproportion +disproved disprov +disproving disprov +disputation disput +disputations disput +dispute disput +disputed disput +disputes disput +disputing disput +disqualification disqualif +disquiet disquiet +disquietude disquietud +disregard disregard +disregarded disregard +disregardful disregard +disregarding disregard +disregards disregard +disreputable disreput +disrespect disrespect +disrespectful disrespect +disrespectfully disrespect +disruption disrupt +dissatisfaction dissatisfact +dissatisfied dissatisfi +dissected dissect +dissecting dissect +dissection dissect +dissemble dissembl +dissembler dissembl +disseminated dissemin +dissemination dissemin +dissension dissens +dissensions dissens +dissent dissent +dissenter dissent +dissertation dissert +dissimilar dissimilar +dissimulation dissimul +dissipate dissip +dissipated dissip +dissipating dissip +dissipation dissip +dissolute dissolut +dissolution dissolut +dissolve dissolv +dissolved dissolv +dissuade dissuad +dissuaded dissuad +dissuasions dissuas +distanc distanc +distance distanc +distanced distanc +distances distanc +distant distant +distantly distant +distaste distast +distasteful distast +distempered distemp +distended distend +distending distend +distilled distil +distinct distinct +distinction distinct +distinctions distinct +distinctive distinct +distinctly distinct +distinctness distinct +distinguish distinguish +distinguishable distinguish +distinguished distinguish +distinguishes distinguish +distinguishing distinguish +distinguons distinguon +distort distort +distorted distort +distortion distort +distortions distort +distract distract +distracted distract +distractedly distract +distracting distract +distraction distract +distracts distract +distraught distraught +distress distress +distressed distress +distresses distress +distressful distress +distressfully distress +distressing distress +distribute distribut +distributed distribut +distributing distribut +distribution distribut +district district +districts district +distrust distrust +distrusted distrust +distrustful distrust +distrustfully distrust +disturb disturb +disturbance disturb +disturbances disturb +disturbed disturb +disturbing disturb +disturbs disturb +disused disus +ditch ditch +ditches ditch +ditching ditch +ditties ditti +ditto ditto +ditty ditti +diurnal diurnal +divan divan +dive dive +dived dive +diver diver +diverge diverg +diverged diverg +divergence diverg +diverging diverg +divers diver +diverse divers +diversified diversifi +diversifying diversifi +diversion divers +diversions divers +diversity divers +divert divert +diverted divert +diverting divert +dives dive +divest divest +divested divest +divesting divest +divide divid +divided divid +dividend dividend +divides divid +dividing divid +divine divin +divined divin +diviner divin +divines divin +diving dive +divining divin +divinities divin +divinity divin +divisio divisio +division divis +divisions divis +divn divn +divorce divorc +divorced divorc +divulge divulg +divulges divulg +dixon dixon +dizzier dizzier +dizziness dizzi +dizzy dizzi +dmitri dmitri +do do +doant doant +dobrizhoffen dobrizhoffen +dobrizhoffer dobrizhoff +docile docil +dock dock +docks dock +dockyard dockyard +dockyards dockyard +doctor doctor +doctoring doctor +doctors doctor +doctrine doctrin +doctrines doctrin +document document +documentary documentari +documents document +dod dod +dodge dodg +dodged dodg +dodges dodg +dodging dodg +dodo dodo +doe doe +doers doer +does doe +doesn doesn +dog dog +dogged dog +doggedly dog +doggedness dogged +doggies doggi +dogging dog +dogs dog +doin doin +doing do +doings do +dole dole +doleful dole +dolefully dole +dolichonyx dolichonyx +doll doll +dollar dollar +dollars dollar +dolls doll +dolly dolli +dolorous dolor +dolt dolt +dom dom +domain domain +domains domain +dome dome +domestic domest +domesticated domest +domestication domest +domestics domest +domiciled domicil +domidor domidor +domidors domidor +dominant domin +domination domin +domineer domin +domineered domin +domineering domin +domingo domingo +dominion dominion +dominions dominion +domino domino +domo domo +don don +donatia donatia +donation donat +done done +dong dong +donkey donkey +donkeys donkey +donnez donnez +donny donni +donnys donni +dont dont +dooble doobl +dooced dooc +doodle doodl +doodleites doodleit +doom doom +doomed doom +dooms doom +doomsday doomsday +doon doon +doonstairs doonstair +door door +doorkeeper doorkeep +doors door +doorway doorway +doorways doorway +doos doo +doozen doozen +dora dora +doris dori +dorker dorker +dormant dormant +dormitory dormitori +dormouse dormous +dorsal dorsal +dose dose +dosed dose +doses dose +dost dost +dostoevsky dostoevski +dotage dotag +dotard dotard +dote dote +doted dote +dotes dote +doth doth +dotheboys dotheboy +dothebys dothebi +doting dote +dots dot +dotted dot +double doubl +doubled doubl +doubleday doubleday +doubles doubl +doubling doubl +doubly doubli +doubt doubt +doubted doubt +doubtful doubt +doubtfully doubt +doubting doubt +doubtingly doubt +doubtless doubtless +doubts doubt +douches douch +douglas dougla +dounia dounia +dourov dourov +dove dove +dover dover +dovercourt dovercourt +doves dove +dovetailedness dovetailed +doveton doveton +dowager dowag +dowagers dowag +dowdles dowdl +dowdy dowdi +dower dower +down down +downcast downcast +downfall downfal +downfallings downfal +downhearted downheart +downing down +downright downright +downs down +downstairs downstair +downward downward +downwards downward +downy downi +dowry dowri +doze doze +dozed doze +dozen dozen +dozens dozen +dozenth dozenth +dozes doze +dozing doze +dr dr +dra dra +drab drab +drabs drab +draft draft +drafts draft +drag drag +dragged drag +dragging drag +draggled draggl +draggletails draggletail +dragon dragon +dragoon dragoon +dragooning dragoon +dragoons dragoon +drags drag +drain drain +drainage drainag +drained drain +draining drain +drains drain +drake drake +drakes drake +dram dram +drama drama +dramatic dramat +dramatically dramat +dramaticus dramaticus +dramatise dramatis +dramatised dramatis +dramatist dramatist +dramatists dramatist +drank drank +drap drap +draperies draperi +drapery draperi +drat drat +draught draught +draughts draught +draughtsman draughtsman +draw draw +drawback drawback +drawbacks drawback +drawbridge drawbridg +drawed draw +drawer drawer +drawers drawer +drawing draw +drawings draw +drawl drawl +drawled drawl +drawling drawl +drawls drawl +drawn drawn +draws draw +dray dray +drays dray +dread dread +dreaded dread +dreadful dread +dreadfully dread +dreading dread +dreadnought dreadnought +dream dream +dreamed dream +dreamer dreamer +dreamily dreamili +dreaminess dreami +dreaming dream +dreamings dream +dreams dream +dreamt dreamt +dreamy dreami +drear drear +dreariness dreari +dreary dreari +dregs dreg +drenched drench +dresden dresden +dress dress +dressed dress +dresser dresser +dresses dress +dressing dress +dressmaker dressmak +dressmakers dressmak +dressmaking dressmak +drest drest +drew drew +driblets driblet +dried dri +drier drier +dries dri +driest driest +drift drift +drifte drift +drifted drift +drifting drift +drifts drift +drigg drigg +drilled drill +drily drili +drink drink +drinkable drinkabl +drinker drinker +drinkers drinker +drinking drink +drinkings drink +drinks drink +drip drip +dripping drip +drips drip +drive drive +drivelling drivel +driven driven +driver driver +drivers driver +drives drive +driving drive +drizzle drizzl +drizzling drizzl +drizzly drizzli +dro dro +droite droit +droll droll +drollery drolleri +drolly drolli +drone drone +drones drone +droonk droonk +droop droop +drooped droop +drooping droop +droops droop +drop drop +droppe dropp +dropped drop +dropping drop +droppings drop +drops drop +dropsy dropsi +dross dross +drought drought +droughts drought +drove drove +drover drover +drovers drover +droves drove +drown drown +drownded drownd +drowned drown +drowning drown +drowsily drowsili +drowsiness drowsi +drowsy drowsi +drubbing drub +drudge drudg +drudgery drudgeri +drudges drudg +drugs drug +druidical druidic +drum drum +drummer drummer +drummers drummer +drummond drummond +drummonds drummond +drums drum +drunk drunk +drunkard drunkard +drunkards drunkard +drunken drunken +drunkenness drunken +drury druri +dry dri +dryer dryer +drying dri +dryly dryli +dryness dryness +dst dst +du du +dubious dubious +dublin dublin +ducal ducal +duchess duchess +duchesses duchess +duchy duchi +duck duck +ducking duck +ducklings duckl +ducks duck +duclida duclida +dudgeon dudgeon +due due +duel duel +duenna duenna +dues due +duets duet +duffer duffer +duffy duffi +dug dug +dugong dugong +duke duke +dukedom dukedom +dukes duke +dulcet dulcet +dull dull +dullards dullard +duller duller +dullest dullest +dullish dullish +dullness dull +dully dulli +dulness dul +dulwich dulwich +duly duli +dumb dumb +dumbbell dumbbel +dumbfounded dumbfound +dumbfoundered dumbfound +dumbly dumbl +dummy dummi +dumpling dumpl +dun dun +duncan duncan +dunes dune +dung dung +dungeon dungeon +dungeons dungeon +dunghill dunghil +dunheved dunhev +dunlops dunlop +duns dun +duodecimos duodecimo +duodenum duodenum +dupe dupe +duped dupe +duping dupe +duplicate duplic +duplicates duplic +duplicity duplic +durability durabl +duratio duratio +duration durat +durden durden +durer durer +durham durham +during dure +dursn dursn +durst durst +durstn durstn +dushkin dushkin +dusk dusk +duskier duskier +dusky duski +dussauts dussaut +dust dust +dusted dust +duster duster +dustier dustier +dusting dust +dustman dustman +dustn dustn +dusty dusti +dutch dutch +dutchman dutchman +duties duti +dutiful duti +dutifully duti +duty duti +dwarf dwarf +dwell dwell +dweller dweller +dwelling dwell +dwellings dwell +dwells dwell +dwelt dwelt +dwindled dwindl +dwindling dwindl +dy dy +dye dye +dyed dy +dyer dyer +dyes dye +dying die +dykes dyke +dynasty dynasti +dysentery dysenteri +e e +each each +ead ead +eager eager +eagerly eager +eagerness eager +eagle eagl +eagles eagl +ealthiest ealthiest +ear ear +eard eard +eared ear +earings ear +earl earl +earlier earlier +earliest earliest +earls earl +early earli +earlybird earlybird +earn earn +earned earn +earnest earnest +earnestly earnest +earnestness earnest +earning earn +earnings earn +earring earring +earrings earring +ears ear +eart eart +earth earth +earthen earthen +earthenware earthenwar +earthly earth +earthquake earthquak +earthquakes earthquak +earths earth +earthy earthi +earwigs earwig +eas ea +ease eas +eased eas +easier easier +easiest easiest +easily easili +easiness easi +east east +easter easter +easterly easter +eastern eastern +eastward eastward +eastwards eastward +easy easi +eat eat +eatable eatabl +eatables eatabl +eaten eaten +eater eater +eaters eater +eating eat +eats eat +eau eau +eaves eav +ebb ebb +ebbed eb +ebbing eb +ebullitions ebullit +eccentric eccentr +eccentricities eccentr +eccentricity eccentr +ecclesiastical ecclesiast +ech ech +echo echo +echoed echo +echoes echo +echoing echo +echoings echo +eclipse eclips +eclipsed eclips +ecod ecod +economic econom +economical econom +economically econom +economists economist +economize econom +economizing econom +economy economi +ecstasies ecstasi +ecstasy ecstasi +ecstatic ecstat +ecstatically ecstat +ed ed +eddication eddic +eddies eddi +eddying eddi +eden eden +edental edent +edentata edentata +edge edg +edged edg +edgeless edgeless +edges edg +edgeware edgewar +edgeways edgeway +edging edg +edible edibl +edict edict +edification edif +edifice edific +edifices edific +edified edifi +edify edifi +edifying edifi +edin edin +edinburgh edinburgh +edition edit +editor editor +editors editor +educate educ +educated educ +educating educ +education educ +educational educ +educator educ +edusa edusa +edward edward +edwards edward +edwin edwin +ee ee +eel eel +eels eel +ees ee +efface effac +effaceable effac +effect effect +effected effect +effecting effect +effective effect +effectiveness effect +effects effect +effectual effectu +effectually effectu +effeminate effemin +effervescence effervesc +effervescent effervesc +effets effet +efficacious efficaci +efficacy efficaci +efficiency effici +efficient effici +effigy effigi +effloresce effloresc +efflorescence effloresc +effluvia effluvia +effluvium effluvium +effort effort +efforts effort +effrontery effronteri +effulgence effulg +effusion effus +effusions effus +efther efther +egad egad +egbert egbert +egg egg +eggs egg +eggshells eggshel +eghert eghert +eglantine eglantin +egoist egoist +egotistically egotist +egregious egregi +egregiously egregi +egress egress +egrets egret +egypt egypt +egyptian egyptian +egyptians egyptian +eh eh +ehrenberg ehrenberg +eight eight +eighteen eighteen +eighteenpence eighteenp +eighteenpences eighteenp +eighteenpenny eighteenpenni +eighth eighth +eighthly eighth +eighths eighth +eightpence eightpenc +eighty eighti +eimeo eimeo +eine ein +either either +ejaculate ejacul +ejaculated ejacul +ejaculates ejacul +ejaculating ejacul +ejaculations ejacul +eject eject +ejected eject +ejecting eject +ekaterininsky ekaterininski +eke eke +eked eke +eking eke +el el +elaborate elabor +elaborated elabor +elaboration elabor +elan elan +elapse elaps +elapsed elaps +elapses elaps +elastic elast +elasticity elast +elated elat +elater elat +elateridae elaterida +elaters elat +elation elat +elber elber +elbers elber +elbow elbow +elbowed elbow +elbowing elbow +elbows elbow +elder elder +elderly elder +elders elder +eldest eldest +eldon eldon +elect elect +elected elect +electing elect +election elect +electioneering election +elections elect +elector elector +electors elector +electric electr +electrical electr +electricity electr +elegance eleg +elegancies eleg +elegans elegan +elegant eleg +elegantly eleg +element element +elementary elementari +elements element +elephant eleph +elephantine elephantin +elephants eleph +elevate elev +elevated elev +elevates elev +elevating elev +elevation elev +elevations elev +elevatory elevatori +eleven eleven +elevens eleven +eleventh eleventh +elewated elew +elf elf +elfin elfin +elgble elgbl +elicit elicit +elicited elicit +eliciting elicit +elicits elicit +eligible elig +eliminate elimin +elite elit +elizabeth elizabeth +ell ell +elle ell +ellen ellen +elles ell +ellesmere ellesmer +elliptic ellipt +ellis elli +ellore ellor +elm elm +elmo elmo +elms elm +elocution elocut +elongated elong +elongation elong +elope elop +eloped elop +elopement elop +eloquence eloqu +eloquent eloqu +eloquently eloqu +elscholchias elscholchia +elsdale elsdal +else els +elsewhere elsewher +elucidate elucid +elucidated elucid +elude elud +eluded elud +eluding elud +elves elv +elwes elw +elysian elysian +elysium elysium +em em +emaciated emaci +emanated eman +emanating eman +emanation eman +emancipated emancip +emancipation emancip +emancipist emancipist +emasculate emascul +embankment embank +embankments embank +embarassed embarass +embargo embargo +embark embark +embarked embark +embarking embark +embarrass embarrass +embarrassed embarrass +embarrassing embarrass +embarrassment embarrass +embarrassments embarrass +embassy embassi +embedded embed +embellish embellish +embellished embellish +embellishes embellish +embellishing embellish +embellishment embellish +embellishments embellish +ember ember +embers ember +embitter embitt +embittered embitt +emblazoned emblazon +emblem emblem +emblems emblem +embodied embodi +embodiment embodi +emboldened embolden +emboldening embolden +emboldens embolden +embossed emboss +embowed embow +embrace embrac +embraced embrac +embracer embrac +embraces embrac +embracing embrac +embroidered embroid +embroidering embroid +embroiders embroid +embroidery embroideri +embroil embroil +embryo embryo +emerald emerald +emerge emerg +emerged emerg +emergency emerg +emerges emerg +emerging emerg +emigrate emigr +emigrated emigr +emigration emigr +emilia emilia +emily emili +eminence emin +eminent emin +eminently emin +emit emit +emits emit +emitted emit +emitting emit +emma emma +emollient emolli +emoluments emolu +emotion emot +emotional emot +emotions emot +emperor emperor +empetrum empetrum +emphasis emphasi +emphasise emphasis +emphasising emphasis +emphasizing emphas +emphatic emphat +emphatically emphat +empire empir +employ employ +employed employ +employer employ +employers employ +employing employ +employment employ +employments employ +employs employ +emporium emporium +emporiums emporium +empower empow +empowered empow +empress empress +emptied empti +empties empti +emptiness empti +emptor emptor +empty empti +emptying empti +emu emu +emulation emul +emus emus +en en +enable enabl +enabled enabl +enables enabl +enabling enabl +enact enact +enacted enact +enacting enact +enamel enamel +enamelled enamel +enamoured enamour +encamped encamp +encampment encamp +encamps encamp +encased encas +encerrado encerrado +enchanted enchant +enchanter enchant +enchanting enchant +encircle encircl +encircled encircl +encircles encircl +encircling encircl +enclos enclo +enclose enclos +enclosed enclos +enclosing enclos +enclosure enclosur +enclosures enclosur +encomium encomium +encomiums encomium +encompassed encompass +encompassing encompass +encore encor +encounter encount +encountered encount +encountering encount +encounters encount +encourage encourag +encouraged encourag +encouragement encourag +encouragements encourag +encourager encourag +encourages encourag +encouraging encourag +encouragingly encourag +encroach encroach +encroached encroach +encroaches encroach +encroachment encroach +encroachments encroach +encrusted encrust +encumber encumb +encumbered encumb +encumbering encumb +encyclop encyclop +end end +endanger endang +endangered endang +endear endear +endeared endear +endearing endear +endearment endear +endearments endear +endeavour endeavour +endeavoured endeavour +endeavouring endeavour +endeavours endeavour +ended end +endemic endem +enderby enderbi +enders ender +ending end +endless endless +endlessly endless +endow endow +endowed endow +endowing endow +endowment endow +endowments endow +endroits endroit +ends end +endurable endur +endurance endur +endure endur +endured endur +enduring endur +eneaf eneaf +enemies enemi +enemy enemi +energetic energet +energetically energet +energies energi +energy energi +enervated enerv +enfant enfant +enfeebled enfeebl +enfolded enfold +enfolding enfold +enforce enforc +enforced enforc +enforcing enforc +engaddi engaddi +engage engag +engaged engag +engagement engag +engagements engag +engages engag +engaging engag +engagingness engaging +engagmg engagmg +engender engend +engendered engend +engenhodo engenhodo +engine engin +engineer engin +engineering engin +engines engin +england england +english english +englishman englishman +englishmen englishmen +englishwoman englishwoman +engraved engrav +engraven engraven +engraver engrav +engraving engrav +engravings engrav +engrossed engross +engrosser engross +engrossing engross +enhance enhanc +enhanced enhanc +enhancing enhanc +enigma enigma +enigmatic enigmat +enigmatically enigmat +enjoin enjoin +enjoined enjoin +enjoins enjoin +enjoy enjoy +enjoyable enjoy +enjoyed enjoy +enjoying enjoy +enjoyingly enjoy +enjoyment enjoy +enjoys enjoy +enlarge enlarg +enlarged enlarg +enlarging enlarg +enlighten enlighten +enlightened enlighten +enlightenment enlighten +enlist enlist +enlisted enlist +enlisting enlist +enlistment enlist +enliven enliven +enlivened enliven +enlivening enliven +enlivenment enliven +enmity enmiti +ennoble ennobl +ennobled ennobl +ennobles ennobl +ennui ennui +enormity enorm +enormous enorm +enormously enorm +enough enough +enrage enrag +enraged enrag +enraptured enraptur +enriched enrich +enriching enrich +enrichment enrich +enrobed enrob +enrol enrol +enrolled enrol +enshrined enshrin +enshrouded enshroud +ensign ensign +enslaver enslav +enslaving enslav +ensnare ensnar +ensnared ensnar +ensue ensu +ensued ensu +ensues ensu +ensuing ensu +ensure ensur +entail entail +entailed entail +entangle entangl +entangled entangl +entanglement entangl +enter enter +entered enter +entering enter +enterprise enterpris +enterprising enterpris +enters enter +entertain entertain +entertained entertain +entertainer entertain +entertaining entertain +entertainment entertain +entertainments entertain +entertains entertain +enthralled enthral +enthusiasm enthusiasm +enthusiastic enthusiast +enthusiastically enthusiast +enticed entic +enticing entic +entire entir +entirely entir +entirety entireti +entitle entitl +entitled entitl +entitling entitl +entombed entomb +entombment entomb +entomol entomol +entomological entomolog +entomologist entomologist +entomology entomolog +entomostraca entomostraca +entomostracous entomostrac +entrails entrail +entrance entranc +entrances entranc +entrap entrap +entrapped entrap +entre entr +entreat entreat +entreated entreat +entreaties entreati +entreating entreat +entreats entreat +entreaty entreati +entree entre +entrenched entrench +entries entri +entrust entrust +entrusted entrust +entry entri +entwine entwin +entwined entwin +entwines entwin +enumerate enumer +enumerated enumer +enunciated enunci +enunciation enunci +envelope envelop +enveloped envelop +envelopes envelop +envelops envelop +envenomed envenom +enviable enviabl +envied envi +envies envi +envious envious +environ environ +environment environ +environne environn +envy envi +epaulets epaulet +epaulette epaulett +epeira epeira +ephemeral ephemer +epicure epicur +epicurean epicurean +epidemics epidem +epilepsy epilepsi +epileptic epilept +epilogue epilogu +episode episod +episodes episod +epistle epistl +epithet epithet +epithets epithet +epitome epitom +epoch epoch +epochs epoch +eprise epris +epsom epsom +equable equabl +equal equal +equality equal +equalle equall +equalled equal +equalling equal +equally equal +equals equal +equanimity equanim +equator equat +equatorial equatori +equestrian equestrian +equidistant equidist +equilibrium equilibrium +equinox equinox +equipage equipag +equipages equipag +equipment equip +equipped equip +equitable equit +equitably equit +equitem equitem +equity equiti +equivalent equival +equivocal equivoc +equivocation equivoc +equus equus +er er +era era +eradicate erad +eradicated erad +eras era +erased eras +ercharged ercharg +ere ere +erec erec +erect erect +erected erect +erections erect +erectness erect +erects erect +erichson erichson +erle erl +erme erm +ermine ermin +erosio erosio +err err +errand errand +errands errand +erratic errat +erred er +erring er +erroneous erron +error error +errors error +erst erst +erstan erstan +eructans eructan +erudite erudit +erudition erudit +erupted erupt +eruption erupt +eruptions erupt +eruptive erupt +eryngium eryngium +erysipelas erysipela +erythraeum erythraeum +es es +escape escap +escaped escap +escapes escap +escaping escap +escarpment escarp +escarpments escarp +eschara eschara +escheated escheat +escort escort +escorted escort +escorting escort +esculentus esculentus +escutcheons escutcheon +esk esk +espagne espagn +especial especi +especially especi +espied espi +esplanades esplanad +espouse espous +espoused espous +esprit esprit +esq esq +esquimau esquimau +esquire esquir +essay essay +essayed essay +essays essay +esse ess +essence essenc +essential essenti +essentially essenti +essentials essenti +essex essex +est est +establish establish +established establish +establishes establish +establishing establish +establishment establish +establishments establish +estacado estacado +estancia estancia +estancias estancia +estanciero estanciero +estate estat +estates estat +esteem esteem +esteemed esteem +esteeming esteem +esteems esteem +esther esther +esthers esther +estimable estim +estimate estim +estimated estim +estimates estim +estimating estim +estimation estim +estrange estrang +estranged estrang +estrangement estrang +estranging estrang +estuaries estuari +estuary estuari +et et +etage etag +etc etc +ete ete +eternal etern +eternally etern +eternelle eternell +eternity etern +etes ete +ethereal ether +etiquette etiquett +etiquettes etiquett +etna etna +eton eton +etonnement etonn +etymology etymolog +eucalypti eucalypti +eucalyptus eucalyptus +eudromia eudromia +eulogistic eulogist +eulogium eulogium +euphorbia euphorbia +euphorbiaceae euphorbiacea +europe europ +european european +europeans european +eustace eustac +euston euston +ev ev +evade evad +evaded evad +evading evad +evans evan +evaporate evapor +evaporated evapor +evaporates evapor +evaporation evapor +evasion evas +evasions evas +evasive evas +evasively evas +evasiveness evas +eve eve +evelyn evelyn +evelyns evelyn +even even +evening even +evenings even +evenlng evenlng +evenly even +evenness even +event event +eventful event +events event +eventually eventu +ever ever +everbody everbodi +everbrowns everbrown +everett everett +evergreen evergreen +evergreens evergreen +everlasting everlast +everlastingly everlast +evermore evermor +evervwhere evervwher +every everi +everybody everybodi +everybodys everybodi +everyday everyday +everyone everyon +everything everyth +everythink everythink +everyways everyway +everywhere everywher +everywheres everywher +evidence evid +evidences evid +evidenfly evidenfli +evident evid +evidently evid +evil evil +evils evil +evince evinc +evinced evinc +evincing evinc +evins evin +evoke evok +evoked evok +evokes evok +evolution evolut +evolutions evolut +ew ew +ewe ewe +ewent ewent +ex ex +exact exact +exacted exact +exacting exact +exactions exact +exactitude exactitud +exactly exact +exactness exact +exaggerate exagger +exaggerated exagger +exaggerates exagger +exaggerating exagger +exaggeration exagger +exaggerations exagger +exalt exalt +exaltation exalt +exalted exalt +exalting exalt +examination examin +examinations examin +examine examin +examined examin +examines examin +examining examin +example exampl +examples exampl +exasperated exasper +exasperating exasper +exasperation exasper +excavated excav +excavation excav +excavations excav +exceed exceed +exceeded exceed +exceeding exceed +exceedingly exceed +exceeds exceed +excelled excel +excellence excel +excellences excel +excellencies excel +excellency excel +excellent excel +excellently excel +except except +excepted except +excepting except +exception except +exceptional except +exceptionally except +exceptionalness exception +exceptions except +excess excess +excesses excess +excessive excess +excessively excess +exchange exchang +exchanged exchang +exchanges exchang +exchanging exchang +exchequer exchequ +excitable excit +excitableness excit +excite excit +excited excit +excitedly excit +excitement excit +excitements excit +excites excit +exciting excit +exclaim exclaim +exclaimed exclaim +exclaiming exclaim +exclaims exclaim +exclamation exclam +exclamations exclam +exclude exclud +excluded exclud +excluding exclud +exclusion exclus +exclusions exclus +exclusive exclus +exclusively exclus +exclusiveness exclus +excoriate excori +excremens excremen +excrescence excresc +excruciatingly excruci +excursion excurs +excursions excurs +excusable excus +excuse excus +excused excus +excuses excus +excusing excus +execrable execr +execrate execr +execrating execr +execute execut +executed execut +executing execut +execution execut +executioner execution +executions execut +executive execut +executor executor +executors executor +exemplary exemplari +exemplified exemplifi +exemplifies exemplifi +exemplify exemplifi +exempt exempt +exempted exempt +exemption exempt +exercise exercis +exercised exercis +exercises exercis +exercising exercis +exert exert +exerted exert +exerting exert +exertion exert +exertions exert +exerts exert +exeter exet +exhalations exhal +exhale exhal +exhaled exhal +exhaust exhaust +exhausted exhaust +exhausting exhaust +exhaustion exhaust +exhaustless exhaustless +exhausts exhaust +exhibit exhibit +exhibited exhibit +exhibiting exhibit +exhibition exhibit +exhibitions exhibit +exhibits exhibit +exhilarated exhilar +exhilarating exhilar +exhilaration exhilar +exhort exhort +exhortation exhort +exhortations exhort +exhorted exhort +exhorting exhort +exhorts exhort +exigencies exig +exile exil +exiled exil +exiles exil +exist exist +existe exist +existed exist +existence exist +existent exist +existing exist +exists exist +exit exit +exorbitant exorbit +exordium exordium +exotic exot +exotically exot +exotics exot +expand expand +expande expand +expanded expand +expanding expand +expands expand +expanse expans +expanses expans +expansion expans +expansions expans +expansive expans +expatiate expati +expatiated expati +expatiating expati +expatriated expatri +expatriation expatri +expect expect +expectancy expect +expectant expect +expectants expect +expectation expect +expectations expect +expected expect +expecting expect +expects expect +exped exp +expedience expedi +expediency expedi +expedient expedi +expedients expedi +expedite expedit +expedition expedit +expeditions expedit +expeditious expediti +expeditiously expediti +expel expel +expelled expel +expelling expel +expend expend +expended expend +expenditure expenditur +expense expens +expenses expens +expensive expens +expensively expens +experience experi +experienced experienc +experiences experi +experiment experi +experimental experiment +experimented experi +experiments experi +expert expert +expiate expiat +expiating expiat +expiation expiat +expiration expir +expire expir +expired expir +expiring expir +explain explain +explained explain +explaining explain +explains explain +explanation explan +explanations explan +explanatory explanatori +expletive explet +expletives explet +expletus expletus +explicit explicit +explode explod +explodes explod +exploding explod +exploit exploit +exploits exploit +explore explor +explored explor +explorer explor +exploring explor +explosion explos +explosions explos +explosive explos +exponent expon +export export +exportation export +exported export +exports export +expose expos +exposed expos +exposes expos +exposing expos +exposition exposit +expostulate expostul +expostulated expostul +expostulating expostul +expostulation expostul +exposure exposur +expound expound +expounding expound +express express +expressed express +expresses express +expressing express +expression express +expressionless expressionless +expressions express +expressive express +expressively express +expressly expressli +expulsion expuls +exquisite exquisit +exquisitely exquisit +exquisites exquisit +exserted exsert +extant extant +extemporaneously extemporan +extemporary extemporari +extemporized extempor +extend extend +extended extend +extending extend +extends extend +extensile extensil +extension extens +extensive extens +extensively extens +extent extent +extenuating extenu +extenuation extenu +exterior exterior +exterminated extermin +exterminating extermin +extermination extermin +exterminations extermin +external extern +externally extern +extinct extinct +extinction extinct +extinguish extinguish +extinguished extinguish +extinguisher extinguish +extinguishers extinguish +extinguishes extinguish +extinguishing extinguish +extirpating extirp +extol extol +extolled extol +extolling extol +extort extort +extorted extort +extorting extort +extortion extort +extortions extort +extra extra +extract extract +extracted extract +extracting extract +extraction extract +extracts extract +extraneous extran +extraordinarily extraordinarili +extraordinary extraordinari +extras extra +extravagance extravag +extravagances extravag +extravagant extravag +extreme extrem +extremely extrem +extremes extrem +extremest extremest +extremities extrem +extremity extrem +extremum extremum +extricate extric +extricated extric +extricating extric +extrication extric +exuberant exuber +exudations exud +exuded exud +exultation exult +exulted exult +exulting exult +exultingly exult +exults exult +ey ey +eye eye +eyeball eyebal +eyebrow eyebrow +eyebrows eyebrow +eyed eye +eyeglass eyeglass +eyeing eye +eyelash eyelash +eyelashes eyelash +eyelid eyelid +eyelids eyelid +eyes eye +eyesight eyesight +eyesore eyesor +eyre eyr +ezactly ezact +f f +fa fa +fable fabl +fabled fabl +fables fabl +fabric fabric +fabricated fabric +fabricius fabricius +fabulous fabul +fabulously fabul +facade facad +face face +faced face +faces face +facetious faceti +facetiously faceti +facetiousness faceti +facial facial +facile facil +facilitate facilit +facilitates facilit +facilitating facilit +facilities facil +facility facil +facing face +facings face +fact fact +faction faction +factor factor +factors factor +factory factori +facts fact +faculties faculti +faculty faculti +fade fade +faded fade +fadedly fade +fades fade +fading fade +fag fag +fagged fag +faggot faggot +fagus fagus +fah fah +fail fail +failed fail +failing fail +failings fail +fails fail +failure failur +failures failur +fain fain +faineant faineant +faineants faineant +faint faint +fainted faint +fainter fainter +faintest faintest +fainting faint +faintings faint +faintly faint +faintness faint +faints faint +fair fair +faire fair +fairer fairer +fairest fairest +fairies fairi +fairish fairish +fairly fair +fairness fair +fairy fairi +fait fait +faith faith +faithful faith +faithfuller faithful +faithfully faith +faithfulness faith +falconer falcon +falkland falkland +falklands falkland +fall fall +fallacy fallaci +fallen fallen +fallible fallibl +fallin fallin +falling fall +falls fall +falmouth falmouth +false fals +falsehood falsehood +falsehoods falsehood +falsely fals +falseness fals +falser falser +falsetto falsetto +falsify falsifi +falsity falsiti +falter falter +faltered falter +faltering falter +falteringly falter +falters falter +fame fame +famed fame +familiar familiar +familiaris familiari +familiarised familiaris +familiarities familiar +familiarity familiar +familiarized familiar +familiarly familiar +familiars familiar +families famili +family famili +famine famin +famines famin +famished famish +famoso famoso +famous famous +famously famous +fan fan +fanaticism fanatic +fancied fanci +fancier fancier +fancies fanci +fanciful fanci +fancy fanci +fancying fanci +faneant faneant +fangs fang +fanlight fanlight +fanned fan +fanny fanni +fans fan +fanshawe fanshaw +fantastic fantast +fantastical fantast +fantastically fantast +fantasy fantasi +far far +farce farc +fare fare +fared fare +fares fare +farewell farewel +farewells farewel +farinha farinha +farm farm +farmed farm +farmer farmer +farmers farmer +farmhouse farmhous +farmhouses farmhous +farming farm +farms farm +farrago farrago +farther farther +farthest farthest +farthing farth +farthings farth +fascinate fascin +fascinated fascin +fascinating fascin +fascination fascin +fascinations fascin +fascinator fascin +fash fash +fashion fashion +fashionable fashion +fashionably fashion +fashionahle fashionahl +fashioned fashion +fashions fashion +fast fast +fasten fasten +fastened fasten +fastening fasten +fastenings fasten +fastens fasten +faster faster +fastest fastest +fastidious fastidi +fastidiousness fastidi +fasting fast +fastness fast +fat fat +fatal fatal +fate fate +fated fate +fateful fate +fates fate +father father +fatherland fatherland +fatherless fatherless +fatherly father +fathers father +fathom fathom +fathomless fathomless +fathoms fathom +fatigue fatigu +fatigued fatigu +fatigues fatigu +fatiguing fatigu +fatima fatima +fatly fat +fatness fat +fatten fatten +fattened fatten +fattening fatten +fatter fatter +fattish fattish +fatuity fatuiti +faugh faugh +fault fault +faultless faultless +faults fault +fauna fauna +faux faux +favour favour +favourable favour +favourably favour +favoured favour +favouring favour +favourite favourit +favourites favourit +favours favour +fawn fawn +fawned fawn +fawning fawn +fawns fawn +fazenda fazenda +fazendas fazenda +fe fe +feace feac +feaced feac +fealty fealti +fear fear +feared fear +feareth feareth +fearful fear +fearfully fear +fearfulty fearfulti +fearing fear +feariocious fearioci +fearless fearless +fearlessly fearless +fears fear +feasible feasibl +feast feast +feasted feast +feasting feast +feasts feast +feat feat +feather feather +featherbed featherb +feathered feather +feathers feather +feathery featheri +feats feat +feature featur +featured featur +features featur +feb feb +februa februa +february februari +fed fed +fedosya fedosya +fedyaev fedyaev +fee fee +feeble feebl +feebleness feebl +feebler feebler +feebly feebli +feeckle feeckl +feed feed +feeder feeder +feeders feeder +feeding feed +feeds feed +feel feel +feeling feel +feelingly feel +feelings feel +feels feel +fees fee +feet feet +feign feign +feigned feign +feigning feign +feigns feign +feijao feijao +feint feint +feints feint +fel fel +feldspathic feldspath +felicitations felicit +felicitous felicit +felicitously felicit +felicity felic +feline felin +felipe felip +felix felix +fell fell +felled fell +feller feller +fellow fellow +fellows fellow +fellowship fellowship +felo felo +felon felon +feloniously feloni +felons felon +felony feloni +felspar felspar +felspathic felspath +felt felt +female femal +females femal +feminine feminin +fen fen +fence fenc +fenced fenc +fences fenc +fencing fenc +fender fender +fennel fennel +fens fen +ferdinand ferdinand +ferdy ferdi +ferguson ferguson +ferment ferment +fermentable ferment +fermenting ferment +fern fern +fernal fernal +fernandez fernandez +fernando fernando +fernery ferneri +ferns fern +ferocious feroci +ferociously feroci +ferocity feroc +feronia feronia +ferret ferret +ferreted ferret +ferried ferri +ferruginous ferrugin +ferrule ferrul +ferry ferri +fertile fertil +fertility fertil +fertilizing fertil +ferule ferul +fervency fervenc +fervent fervent +fervently fervent +fervid fervid +fervour fervour +fester fester +festering fester +festival festiv +festivals festiv +festive festiv +festivities festiv +festivity festiv +festoon festoon +festoons festoon +fetch fetch +fetched fetch +fetches fetch +fetching fetch +feted fete +fetid fetid +fetlock fetlock +fetlocks fetlock +fetters fetter +feud feud +feudal feudal +feury feuri +fever fever +fevered fever +feverish feverish +feverishly feverish +feverishness feverish +fevers fever +few few +fewer fewer +fewest fewest +fewness few +feyther feyther +feythers feyther +fiance fianc +fiancee fiance +fiat fiat +fib fib +fibbing fib +fibre fibr +fibres fibr +fibrous fibrous +fibs fib +fichy fichi +fickle fickl +fickleness fickl +fico fico +fiction fiction +fictions fiction +fictitious fictiti +fiddle fiddl +fiddles fiddl +fiddlesticks fiddlestick +fide fide +fidelity fidel +fidget fidget +fidgeted fidget +fidgeting fidget +fidgett fidgett +fidgetts fidgett +fidgety fidgeti +fie fie +field field +fieldfare fieldfar +fieldingsby fieldingsbi +fields field +fiend fiend +fiendish fiendish +fierce fierc +fiercely fierc +fierceness fierc +fiercer fiercer +fiercest fiercest +fiery fieri +fife fife +fifer fifer +fifteen fifteen +fifteenth fifteenth +fifth fifth +fifthly fifth +fifths fifth +fifty fifti +fig fig +fight fight +fighter fighter +fighting fight +fights fight +figment figment +figs fig +figuireda figuireda +figurative figur +figure figur +figured figur +figures figur +figuring figur +filamentous filament +filched filch +file file +filed file +files file +filial filial +filigree filigre +filing file +filka filka +fill fill +fille fill +filled fill +fillet fillet +filling fill +fillip fillip +fills fill +film film +films film +filtered filter +filtering filter +filth filth +filthily filthili +filthiness filthi +filthy filthi +fin fin +final final +finally final +finance financ +finances financ +financial financi +finch finch +finches finch +find find +finding find +finds find +fine fine +finely fine +finer finer +finery fineri +finest finest +finger finger +fingered finger +fingerends fingerend +fingerless fingerless +fingers finger +finis fini +finish finish +finished finish +finishes finish +finishing finish +finlshed finlsh +finn finn +finnish finnish +fins fin +finsbury finsburi +fiord fiord +fir fir +fire fire +firearms firearm +firebrand firebrand +fired fire +fireflies firefli +firelight firelight +fireman fireman +fireplace fireplac +fires fire +fireside firesid +firesides firesid +firewood firewood +firework firework +fireworks firework +firing fire +firm firm +firma firma +firmament firmament +firmaments firmament +firmer firmer +firmest firmest +firmly firm +firmness firm +firs fir +first first +firstborn firstborn +firstly first +fis fis +fiscal fiscal +fish fish +fished fish +fisherman fisherman +fishermen fishermen +fishes fish +fishing fish +fishmonger fishmong +fissure fissur +fissured fissur +fissurella fissurella +fissurellae fissurella +fissures fissur +fist fist +fisted fist +fists fist +fit fit +fitful fit +fitfully fit +fitly fit +fitness fit +fitnesses fit +fits fit +fitted fit +fitter fitter +fittest fittest +fitting fit +fittings fit +fitz fitz +fitzgibbon fitzgibbon +fitzgibbons fitzgibbon +fitzhugh fitzhugh +fitzroy fitzroy +five five +fiver fiver +fives five +fix fix +fixed fix +fixedly fix +fixes fix +fixing fix +fixity fixiti +fixture fixtur +fixtures fixtur +flabbily flabbili +flabby flabbi +flabella flabella +flaco flaco +flag flag +flagellation flagel +flagellator flagel +flagged flag +flagging flag +flagrant flagrant +flagrantly flagrant +flags flag +flagstaff flagstaff +flake flake +flakes flake +flambeaux flambeaux +flame flame +flames flame +flaming flame +flamingoes flamingo +flank flank +flanked flank +flanks flank +flannel flannel +flap flap +flapped flap +flapping flap +flaps flap +flare flare +flares flare +flaring flare +flash flash +flashed flash +flashes flash +flashing flash +flashy flashi +flask flask +flat flat +flatly flat +flatness flat +flats flat +flattened flatten +flattening flatten +flatter flatter +flattered flatter +flatterer flatter +flatterers flatter +flattering flatter +flatters flatter +flattery flatteri +flattest flattest +flattish flattish +flavor flavor +flavour flavour +flavoured flavour +flaw flaw +flawed flaw +flaws flaw +flax flax +flaxen flaxen +flaying flay +flea flea +fleas flea +fleck fleck +flecked fleck +fled fled +fledged fledg +fledgling fledgl +fledglings fledgl +flee flee +fleece fleec +fleecy fleeci +fleet fleet +fleeting fleet +fleetingly fleet +flemish flemish +fler fler +flesh flesh +fleshing flesh +fleshly flesh +fleshy fleshi +fletcher fletcher +fletcherites fletcherit +fletchers fletcher +flew flew +flexibility flexibl +flexible flexibl +flexure flexur +flickering flicker +flickers flicker +flicking flick +flier flier +flies fli +flight flight +flights flight +flighty flighti +flinch flinch +flinching flinch +flinder flinder +flinders flinder +fling fling +flinging fling +flings fling +flint flint +flinty flinti +flippant flippant +flipping flip +flirt flirt +flirtation flirtat +flirtations flirtat +flirted flirt +flirting flirt +flirts flirt +flit flit +flite flite +flits flit +flitted flit +flitting flit +float float +floated float +floating float +floats float +flocculent floccul +flock flock +flocked flock +flocking flock +flocks flock +flog flog +flogged flog +flogging flog +flood flood +flooded flood +floodgates floodgat +flooding flood +floods flood +floor floor +floored floor +flooring floor +floors floor +flop flop +flora flora +floral floral +florence florenc +florian florian +floriated floriat +florid florid +florist florist +florula florula +flotilla flotilla +flounce flounc +flounced flounc +flounces flounc +flouncing flounc +floundered flounder +floundering flounder +flour flour +floured flour +flourish flourish +flourished flourish +flourishes flourish +flourishing flourish +flow flow +flowed flow +flower flower +flowering flower +flowers flower +flowing flow +flown flown +flows flow +flrst flrst +flu flu +fluctuate fluctuat +fluctuated fluctuat +fluctuating fluctuat +flue flue +fluent fluent +fluently fluentli +fluffles fluffl +fluggers flugger +fluid fluid +fluidified fluidifi +fluids fluid +flung flung +flunkey flunkey +flurried flurri +flurries flurri +flurry flurri +flush flush +flushed flush +flushes flush +flushing flush +flustered fluster +flustra flustra +flustraceae flustracea +flute flute +flutes flute +flutings flute +flutter flutter +fluttered flutter +flutterers flutter +fluttering flutter +flutteringiy flutteringiy +flutters flutter +fly fli +flycatcher flycatch +flycatchers flycatch +flying fli +flys flys +fo fo +foal foal +foals foal +foam foam +foaming foam +fob fob +focus focus +fodere foder +foe foe +foes foe +foetid foetid +fog fog +fogeys fogey +foggy foggi +fogies fogi +fogs fog +fogy fogi +foh foh +foibles foibl +foil foil +foiled foil +foind foind +foinds foind +folair folair +fold fold +folded fold +folding fold +folds fold +foliaceous foliac +foliage foliag +folio folio +folk folk +folkestone folkeston +folks folk +foller foller +follerer foller +follerers foller +follering foller +follies folli +follow follow +followed follow +follower follow +followers follow +following follow +follows follow +folly folli +fomentation foment +fomitch fomitch +fond fond +fonder fonder +fondest fondest +fondle fondl +fondles fondl +fondling fondl +fondly fond +fondness fond +font font +foo foo +food food +foodle foodl +fool fool +fooled fool +fooleries fooleri +foolery fooleri +fooling fool +foolish foolish +foolishly foolish +foolishness foolish +fools fool +foolscap foolscap +foot foot +football footbal +footboy footboy +footed foot +footer footer +footfall footfal +footguards footguard +foothold foothold +footing foot +footlights footlight +footman footman +footmen footmen +footpad footpad +footpath footpath +footprint footprint +footprints footprint +footsore footsor +footstep footstep +footsteps footstep +footstool footstool +footstools footstool +footway footway +footways footway +foppish foppish +for for +foragers forag +forard forard +forards forard +forasmuch forasmuch +forbade forbad +forbear forbear +forbearance forbear +forbearing forbear +forbearingly forbear +forbears forbear +forbes forb +forbid forbid +forbidden forbidden +forbidding forbid +forbids forbid +forbore forbor +force forc +forced forc +forceps forcep +forces forc +forcible forcibl +forcibly forcibl +forcing forc +ford ford +forded ford +fore fore +foreboded forebod +foreboding forebod +forebodings forebod +forecast forecast +forecoming forecom +forefathers forefath +forefinger forefing +forefingers forefing +foregathered foregath +forego forego +foregoing forego +foregone foregon +foreground foreground +forehead forehead +foreheads forehead +foreign foreign +foreigner foreign +foreigners foreign +forelock forelock +foreman foreman +foremost foremost +forenoon forenoon +forensic forens +forerunner forerunn +foresaw foresaw +foresee forese +foreseeing forese +foreseen foreseen +foresees forese +foreshadow foreshadow +foreshadowing foreshadow +foreshortened foreshorten +foresight foresight +forest forest +forests forest +foretaste foretast +foretell foretel +foretelling foretel +forethought forethought +foretold foretold +forever forev +forewarned forewarn +forewarning forewarn +forewarnings forewarn +forewoman forewoman +forfeit forfeit +forfeited forfeit +forfeiting forfeit +forfeits forfeit +forficatus forficatus +forgave forgav +forge forg +forged forg +forgeries forgeri +forgery forgeri +forget forget +forgetful forget +forgetfulness forget +forgets forget +forgetting forget +forgi forgi +forging forg +forgive forgiv +forgiven forgiven +forgiveness forgiv +forgives forgiv +forgiving forgiv +forgivingly forgiv +forgot forgot +forgotten forgotten +fork fork +forked fork +forks fork +forlorn forlorn +forlornest forlornest +forlornly forlorn +form form +formal formal +formalities formal +formality formal +formally formal +formation format +formations format +formed form +former former +formerly former +formidable formid +forming form +forms form +forrard forrard +forrenner forrenn +forres forr +forsake forsak +forsaken forsaken +forsaking forsak +forsook forsook +forster forster +forsworn forsworn +fort fort +forte fort +forth forth +forthcoming forthcom +forthwith forthwith +fortification fortif +fortifications fortif +fortified fortifi +fortifying fortifi +fortis forti +fortitude fortitud +fortnight fortnight +fortress fortress +forts fort +fortuitous fortuit +fortunate fortun +fortunately fortun +fortunatus fortunatus +fortune fortun +fortunes fortun +forty forti +forward forward +forwarded forward +forwarding forward +forwardness forward +forwards forward +fossil fossil +fossiles fossil +fossiliferous fossilifer +fossils fossil +foster foster +fostered foster +fostering foster +fothergill fothergil +fotheringham fotheringham +fotheringhams fotheringham +fou fou +fought fought +foul foul +fouled foul +foulest foulest +foun foun +found found +foundation foundat +foundations foundat +founded found +founding found +foundling foundl +foundries foundri +founds found +fount fount +fountain fountain +fountains fountain +fouque fouqu +four four +fourier fourier +fourpence fourpenc +fours four +fourteen fourteen +fourteenpenny fourteenpenni +fourteenth fourteenth +fourth fourth +fourthly fourth +fourths fourth +fower fower +fowl fowl +fowler fowler +fowls fowl +fox fox +foxes fox +foxgloves foxglov +fra fra +fraction fraction +fractious fractious +fracture fractur +fractured fractur +fractures fractur +fragile fragil +fragility fragil +fragm fragm +fragment fragment +fragmentary fragmentari +fragments fragment +fragrance fragranc +fragrant fragrant +frail frail +frame frame +framed frame +frames frame +framework framework +framing frame +francais francai +france franc +franchise franchis +franchises franchis +francia francia +francis franci +francisco francisco +frank frank +frankest frankest +frankfort frankfort +frankly frank +frankness frank +franks frank +frantic frantic +frantically frantic +frantsovna frantsovna +frantsovnas frantsovna +fraternal fratern +fraternity fratern +fraud fraud +fraudulent fraudul +fraudulently fraudul +fraught fraught +fray fray +frayed fray +freak freak +freaks freak +freckled freckl +frederick frederick +free free +freed freed +freedom freedom +freeholders freehold +freeing free +freely freeli +freemason freemason +freemasonry freemasonri +freer freer +frees free +freestone freeston +freeze freez +freezes freez +freezing freez +freight freight +freischutz freischutz +french french +frenchman frenchman +frenchmen frenchmen +frenchwoman frenchwoman +frenchwomen frenchwomen +frenzied frenzi +frenzy frenzi +frequency frequenc +frequenfly frequenfli +frequent frequent +frequented frequent +frequenters frequent +frequenting frequent +frequentl frequentl +frequently frequent +frequents frequent +fres fres +fresco fresco +fresh fresh +freshen freshen +freshened freshen +freshening freshen +fresher fresher +freshest freshest +freshly fresh +freshness fresh +freshwater freshwat +fret fret +fretful fret +fretfully fret +fretfulness fret +fretted fret +fretting fret +frever frever +freyrina freyrina +friable friabl +friar friar +fricassee fricasse +friction friction +friday friday +fridays friday +fridolin fridolin +fried fri +friend friend +friendless friendless +friendliest friendliest +friendliness friendli +friendly friend +friends friend +friendship friendship +friendships friendship +frigate frigat +fright fright +frighten frighten +frightened frighten +frightening frighten +frightens frighten +frightful fright +frightfully fright +frights fright +frigid frigid +frigidity frigid +frill frill +frilled frill +frills frill +fringe fring +fringed fring +fringes fring +fringing fring +frio frio +frippery fripperi +frisk frisk +frisking frisk +friths frith +fritter fritter +frittered fritter +frivolities frivol +frivolity frivol +frivolous frivol +frizzling frizzl +fro fro +frock frock +frocks frock +frog frog +frogs frog +frolic frolic +frolics frolic +frolicsome frolicsom +from from +frond frond +fronds frond +front front +fronte front +fronted front +frontier frontier +fronting front +frontispiece frontispiec +fronts front +frost frost +frosted frost +frosts frost +frosty frosti +froth froth +frothed froth +frothy frothi +frouzy frouzi +frown frown +frowned frown +frowning frown +frowns frown +frowsy frowsi +froze froze +frozen frozen +fructifying fructifi +frugal frugal +frugality frugal +fruit fruit +fruitful fruit +fruitless fruitless +fruitlessly fruitless +fruits fruit +frusta frusta +fry fri +frying fri +fuchsia fuchsia +fucus fucus +fuddled fuddl +fuega fuega +fuegia fuegia +fuegian fuegian +fuegians fuegian +fuego fuego +fuel fuel +fuentes fuent +fuffy fuffi +fugitive fugit +fugitives fugit +fulcrum fulcrum +fule fule +fulfil fulfil +fulfilled fulfil +fulfilling fulfil +fulfilment fulfil +fulgurites fulgurit +fulils fulil +full full +fuller fuller +fullest fullest +fullness full +fully fulli +fulness ful +fulvipes fulvip +fumbled fumbl +fumbling fumbl +fume fume +fumed fume +fumes fume +fumigation fumig +fuming fume +fun fun +function function +functionary functionari +functions function +fund fund +fundamental fundament +fundamentally fundament +funds fund +funebre funebr +funeral funer +funerals funer +funereal funer +fungi fungi +fungus fungus +funk funk +funnel funnel +funniest funniest +funny funni +fur fur +furbished furbish +furder furder +furies furi +furious furious +furiously furious +furlongs furlong +furnace furnac +furnaces furnac +furnarius furnarius +furnish furnish +furnished furnish +furnishes furnish +furnishing furnish +furniter furnit +furniture furnitur +furrowed furrow +furrows furrow +furry furri +furs fur +further further +furtherance further +furthermore furthermor +furthest furthest +furtive furtiv +furtively furtiv +fury furi +furze furz +fuse fuse +fused fuse +fusibility fusibl +fuss fuss +fussily fussili +fussy fussi +fust fust +fustian fustian +futile futil +futur futur +future futur +futures futur +fyodor fyodor +fyodorovna fyodorovna +fypunnote fypunnot +g g +ga ga +gab gab +gabble gabbl +gabbled gabbl +gable gabl +gables gabl +gad gad +gadfly gadfli +gadzooks gadzook +gags gag +gaieties gaieti +gaiety gaieti +gaily gaili +gaimard gaimard +gain gain +gained gain +gainer gainer +gaining gain +gains gain +gainsaid gainsaid +gainsay gainsay +gainsaying gainsay +gait gait +gaiters gaiter +gal gal +gala gala +galapageian galapageian +galapagoensis galapagoensi +galapagos galapago +galaxy galaxi +gale gale +gales gale +gall gall +gallanbile gallanbil +gallant gallant +gallantly gallant +gallantries gallantri +gallantry gallantri +gallants gallant +galled gall +gallegos gallego +galleries galleri +gallery galleri +galley galley +galleys galley +gallinaceous gallinac +gallinazo gallinazo +gallinazos gallinazo +galling gall +gallivanting galliv +gallon gallon +gallons gallon +gallop gallop +galloped gallop +galloping gallop +gallops gallop +gallows gallow +gals gal +galvanism galvan +gambier gambier +gamble gambl +gambled gambl +gambler gambler +gamblers gambler +gambles gambl +gambling gambl +gambolling gambol +gambrinus gambrinus +game game +gamekeepers gamekeep +games game +gamester gamest +gamesters gamest +gaming game +gammon gammon +gammoning gammon +gamut gamut +gander gander +gane gane +gang gang +ganges gang +ganging gang +ganglion ganglion +gangs gang +gangway gangway +gannet gannet +gannets gannet +ganz ganz +gap gap +gape gape +gaped gape +gapes gape +gaping gape +gaps gap +gar gar +garb garb +garbled garbl +garbs garb +garde gard +garden garden +gardener garden +gardeners garden +gardening garden +gardens garden +gardner gardner +gardners gardner +garish garish +garland garland +garlanded garland +garlands garland +garment garment +garments garment +garnet garnet +garnett garnett +garnish garnish +garnished garnish +garnishing garnish +garniture garnitur +garran garran +garret garret +garrets garret +garrison garrison +garter garter +gartered garter +garters garter +garth garth +garthers garther +gas gas +gases gase +gash gash +gashed gash +gaslights gaslight +gasp gasp +gasped gasp +gasping gasp +gaspingly gasp +gasps gasp +gate gate +gates gate +gateway gateway +gateways gateway +gather gather +gathered gather +gatherer gather +gatherers gather +gathering gather +gatherings gather +gatherlng gatherlng +gathers gather +gatherum gatherum +gato gato +gauch gauch +gaucho gaucho +gauchos gaucho +gaudiest gaudiest +gaudy gaudi +gaul gaul +gaunt gaunt +gauntlet gauntlet +gauntlets gauntlet +gauntly gaunt +gauze gauz +gauzy gauzi +gave gave +gavia gavia +gawky gawki +gay gay +gayest gayest +gaze gaze +gazed gaze +gazelle gazell +gazelles gazell +gazes gaze +gazette gazett +gazing gaze +gazingi gazingi +gear gear +geese gees +geist geist +gelatinous gelatin +gem gem +gemmules gemmul +gen gen +gender gender +genealogical genealog +genealogist genealogist +genelman genelman +genelmen genelmen +genera genera +general general +generalities general +generality general +generalization general +generally general +generals general +generalship generalship +generate generat +generated generat +generation generat +generations generat +generic generic +generosity generos +generous generous +generously generous +genesis genesi +geneva geneva +genfleman genfleman +genial genial +genially genial +genie geni +genius genius +geniuses genius +genlmen genlmen +genlmn genlmn +genteel genteel +genteelest genteelest +genteelly genteelli +gentile gentil +gentility gentil +gentle gentl +gentlefolk gentlefolk +gentlefolks gentlefolk +gentlema gentlema +gentleman gentleman +gentlemanlike gentlemanlik +gentlemanly gentleman +gentlemen gentlemen +gentleness gentl +gentler gentler +gentlest gentlest +gentlewoman gentlewoman +gently gentl +gentry gentri +genuine genuin +genuinely genuin +genus genus +geoffroi geoffroi +geoffroy geoffroy +geograph geograph +geographer geograph +geographica geographica +geographical geograph +geography geographi +geolog geolog +geological geolog +geologically geolog +geologicas geologica +geologist geologist +geologists geologist +geologize geolog +geologizing geolog +geology geolog +geometrical geometr +geometry geometri +george georg +georges georg +georgia georgia +georgina georgina +geospiza geospiza +geously geousli +geraldine geraldin +geranium geranium +geraniums geranium +germ germ +german german +germans german +germany germani +germinating germin +germs germ +gerous gerous +gervais gervai +geschichte geschicht +gesticulating gesticul +gesticulations gesticul +gesture gestur +gestures gestur +get get +gets get +getting get +gettings get +gewgaws gewgaw +gha gha +ghastlier ghastlier +ghastly ghast +ghirlandajo ghirlandajo +ghost ghost +ghostly ghost +ghosts ghost +ght ght +gi gi +giant giant +giants giant +gibing gibe +gibraltar gibraltar +giddily giddili +giddiness giddi +giddy giddi +gift gift +gifted gift +gifts gift +gig gig +gigantea gigantea +gigantic gigant +gigas giga +giggle giggl +giggled giggl +giggles giggl +giggling giggl +gild gild +gilded gild +gilding gild +gilds gild +giles gile +gill gill +gillies gilli +gillingwater gillingwat +gilt gilt +gimlet gimlet +gimlets gimlet +gin gin +ginger ginger +gingerbread gingerbread +gingery gingeri +gipsy gipsi +giraffe giraff +giraffes giraff +gird gird +girdle girdl +girdled girdl +girl girl +girlhood girlhood +girlish girlish +girlishly girlish +girls girl +girt girt +girth girth +girths girth +gist gist +git git +giuseppe giusepp +giv giv +give give +given given +giver giver +gives give +giving give +gizzard gizzard +gl gl +glacier glacier +glaciers glacier +glad glad +gladden gladden +gladdened gladden +glades glade +gladiator gladiat +gladly glad +gladness glad +gladsome gladsom +gladsomeness gladsom +glance glanc +glanced glanc +glances glanc +glancing glanc +glare glare +glared glare +glares glare +glaring glare +glaringly glare +glass glass +glasses glass +glassful glass +glassy glassi +glavormelly glavormelli +glaze glaze +glazed glaze +gleam gleam +gleamed gleam +gleaming gleam +gleams gleam +glean glean +gleaned glean +glee glee +gleefully gleefulli +gleesome gleesom +glen glen +glencora glencora +glib glib +glide glide +glided glide +glides glide +gliding glide +glimmer glimmer +glimmered glimmer +glimmering glimmer +glimmerings glimmer +glimpse glimps +glimpses glimps +glissez glissez +glisten glisten +glistened glisten +glistening glisten +glistens glisten +glitter glitter +glittered glitter +glittering glitter +gloated gloat +gloating gloat +globe globe +globes globe +globular globular +globules globul +glod glod +gloom gloom +gloomier gloomier +gloomily gloomili +gloominess gloomi +gloomy gloomi +gloried glori +glories glori +glorious glorious +glory glori +glorying glori +gloss gloss +glossary glossari +glossy glossi +gloucester gloucest +glove glove +gloved glove +gloves glove +glow glow +glowed glow +glowered glower +glowing glow +glows glow +glowworm glowworm +glowworms glowworm +glue glue +glum glum +glutinous glutin +glutton glutton +gluttons glutton +gnarled gnarl +gnashed gnash +gnashing gnash +gnats gnat +gnaw gnaw +gnawed gnaw +gnawer gnawer +gnawers gnawer +gnawing gnaw +gneiss gneiss +gnus gnus +go go +goa goa +goad goad +goaded goad +goads goad +goal goal +goar goar +goat goat +goatherd goatherd +goats goat +goatskin goatskin +goatsucker goatsuck +goblet goblet +goblets goblet +goblin goblin +god god +godalming godalm +godchild godchild +goddess goddess +godfather godfath +godfeyther godfeyth +godfrey godfrey +godless godless +godlike godlik +godly god +godmother godmoth +gods god +godsend godsend +godson godson +goeree goere +goes goe +goesler goesler +goeth goeth +goethe goeth +gog gog +goggle goggl +gogol gogol +going go +goings go +goitre goitr +gold gold +golden golden +goldfinch goldfinch +goldfinches goldfinch +goldfish goldfish +goldingsby goldingsbi +goldsmith goldsmith +golgotha golgotha +goloshes golosh +gomez gomez +gondola gondola +gone gone +gong gong +gonoph gonoph +gonzales gonzal +goo goo +good good +goodbye goodby +goodle goodl +goodly good +goodnaturedly goodnatur +goodness good +goods good +goodwill goodwil +goodwood goodwood +goose goos +gooseberries gooseberri +gooseberry gooseberri +gootther gootther +gorda gorda +gore gore +gorge gorg +gorged gorg +gorgeous gorgeous +gorgeously gorgeous +gorgeousness gorgeous +gorges gorg +gorging gorg +gormandize gormand +gorse gors +gory gori +gospel gospel +gossamer gossam +gossip gossip +gossiper gossip +gossiping gossip +gossips gossip +got got +gothic gothic +gothlands gothland +gott gott +gotten gotten +gould gould +gourmand gourmand +gourmands gourmand +gout gout +gouty gouti +gov gov +gove gove +govemment govem +govern govern +governed govern +governess gover +governesses gover +governessing gover +governing govern +government govern +governments govern +governor governor +governors governor +governorship governorship +governs govern +govett govett +govvernor govvernor +gower gower +gown gown +gownd gownd +gowns gown +gra gra +grace grace +gracechurch gracechurch +graced grace +graceful grace +gracefully grace +graceless graceless +graces grace +gracing grace +gracious gracious +graciously gracious +graciousness gracious +gradation gradat +gradations gradat +grade grade +grades grade +gradual gradual +gradually gradual +graduate graduat +graduated graduat +grafted graft +grafts graft +grain grain +grained grain +grains grain +grammar grammar +grammarian grammarian +grammars grammar +grammatical grammat +gran gran +granaries granari +grand grand +grandchild grandchild +grandchildren grandchildren +granddaughter granddaught +grande grand +grandee grande +grandees grande +grander grander +grandest grandest +grandeur grandeur +grandeurs grandeur +grandfather grandfath +grandfathers grandfath +grandiflorus grandiflorus +grandiloquent grandiloqu +grandiloquently grandiloqu +grandly grand +grandmama grandmama +grandmamma grandmamma +grandmother grandmoth +grandmothers grandmoth +grandpapa grandpapa +grandsire grandsir +grandson grandson +granite granit +granitic granit +granny granni +grant grant +granted grant +grantham grantham +granting grant +granular granular +granulo granulo +grape grape +grapes grape +grapevine grapevin +grapple grappl +grappled grappl +grappling grappl +grasp grasp +grasped grasp +grasping grasp +grasps grasp +graspus graspus +grass grass +grasses grass +grasshopper grasshopp +grasshoppers grasshopp +grassy grassi +grate grate +grated grate +grateful grate +gratefully grate +grater grater +grates grate +gratful grat +gratification gratif +gratified gratifi +gratifies gratifi +gratify gratifi +gratifying gratifi +grating grate +gratitude gratitud +gratuitous gratuit +gratuitously gratuit +gratulation gratul +gravamen gravamen +grave grave +graveclothes gravecloth +gravel gravel +gravelled gravel +gravelly gravelli +gravely grave +graver graver +graves grave +gravesend gravesend +gravest gravest +gravestone graveston +gravestones graveston +graveyard graveyard +gravies gravi +gravity graviti +gravy gravi +gray gray +graymarsh graymarsh +graze graze +grazed graze +grazes graze +grazier grazier +grazing graze +grea grea +grease greas +greased greas +greasily greasili +greasy greasi +great great +greatcoat greatcoat +greateful great +greater greater +greatest greatest +greatl greatl +greatly great +greatness great +grecian grecian +grecians grecian +greece greec +greed greed +greedily greedili +greediness greedi +greedy greedi +greek greek +green green +greener greener +greengrocer greengroc +greengrocery greengroceri +greenhorn greenhorn +greenish greenish +greenland greenland +greenleaf greenleaf +greenly green +greenness green +greens green +greenstone greenston +greensward greensward +greenwich greenwich +greet greet +greeted greet +greeting greet +greetings greet +greets greet +gregarious gregari +gregory gregori +gregsbury gregsburi +grenadier grenadi +grenadiers grenadi +gresham gresham +greshambury greshamburi +greta greta +grew grew +grey grey +greyhound greyhound +greyhounds greyhound +greyish greyish +gride gride +gridiron gridiron +gridley gridley +grief grief +griefs grief +grievance grievanc +grievances grievanc +grieve griev +grieved griev +grieves griev +grieving griev +grievous grievous +grievously grievous +griffin griffin +griffith griffith +griffiths griffith +grig grig +grigorievitch grigorievitch +grigoryev grigoryev +grim grim +grimace grimac +grimaces grimac +grimacing grimac +grimalkin grimalkin +grimble grimbl +grimbles grimbl +grime grime +grimed grime +grimes grime +grimly grim +grimy grimi +grin grin +grind grind +grinder grinder +grinders grinder +grinding grind +grinned grin +grinning grin +grins grin +grip grip +griping gripe +gripped grip +gripping grip +grips grip +grisly grisli +grist grist +gritting grit +grizzled grizzl +groan groan +groaned groan +groaning groan +groans groan +grocer grocer +grogram grogram +grogzwig grogzwig +groom groom +groomed groom +grooms groom +groove groov +grooves groov +grooving groov +grope grope +groped grope +gropes grope +gropin gropin +groping grope +grose grose +gross gross +grosser grosser +grossest grossest +grossly grossli +grossness gross +grosvenor grosvenor +grotesque grotesqu +grotesquely grotesqu +grottoes grotto +ground ground +grounded ground +groundless groundless +groundlessness groundless +grounds ground +groundwork groundwork +group group +grouped group +grouping group +groups group +grouse grous +grove grove +grovel grovel +grovelling grovel +groves grove +grow grow +groweth groweth +growin growin +growing grow +growl growl +growled growl +growlery growleri +growling growl +growlings growl +growls growl +grown grown +grows grow +growth growth +grub grub +grubbed grub +grubbing grub +grubble grubbl +grudden grudden +grudge grudg +grudged grudg +grudges grudg +grudgingly grudg +gruff gruff +gruffly gruffli +grumble grumbl +grumbled grumbl +grumbler grumbler +grumblers grumbler +grumbling grumbl +grumblings grumbl +grund grund +grunt grunt +grunted grunt +grunts grunt +gryllus gryllus +guanaco guanaco +guanacos guanaco +guano guano +guantajaya guantajaya +guarantee guarante +guaranteed guarante +guard guard +guardage guardag +guarded guard +guardedness guarded +guardhouse guardhous +guardia guardia +guardian guardian +guardians guardian +guardianship guardianship +guarding guard +guards guard +guardsman guardsman +guardsmen guardsmen +guasco guasco +guascos guasco +guaso guaso +guasos guaso +guatemala guatemala +guava guava +guayaquil guayaquil +guayatecas guayateca +guayavita guayavita +gucho gucho +gude gude +guerre guerr +guess guess +guessed guess +guesses guess +guessing guess +guest guest +guests guest +guffaw guffaw +guffawed guffaw +guffawing guffaw +guffy guffi +guid guid +guidance guidanc +guide guid +guided guid +guides guid +guiding guid +guilandina guilandina +guildford guildford +guile guil +guileless guileless +guilt guilt +guiltily guiltili +guiltiness guilti +guiltless guiltless +guilty guilti +guinea guinea +guineas guinea +guise guis +guitar guitar +guitron guitron +gulf gulf +gulfs gulf +gull gull +gulled gull +gullet gullet +gulleys gulley +gullies gulli +gulliver gulliv +gulls gull +gully gulli +gulp gulp +gulped gulp +gulping gulp +gulps gulp +gum gum +gums gum +gumwood gumwood +gun gun +gunless gunless +gunner gunner +gunnera gunnera +gunners gunner +gunnners gunnner +gunpowder gunpowd +guns gun +gunsmith gunsmith +gunther gunther +gunwale gunwal +gunwales gunwal +gup gup +guppy guppi +gurgled gurgl +gurgling gurgl +gush gush +gushed gush +gusher gusher +gushing gush +gust gust +guster guster +gusts gust +gusty gusti +gutta gutta +gutter gutter +guttered gutter +guttering gutter +gutters gutter +guttural guttur +guv guv +guy guy +guyaquil guyaquil +guzzling guzzl +gwyneth gwyneth +gymnasium gymnasium +gymnastic gymnast +gypsies gypsi +gypsum gypsum +gypsy gypsi +gyrations gyrat +h h +ha ha +habeas habea +haberdasher haberdash +habiliments habili +habit habit +habitable habit +habitation habit +habitations habit +habited habit +habits habit +habitual habitu +habitually habitu +habituated habitu +hachette hachett +hacienda hacienda +haciendero haciendero +hack hack +hackney hackney +hacks hack +had had +hadn hadn +hadst hadst +hag hag +haggard haggard +haggardly haggard +haggardness haggard +haggle haggl +hah hah +hail hail +hailed hail +hailing hail +hailstones hailston +hair hair +hairbrush hairbrush +hairdresser hairdress +haired hair +hairless hairless +hairs hair +hairy hairi +halcyon halcyon +hale hale +half half +halfpence halfpenc +halfpenny halfpenni +halfpennyworth halfpennyworth +halfway halfway +hall hall +hallo hallo +halloa halloa +halloo halloo +hallooing halloo +hallowed hallow +halls hall +hallucination hallucin +halo halo +halt halt +halted halt +halter halter +haltica haltica +halting halt +halts halt +halves halv +ham ham +hamilton hamilton +hamlet hamlet +hamlets hamlet +hammer hammer +hammercloths hammercloth +hammered hammer +hammering hammer +hammers hammer +hammersmith hammersmith +hammond hammond +hampdens hampden +hamper hamper +hampered hamper +hampering hamper +hampers hamper +hampshire hampshir +hampstead hampstead +hampton hampton +hams ham +hamstrings hamstr +hand hand +handcuff handcuff +handcuffed handcuf +handcuffs handcuff +hande hand +handed hand +handeder handed +handel handel +handful hand +handfuls hand +handing hand +handkercher handkerch +handkerchief handkerchief +handkerchiefs handkerchief +handle handl +handled handl +handles handl +handling handl +handmaid handmaid +handmaiden handmaiden +handrail handrail +hands hand +handsome handsom +handsomely handsom +handsomer handsom +handsomest handsomest +handwriting handwrit +handy handi +hang hang +hangdog hangdog +hanged hang +hanger hanger +hangers hanger +hanging hang +hangings hang +hangman hangman +hangs hang +hankering hanker +hankers hanker +hannah hannah +hanover hanov +hansome hansom +hap hap +haphazard haphazard +hapless hapless +haply hapli +happen happen +happened happen +happening happen +happens happen +happerton happerton +happertons happerton +happier happier +happiest happiest +happily happili +happiness happi +happy happi +harangue harangu +harangued harangu +harass harass +harassed harass +harassing harass +harbinger harbing +harbour harbour +harboured harbour +harbouring harbour +harbours harbour +hard hard +harden harden +hardened harden +hardening harden +harder harder +hardest hardest +hardihood hardihood +harding hard +hardly hard +hardness hard +hardship hardship +hardships hardship +hardworking hardwork +hardy hardi +hare hare +hares hare +hareskin hareskin +hark hark +harkee harke +harkov harkov +harkye harky +harlamov harlamov +harlequin harlequin +harlot harlot +harm harm +harmattan harmattan +harmful harm +harmless harmless +harmlessly harmless +harmonic harmon +harmonious harmoni +harmoniously harmoni +harmonised harmonis +harmony harmoni +harn harn +harness har +harnessed har +harnessing har +harold harold +harp harp +harpalidae harpalida +harpalus harpalus +harpies harpi +harping harp +harps harp +harpy harpi +harriet harriet +harriett harriett +harrington harrington +harris harri +harrison harrison +harrow harrow +harrowgate harrowg +harrowing harrow +harrows harrow +harse hars +harsh harsh +harsher harsher +harshest harshest +harshly harsh +harshness harsh +hart hart +hartlepod hartlepod +hartlepool hartlepool +hartshorn hartshorn +harum harum +harurn harurn +harvest harvest +has has +hash hash +hashed hash +hasn hasn +hasp hasp +hassan hassan +hast hast +haste hast +hasten hasten +hastened hasten +hastening hasten +hastens hasten +hastily hastili +hasty hasti +hat hat +hatch hatch +hatched hatch +hatches hatch +hatchet hatchet +hatching hatch +hatchings hatch +hatchment hatchment +hate hate +hated hate +hateful hate +hater hater +hates hate +hath hath +hating hate +hatless hatless +hatred hatr +hatreds hatr +hats hat +hatter hatter +hatton hatton +haughtiest haughtiest +haughtily haughtili +haughtiness haughti +haughtinesses haughti +haughty haughti +haul haul +hauled haul +hauling haul +haunches haunch +haunt haunt +haunted haunt +haunting haunt +haunts haunt +hav hav +have have +haven haven +having have +havoc havoc +hawdon hawdon +hawed haw +hawfinch hawfinch +hawk hawk +hawkinses hawkins +hawks hawk +hawthorns hawthorn +hay hay +haycock haycock +hayes hay +haymakers haymak +haymaking haymak +haymarket haymarket +haystacks haystack +hazard hazard +hazarded hazard +hazarding hazard +hazardous hazard +hazards hazard +haze haze +hazel hazel +hazy hazi +hd hd +he he +hea hea +head head +headache headach +headaches headach +headdress headdress +headed head +headgear headgear +heading head +headland headland +headlands headland +headless headless +headlong headlong +headmost headmost +headquarters headquart +heads head +headstrong headstrong +heal heal +healed heal +healing heal +health health +healthful health +healthier healthier +healthiness healthi +healths health +healthy healthi +heap heap +heaped heap +heaping heap +heaps heap +hear hear +heard heard +hearer hearer +hearers hearer +hearest hearest +hearing hear +hearken hearken +hearne hearn +hears hear +hearse hears +heart heart +heartache heartach +heartbroken heartbroken +heartburns heartburn +hearted heart +heartedest heartedest +heartedness hearted +heartfelt heartfelt +hearth hearth +hearths hearth +hearthstone hearthston +heartiest heartiest +heartily heartili +heartiness hearti +heartless heartless +heartlessly heartless +heartlessness heartless +heartrending heartrend +hearts heart +heartsease heartseas +heartsore heartsor +heartstrings heartstr +hearty hearti +heat heat +heated heat +heater heater +heath heath +heathen heathen +heather heather +heaths heath +heav heav +heave heav +heaved heav +heaven heaven +heavenly heaven +heavens heaven +heaver heaver +heaves heav +heavier heavier +heaviest heaviest +heavily heavili +heaviness heavi +heaving heav +heavings heav +heavv heavv +heavy heavi +hebrew hebrew +hecla hecla +hectic hectic +hectoring hector +hedge hedg +hedgehog hedgehog +hedgerows hedgerow +hedges hedg +hedging hedg +heed heed +heeded heed +heeding heed +heedless heedless +heedlessly heedless +heedlessness heedless +heeds heed +heel heel +heeled heel +heels heel +heerd heerd +heern heern +heigh heigh +heigho heigho +height height +heighten heighten +heightened heighten +heightening heighten +heightens heighten +heighth heighth +heights height +heinous heinous +heir heir +heiress heiress +heiresses heiress +heirlooms heirloom +heirs heir +heirship heirship +held held +helden helden +helen helen +helena helena +heliotrope heliotrop +helix helix +hell hell +helm helm +helmet helmet +helmets helmet +help help +helped help +helper helper +helpers helper +helpful help +helping help +helpless helpless +helplessly helpless +helplessness helpless +helpmate helpmat +helps help +helvellyn helvellyn +hem hem +hemiptera hemiptera +hemisphere hemispher +hemispheres hemispher +hemmed hem +hemming hem +hempen hempen +hen hen +hence henc +henceforth henceforth +henceforward henceforward +hend hend +henemies henemi +henrietta henrietta +henriette henriett +henry henri +hens hen +henslow henslow +heptarchy heptarchi +her her +herald herald +heralded herald +heraldic herald +herb herb +herbaceous herbac +herbage herbag +herbarium herbarium +herbert herbert +herbivorous herbivor +herbs herb +herculean herculean +hercules hercul +herd herd +herds herd +here here +hereabouts hereabout +hereafter hereaft +hereby herebi +hereditary hereditari +hereford hereford +herein herein +hereof hereof +heresy heresi +heretic heret +heretick heretick +hereticks heretick +heretics heret +heretofore heretofor +hereupon hereupon +herewith herewith +heritage heritag +hermit hermit +hermitage hermitag +hero hero +herod herod +heroded herod +heroes hero +heroic heroic +heroine heroin +heroism heroism +herons heron +herries herri +herrings herring +hers her +herschel herschel +herself herself +hertfordshire hertfordshir +heruvimov heruvimov +hesitate hesit +hesitated hesit +hesitates hesit +hesitating hesit +hesitatingly hesit +hesitation hesit +hesitations hesit +heterogeneous heterogen +heteromera heteromera +heteromerous heteromer +heteromidae heteromida +hever hever +hew hew +hewer hewer +hewers hewer +hewing hew +hey hey +heyday heyday +hi hi +hiatus hiatus +hibiscus hibiscus +hiccup hiccup +hiccuped hiccup +hid hid +hidden hidden +hide hide +hideous hideous +hideously hideous +hideousness hideous +hides hide +hiding hide +hierarchy hierarchi +hieroglyphics hieroglyph +higgenbottom higgenbottom +higgins higgin +high high +higher higher +highest highest +highfaluting highfalut +highgate highgat +highl highl +highland highland +highlanders highland +highlands highland +highly high +highness high +highroad highroad +highway highway +highwayman highwayman +highways highway +hignominiousness hignomini +hilaire hilair +hilarious hilari +hilariously hilari +hilarity hilar +hilda hilda +hill hill +hillock hillock +hillocks hillock +hills hill +hillsides hillsid +hilltops hilltop +hilly hilli +hilt hilt +hilts hilt +him him +himalaya himalaya +himantopus himantopus +himsel himsel +himself himself +hind hind +hinder hinder +hindered hinder +hindering hinder +hindoos hindoo +hindrance hindranc +hinds hind +hindu hindu +hing hing +hinges hing +hint hint +hinted hint +hinting hint +hints hint +hip hip +hippah hippah +hippahs hippah +hipped hip +hippish hippish +hippopotamus hippopotamus +hippopotamuses hippopotamus +hips hip +hire hire +hired hire +hiring hire +hirrold hirrold +his his +hiss hiss +hisself hisself +hisses hiss +hissing hiss +hist hist +histoire histoir +historian historian +historical histor +historically histor +histories histori +history histori +histrionic histrion +hit hit +hitch hitch +hitchcock hitchcock +hitched hitch +hitches hitch +hitching hitch +hither hither +hitherto hitherto +hitherward hitherward +hits hit +hitting hit +hittites hittit +hive hive +hl hl +hm hm +ho ho +hoar hoar +hoard hoard +hoarded hoard +hoarding hoard +hoardings hoard +hoards hoard +hoarse hoars +hoarsely hoars +hoarser hoarser +hoary hoari +hob hob +hobart hobart +hobbled hobbl +hobbledehoy hobbledehoy +hobbles hobbl +hobbling hobbl +hobby hobbi +hobgoblin hobgoblin +hoch hoch +hochbeseeltes hochbeseelt +hock hock +hod hod +hof hof +hoffmanseggi hoffmanseggi +hog hog +hogoleu hogoleu +hogs hog +hoist hoist +hoisted hoist +hoity hoiti +holborn holborn +hold hold +holden holden +holder holder +holders holder +holding hold +holds hold +hole hole +holes hole +holiday holiday +holidays holiday +holies holi +holily holili +holiness holi +holland holland +hollies holli +hollo hollo +holloa holloa +hollow hollow +holloway holloway +hollowed hollow +hollower hollow +hollowness hollow +hollows hollow +holly holli +holman holman +holstein holstein +holuthuriae holuthuria +holy holi +holyhead holyhead +homage homag +hombre hombr +home home +homeless homeless +homelessness homeless +homelike homelik +homely home +homes home +homeward homeward +homewards homeward +homicidal homicid +homily homili +homoptera homoptera +hon hon +hond hond +honds hond +honest honest +honester honest +honestest honestest +honestly honest +honesty honesti +honey honey +honeymoon honeymoon +honeysuckle honeysuckl +hong hong +honoria honoria +honour honour +honourable honour +honourably honour +honourahle honourahl +honoured honour +honouring honour +honourmg honourmg +honours honour +honysuckles honysuckl +hoo hoo +hood hood +hooded hood +hoodle hoodl +hoodwinked hoodwink +hoof hoof +hoofs hoof +hook hook +hooked hook +hooker hooker +hooking hook +hookites hookit +hooks hook +hoold hoold +hoonger hoonger +hoongry hoongri +hoop hoop +hooping hoop +hoops hoop +hoor hoor +hooray hooray +hoorly hoor +hooted hoot +hooting hoot +hootings hoot +hoots hoot +hop hop +hope hope +hoped hope +hopeful hope +hopefully hope +hopefulness hope +hopeless hopeless +hopelessly hopeless +hopelessness hopeless +hopes hope +hoping hope +hopped hop +hopping hop +hops hop +horatio horatio +horders horder +horizon horizon +horizonta horizonta +horizontal horizont +horizontally horizont +horn horn +horned horn +horner horner +hornet hornet +hornos horno +hornpipe hornpip +hornpipes hornpip +horns horn +hornsey hornsey +horny horni +horrible horribl +horribly horribl +horrid horrid +horridly horrid +horrified horrifi +horror horror +horrors horror +horse hors +horseback horseback +horsecloths horsecloth +horseflesh horseflesh +horsefly horsefli +horsehair horsehair +horseman horseman +horsemanship horsemanship +horsemen horsemen +horsepittle horsepittl +horses hors +horsewhip horsewhip +horsewhipped horsewhip +horsewhipping horsewhip +hortense hortens +hortensio hortensio +horticultural horticultur +horticulture horticultur +hose hose +hospitable hospit +hospitably hospit +hospital hospit +hospitalities hospit +hospitality hospit +hospitals hospit +hospitility hospitil +host host +hostages hostag +hoste host +hostelry hostelri +hostess hostess +hostesses hostess +hostile hostil +hostilities hostil +hostility hostil +hostlers hostler +hosts host +hot hot +hotel hotel +hotels hotel +hothouse hothous +hotly hot +hottentot hottentot +hottentots hottentot +hotter hotter +hottest hottest +hou hou +hound hound +hounded hound +hounding hound +hounds hound +hour hour +houri houri +hourly hour +hours hour +house hous +housebreaker housebreak +housebuilder housebuild +housed hous +household household +housekeeper housekeep +housekeepers housekeep +housekeeping housekeep +housemaid housemaid +housemaids housemaid +housemaker housemak +houses hous +housetops housetop +housewife housewif +housewifery housewiferi +hove hove +hovel hovel +hovels hovel +hover hover +hovered hover +hovering hover +hovers hover +how how +howard howard +howbeit howbeit +howell howel +howeve howev +however howev +howitt howitt +howl howl +howled howl +howling howl +howls howl +howsoever howsoev +huacas huaca +huachos huacho +huantamo huantamo +huapi huapi +huaraz huaraz +hubbard hubbard +hubbub hubbub +huckster huckster +huddled huddl +hue hue +huechucucuy huechucucuy +hues hue +huff huff +huffily huffili +huffy huffi +hug hug +huge huge +hugged hug +hugging hug +huggins huggin +hugh hugh +hugs hug +huitreu huitreu +hulk hulk +hullo hullo +hulloa hulloa +hum hum +humain humain +humaine humain +human human +humane human +humanely human +humanising humanis +humanity human +humanizing human +humanly human +humanum humanum +humble humbl +humbled humbl +humbleness humbl +humbler humbler +humblest humblest +humbling humbl +humbly humbl +humboldt humboldt +humbug humbug +humbugging humbug +humdrum humdrum +humid humid +humidity humid +humiliate humili +humiliated humili +humiliating humili +humiliation humili +humility humil +hummed hum +humming hum +hummingbirds hummingbird +hummocks hummock +humorous humor +humorously humor +humour humour +humoured humour +humouredly humour +humouring humour +humours humour +hump hump +humph humph +hums hum +hunchback hunchback +hundred hundr +hundreds hundr +hundredth hundredth +hundredweight hundredweight +hung hung +hunger hunger +hungering hunger +hungry hungri +hunks hunk +hunky hunki +hunt hunt +hunted hunt +hunter hunter +hunters hunter +hunting hunt +hunts hunt +huntsman huntsman +huntsmen huntsmen +hurled hurl +hurly hur +hurrah hurrah +hurrahed hurrah +hurrahs hurrah +hurricane hurrican +hurried hurri +hurriedly hurri +hurries hurri +hurry hurri +hurrying hurri +hurt hurt +hurtado hurtado +hurting hurt +hurts hurt +husband husband +husbanded husband +husbandman husbandman +husbands husband +hush hush +hushed hush +hushing hush +husk husk +huskily huskili +huskiness huski +husky huski +hussar hussar +hussy hussi +hustings hust +hustle hustl +hustled hustl +hustling hustl +hut hut +hutch hutch +huts hut +hutton hutton +hy hy +hyacinth hyacinth +hyacinths hyacinth +hyaena hyaena +hybernate hybern +hybernating hybern +hybernation hybern +hybrid hybrid +hybrida hybrida +hyde hyde +hydra hydra +hydraulic hydraul +hydrobius hydrobius +hydrochaerus hydrochaerus +hydrogen hydrogen +hydrographer hydrograph +hydrophilidae hydrophilida +hydrophilus hydrophilus +hydrophobia hydrophobia +hydroporus hydroporus +hygrometer hygromet +hyla hyla +hymenophallus hymenophallus +hymenoptera hymenoptera +hymenopterous hymenopter +hymn hymn +hymns hymn +hyperbolical hyperbol +hyperion hyperion +hypochondria hypochondria +hypochondriac hypochondriac +hypochondriacal hypochondriac +hypocrisy hypocrisi +hypocrite hypocrit +hypocritical hypocrit +hypocritically hypocrit +hypotheses hypothes +hypothesis hypothesi +hypothetical hypothet +hyseters hyset +hysteric hyster +hysterical hyster +hysterically hyster +hysterics hyster +i i +iagoensis iagoensi +ibis ibi +ica ica +ice ice +iceberg iceberg +icebergs iceberg +iced ice +iceland iceland +ices ice +ich ich +icterus icterus +icy ici +ide ide +idea idea +ideal ideal +idealism ideal +idealist idealist +ideality ideal +ideals ideal +ideas idea +identical ident +identically ident +identification identif +identified identifi +identifles identifl +identifying identifi +identity ident +idiocy idioci +idiosyncrasies idiosyncrasi +idiosyncrasy idiosyncrasi +idiot idiot +idiotcy idiotci +idiotic idiot +idiotically idiot +idiots idiot +idle idl +idleness idl +idlers idler +idlest idlest +idling idl +idly idl +idol idol +idolatrous idolatr +idolatry idolatri +idolized idol +ie ie +ied ie +if if +ies ie +ight ight +ighway ighway +igneous igneous +ignited ignit +igniting ignit +ignoble ignobl +ignominious ignomini +ignominy ignomini +ignoramuses ignoramus +ignorance ignor +ignorant ignor +ignorantly ignor +ignore ignor +ignored ignor +ignoring ignor +iguana iguana +ii ii +iii iii +ikon ikon +ikons ikon +il il +iles ile +ill ill +illapel illapel +illegible illeg +illegitimate illegitim +illiberal illiber +illig illig +illimitable illimit +illiterate illiter +illness ill +illnesses ill +illuminate illumin +illuminated illumin +illuminating illumin +illumined illumin +illusion illus +illusions illus +illustrated illustr +illustrates illustr +illustrating illustr +illustration illustr +illustrations illustr +illustrative illustr +illustrious illustri +ils il +ilya ilya +image imag +images imag +imaginable imagin +imaginary imaginari +imagination imagin +imaginative imagin +imagine imagin +imagined imagin +imagines imagin +imagining imagin +imaginings imagin +imbecile imbecil +imbecility imbecil +imbedded imbed +imbibed imbib +imbue imbu +imbued imbu +imeantersay imeantersay +imitate imit +imitated imit +imitating imit +imitation imit +imitations imit +imitative imit +imitator imit +immaculate immacul +immaterial immateri +immature immatur +immeasurable immeasur +immeasurably immeasur +immediate immedi +immediately immedi +immemorial immemori +immense immens +immensely immens +immensity immens +immensus immensus +immersed immers +immersion immers +immigrants immigr +imminent immin +immoderate immoder +immolate immol +immolation immol +immoral immor +immorality immor +immortal immort +immortality immort +immovability immov +immovable immov +immovably immov +immoveable immov +immured immur +immutability immut +immutable immut +imp imp +impair impair +impaired impair +impairing impair +impaling impal +impalpable impalp +impalpably impalp +impanelled impanel +impart impart +imparted impart +impartial imparti +impartiality imparti +impartially imparti +imparting impart +imparts impart +impassable impass +impassibility impass +impassible impass +impassioned impass +impassive impass +impassiveness impass +impatience impati +impatient impati +impatiently impati +impeach impeach +impeachment impeach +impecuniosity impecunios +impecunious impecuni +impede imped +impeded imped +impediment impedi +impediments impedi +impel impel +impelled impel +impels impel +impend impend +impending impend +impenetrabilities impenetr +impenetrable impenetr +imperative imper +imperatively imper +imperceptibly impercept +imperfect imperfect +imperfection imperfect +imperfectly imperfect +imperial imperi +imperilled imperil +imperils imperil +imperious imperi +imperiously imperi +impersonal imperson +impertinence impertin +impertinent impertin +impertinently impertin +imperturbability imperturb +imperturbable imperturb +imperturbably imperturb +impervious impervi +impetuosity impetuos +impetuous impetu +impetuously impetu +impiety impieti +impious impious +implacable implac +implacably implac +implanted implant +implement implement +implements implement +implicate implic +implicated implic +implication implic +implicit implicit +implicitly implicit +implied impli +implies impli +implore implor +implored implor +imploring implor +imploringly implor +imply impli +implying impli +impolitic impolit +import import +importance import +important import +importation import +imported import +importer import +importing import +importunate importun +importunity importun +impose impos +imposed impos +imposing impos +imposition imposit +impossibilities imposs +impossibility imposs +impossible imposs +imposter impost +impostors impostor +imposture impostur +impostures impostur +impotence impot +impotent impot +impoverished impoverish +impracticability impractic +impracticable impractic +impracticality impract +imprecation imprec +imprecations imprec +impregnability impregn +impregnable impregn +impregnated impregn +impress impress +impressed impress +impresses impress +impressible impress +impressing impress +impression impress +impressionable impression +impressions impress +impressive impress +impressively impress +imprinted imprint +imprinting imprint +imprisoned imprison +imprisonment imprison +improbability improb +improbable improb +improbably improb +impromptu impromptu +improper improp +improperly improp +impropriety improprieti +improve improv +improved improv +improvement improv +improvements improv +improves improv +improvident improvid +improving improv +improvisatrice improvisatric +imprudence imprud +imprudent imprud +imprudently imprud +imps imp +impudence impud +impudent impud +impudently impud +impugned impugn +impulse impuls +impulses impuls +impulsive impuls +impulsively impuls +impulsiveness impuls +impunity impun +impure impur +impurity impur +imputation imput +impute imput +imputed imput +imputing imput +imself imself +in in +inability inabl +inaccessible inaccess +inaccurate inaccur +inaccurately inaccur +inaction inact +inactive inact +inactivity inact +inadequate inadequ +inadmissible inadmiss +inadvertently inadvert +inanimate inanim +inanities inan +inanity inan +inappeasable inappeas +inapplicable inapplic +inappreciable inappreci +inappropriate inappropri +inappropriately inappropri +inaptitude inaptitud +inaptly inapt +inarticulate inarticul +inarticulately inarticul +inartistic inartist +inasmuch inasmuch +inattention inattent +inattentive inattent +inaudible inaud +inaudibly inaud +inaugurate inaugur +inaugurated inaugur +inaugurates inaugur +inauspicious inauspici +inborn inborn +inbred inbr +incalculable incalcul +incalculably incalcul +incapable incap +incapacitated incapacit +incapacity incapac +incarnation incarn +incas inca +incased incas +incautious incauti +incautiously incauti +incense incens +incensed incens +incentive incent +incessant incess +incessantly incess +inch inch +inches inch +incident incid +incidental incident +incidentally incident +incidents incid +incipient incipi +incisions incis +incisive incis +incited incit +incitement incit +incivility incivil +inclemency inclem +inclement inclement +inclination inclin +inclinations inclin +incline inclin +inclined inclin +inclines inclin +inclining inclin +inclosure inclosur +include includ +included includ +includes includ +including includ +inclusive inclus +incog incog +incognita incognita +incognito incognito +incoherence incoher +incoherent incoher +incoherently incoher +income incom +incoming incom +incommoded incommod +incomparably incompar +incompatibility incompat +incompatible incompat +incomplete incomplet +incomprehensible incomprehens +inconceivable inconceiv +incongruity incongru +incongruous incongru +inconsiderable inconsider +inconsiderate inconsider +inconsiderately inconsider +inconsiderateness inconsider +inconsistencies inconsist +inconsistency inconsist +inconsistent inconsist +inconsistently inconsist +inconsolable inconsol +inconstancy inconst +inconstant inconst +incontestable incontest +incontestably incontest +inconvenience inconveni +inconvenienced inconvenienc +inconveniences inconveni +inconveniency inconveni +inconvenient inconveni +inconveniently inconveni +incorrect incorrect +incorrectly incorrect +incorrigible incorrig +incorruptible incorrupt +increase increas +increased increas +increases increas +increasing increas +increasingly increas +incredible incred +incredibly incred +incredulity incredul +incredulous incredul +incredulously incredul +incrustation incrust +incrustations incrust +incrusted incrust +incubation incub +incubus incubus +inculcate inculc +inculcates inculc +inculcating inculc +incumbent incumb +incumbrance incumbr +incumbrances incumbr +incur incur +incurious incuri +incurred incur +incursion incurs +indebted indebt +indecency indec +indecent indec +indecently indec +indecision indecis +indecorous indecor +indecorously indecor +indeed inde +indefatigable indefatig +indefatigably indefatig +indefinable indefin +indefinably indefin +indefinite indefinit +indefinitely indefinit +indelible indel +indelibly indel +indelicate indel +indented indent +indenting indent +indenture indentur +independence independ +independent independ +independently independ +independeuce independeuc +inder inder +indescribable indescrib +indescribably indescrib +indestructible indestruct +india india +indiaman indiaman +indian indian +indians indian +indica indica +indicate indic +indicated indic +indicates indic +indicating indic +indication indic +indications indic +indicative indic +indies indi +indifference indiffer +indifferent indiffer +indifferently indiffer +indigenous indigen +indigent indig +indigestion indigest +indignant indign +indignantly indign +indignation indign +indignities indign +indignity indign +indigo indigo +indios indio +indirect indirect +indirectly indirect +indiscreet indiscreet +indiscreetness indiscreet +indiscretion indiscret +indiscretions indiscret +indiscriminate indiscrimin +indiscriminately indiscrimin +indiscriminating indiscrimin +indispensable indispens +indispensably indispens +indisposed indispos +indisposition indisposit +indisputably indisput +indistinct indistinct +indistinctly indistinct +indistinctness indistinct +indistinguishable indistinguish +indited indit +individua individua +individual individu +individualism individu +individuality individu +individually individu +individuals individu +indo indo +indolence indol +indolent indol +indolently indol +indomitable indomit +indoor indoor +indoors indoor +indubitable indubit +indubitably indubit +induce induc +induced induc +inducement induc +inducements induc +induces induc +inducing induc +inducted induct +inducts induct +indulge indulg +indulged indulg +indulgence indulg +indulgences indulg +indulgent indulg +indulging indulg +indurated indur +industrie industri +industrious industri +industriously industri +industry industri +inebriated inebri +inebriety inebrieti +ineffable ineff +ineffective ineffect +ineffectiveness ineffect +ineffectual ineffectu +ineffectually ineffectu +inefficacious inefficaci +inefficacy inefficaci +inefficiency ineffici +inefficient ineffici +inelegance ineleg +ineptitude ineptitud +inequalities inequ +inequality inequ +ineradicable ineradic +inermis inermi +inert inert +inertia inertia +inertness inert +inestimable inestim +inestimably inestim +inevitable inevit +inevitably inevit +inexcusable inexcus +inexhaustible inexhaust +inexorable inexor +inexpedient inexpedi +inexperience inexperi +inexperienced inexperienc +inexpiable inexpi +inexplicable inexplic +inexpressible inexpress +inexpressibles inexpress +inexpressibly inexpress +inexpressive inexpress +inexpressively inexpress +inextinguishable inextinguish +infallibility infal +infallible infal +infallibly infal +infame infam +infamies infami +infamous infam +infamy infami +infancy infanc +infant infant +infanticide infanticid +infantine infantin +infantry infantri +infants infant +infatuated infatu +infatuation infatu +infect infect +infected infect +infection infect +infectious infecti +infer infer +inference infer +inferior inferior +inferiorities inferior +inferiority inferior +inferiors inferior +infernal infern +inferred infer +inferring infer +infested infest +infidel infidel +infidelities infidel +infidelity infidel +infidels infidel +infinite infinit +infinitely infinit +infinitesimal infinitesim +infinitum infinitum +infinity infin +infirm infirm +infirmities infirm +infirmity infirm +inflamed inflam +inflammable inflamm +inflammation inflamm +inflated inflat +inflates inflat +inflation inflat +inflexam inflexam +inflexibility inflex +inflexible inflex +inflict inflict +inflicted inflict +inflicting inflict +infliction inflict +inflicts inflict +influence influenc +influenced influenc +influences influenc +influencing influenc +influential influenti +influx influx +inform inform +informant inform +information inform +informed inform +informer inform +informing inform +informs inform +infra infra +infrequency infrequ +infrequent infrequ +infrequently infrequ +infuriated infuri +infuse infus +infused infus +infusing infus +infusoria infusoria +infusorial infusori +ing ing +ingenio ingenio +ingenious ingeni +ingeniously ingeni +ingenuity ingenu +ingenuous ingenu +ingenuously ingenu +ingleses ingles +ingrained ingrain +ingratiate ingrati +ingratiated ingrati +ingratiating ingrati +ingratitude ingratitud +ingredient ingredi +ingredients ingredi +inhabit inhabit +inhabitant inhabit +inhabitants inhabit +inhabited inhabit +inhabiting inhabit +inhabits inhabit +inhaled inhal +inhaling inhal +inharmonious inharmoni +inherent inher +inherit inherit +inheritance inherit +inherited inherit +inheriting inherit +inhospitable inhospit +inhospitality inhospit +inhuman inhuman +inhumanity inhuman +inhumanly inhuman +inimical inim +iniquities iniqu +iniquity iniqu +init init +initial initi +initiated initi +initiation initi +initiative initi +initiatory initiatori +injected inject +injection inject +injections inject +injudicious injudici +injudiciously injudici +injunction injunct +injunctions injunct +injure injur +injured injur +injures injur +injuries injuri +injuring injur +injurious injuri +injury injuri +injustice injustic +ink ink +inked ink +inkling inkl +inkpot inkpot +inkstand inkstand +inkstands inkstand +inkwhich inkwhich +inkwhiched inkwhich +inky inki +inlaid inlaid +inland inland +inlet inlet +inlets inlet +inmate inmat +inmates inmat +inmost inmost +inn inn +innate innat +inner inner +innings inning +innkeeper innkeep +innkeepers innkeep +innocence innoc +innocent innoc +innocently innoc +innocents innoc +innocuous innocu +innombrable innombr +inns inn +innuendo innuendo +innuendoes innuendo +innumerable innumer +inoffensive inoffens +inopportune inopportun +inopportunely inopportun +inorganic inorgan +inquest inquest +inquests inquest +inquire inquir +inquired inquir +inquirer inquir +inquirers inquir +inquires inquir +inquiries inquiri +inquiring inquir +inquiringly inquir +inquiry inquiri +inquisition inquisit +inquisitive inquisit +inquisitively inquisit +inquisitiveness inquisit +inroad inroad +inroads inroad +ins in +insane insan +insanity insan +insatiable insati +insatiate insati +inscribed inscrib +inscription inscript +inscriptions inscript +inscrutable inscrut +insect insect +insects insect +insecure insecur +insecurity insecur +insense insens +insensibility insens +insensible insens +insensibly insens +inseparable insepar +inserted insert +inserting insert +insertion insert +inserts insert +inside insid +insides insid +insight insight +insignificance insignific +insignificant insignific +insinuate insinu +insinuated insinu +insinuating insinu +insinuation insinu +insinuations insinu +insipid insipid +insipidity insipid +insist insist +insisted insist +insistence insist +insistent insist +insistently insist +insistes insist +insisting insist +insists insist +insolence insol +insolent insol +insolently insol +insolvent insolv +insomuch insomuch +inspect inspect +inspected inspect +inspecting inspect +inspection inspect +inspector inspector +inspects inspect +inspiration inspir +inspire inspir +inspired inspir +inspires inspir +inspiring inspir +inspirit inspirit +inspiriting inspirit +instability instabl +installed instal +instalment instal +instance instanc +instanced instanc +instances instanc +instant instant +instantaneous instantan +instantaneously instantan +instantly instant +instea instea +instead instead +instigated instig +instigation instig +instigator instig +instil instil +instinct instinct +instinctive instinct +instinctively instinct +instincts instinct +institut institut +institute institut +instituted institut +institution institut +institutions institut +instruct instruct +instructed instruct +instructing instruct +instruction instruct +instructions instruct +instructive instruct +instructor instructor +instructs instruct +instrument instrument +instrumental instrument +instrumentality instrument +instruments instrument +insubordinate insubordin +insubordination insubordin +insufferable insuffer +insufferably insuffer +insufficient insuffici +insufficiently insuffici +insular insular +insulated insul +insult insult +insulted insult +insulting insult +insults insult +insuperable insuper +insupportable insupport +insure insur +insured insur +insuring insur +insurmountable insurmount +intact intact +integral integr +integrity integr +intellect intellect +intellects intellect +intellectual intellectu +intellectuality intellectu +intellectually intellectu +intelligence intellig +intelligent intellig +intelligently intellig +intelligible intellig +intelligibly intellig +intemperance intemper +intemperate intemper +intend intend +intended intend +intendeds intend +intending intend +intends intend +intense intens +intensely intens +intensest intensest +intensifies intensifi +intensifying intensifi +intensity intens +intent intent +intention intent +intentional intent +intentionally intent +intentioned intent +intentions intent +intently intent +intents intent +inter inter +intercalated intercal +intercede interced +intercept intercept +intercepted intercept +intercepting intercept +intercepts intercept +intercession intercess +interchange interchang +interchangeable interchang +interchanged interchang +interchanging interchang +intercourse intercours +interest interest +interested interest +interestin interestin +interesting interest +interests interest +interfere interfer +interfered interf +interference interfer +interferes interfer +interfering interf +interior interior +interjection interject +interlacings interlac +interleaved interleav +interloper interlop +interlopers interlop +interlude interlud +intermarriages intermarriag +intermeddling intermeddl +intermediate intermedi +interminable intermin +intermingling intermingl +intermission intermiss +intermittent intermitt +internal intern +internally intern +international intern +interpose interpos +interposed interpos +interposes interpos +interposing interpos +interposition interposit +interpret interpret +interpretation interpret +interpretations interpret +interpreted interpret +interpreter interpret +interrogate interrog +interrogated interrog +interrogating interrog +interrogations interrog +interrogator interrog +interrogatories interrogatori +interrogatory interrogatori +interrupt interrupt +interrupted interrupt +interrupting interrupt +interruption interrupt +interruptions interrupt +interrupts interrupt +intersect intersect +intersected intersect +intersecting intersect +intersection intersect +interspersed interspers +interspersing interspers +interstices interstic +interstratified interstratifi +intertropical intertrop +intertwined intertwin +interval interv +intervals interv +intervened interven +intervening interven +interview interview +interviews interview +interwoven interwoven +intestate intest +intestinal intestin +intestines intestin +intimacy intimaci +intimate intim +intimated intim +intimately intim +intimates intim +intimating intim +intimation intim +intimidated intimid +intimidation intimid +intiv intiv +into into +intolerable intoler +intolerably intoler +intombed intomb +intonation inton +intonations inton +intoning inton +intoxicated intox +intoxicating intox +intoxication intox +intractable intract +intreat intreat +intrepid intrepid +intrepidity intrepid +intricacies intricaci +intricate intric +intrigue intrigu +intrigued intrigu +intrigues intrigu +intriguing intrigu +intrinsic intrins +introduce introduc +introduced introduc +introduces introduc +introducing introduc +introduction introduct +introductions introduct +introductory introductori +intrude intrud +intruded intrud +intruder intrud +intrudes intrud +intruding intrud +intrusion intrus +intrusive intrus +intrust intrust +intrusted intrust +intuition intuit +intuitive intuit +intwined intwin +intwining intwin +inundated inund +inundations inund +inured inur +inutility inutil +invade invad +invaded invad +invaders invad +invading invad +invalid invalid +invalidate invalid +invalided invalid +invalids invalid +invaluable invalu +invariable invari +invariably invari +invasion invas +invective invect +invectives invect +inveighed inveigh +inveigle inveigl +inveigled inveigl +invencion invencion +invent invent +invented invent +inventing invent +invention invent +inventions invent +inventory inventori +invents invent +inverness inver +invertebrate invertebr +inverted invert +invest invest +invested invest +investigate investig +investigated investig +investigating investig +investigation investig +investigations investig +investigators investig +investment invest +invests invest +inveterate inveter +invigorate invigor +invigorated invigor +invigorating invigor +invigoration invigor +invincible invinc +invisible invis +invisibly invis +invitation invit +invitations invit +invite invit +invited invit +invites invit +inviting invit +invitingly invit +invoking invok +involuntarily involuntarili +involuntary involuntari +involutions involut +involve involv +involved involv +involvement involv +involves involv +involving involv +inward inward +inwardly inward +inwards inward +inwentory inwentori +iodic iodic +ionic ionic +iota iota +iou iou +iquique iquiqu +irascibility irasc +irascible irasc +irascibly irasc +irate irat +ire ire +ireland ireland +iridescent iridesc +iris iri +irish irish +irishman irishman +irishmen irishmen +irishwoman irishwoman +irksome irksom +irksomeness irksom +iron iron +ironed iron +ironical iron +ironically iron +ironing iron +ironmaster ironmast +ironmasters ironmast +ironmonger ironmong +irons iron +irony ironi +irradiated irradi +irrational irrat +irreclaimable irreclaim +irreconcilable irreconcil +irrecoverable irrecover +irredeemable irredeem +irrefutable irrefut +irregular irregular +irregularities irregular +irregularity irregular +irregularly irregular +irrelevant irrelev +irrepressible irrepress +irreproachable irreproach +irresistible irresist +irresistibly irresist +irresolute irresolut +irresolutely irresolut +irresolution irresolut +irrespective irrespect +irresponsible irrespons +irresponsive irrespons +irretrievable irretriev +irretrievably irretriev +irreverent irrever +irreverently irrever +irrevocable irrevoc +irrevocably irrevoc +irrigate irrig +irrigated irrig +irrigating irrig +irrigation irrig +irritability irrit +irritable irrit +irritably irrit +irritate irrit +irritated irrit +irritating irrit +irritation irrit +irruption irrupt +irtish irtish +is is +isabel isabel +isaiah isaiah +isid isid +isidro isidro +island island +islanders island +islands island +isle isl +isles isl +islet islet +islets islet +islington islington +isn isn +isobel isobel +isolated isol +isolation isol +israelites israelit +issue issu +issued issu +issues issu +issuing issu +ist ist +isthmus isthmus +it it +italian italian +italy itali +itch itch +itchen itchen +itching itch +item item +items item +ithacaia ithacaia +itinerant itiner +its it +itself itself +iv iv +ivan ivan +ivanitch ivanitch +ivanovitch ivanovitch +ivanovna ivanovna +ivory ivori +ivy ivi +ix ix +ixion ixion +j j +ja ja +jabbers jabber +jaca jaca +jack jack +jackals jackal +jackanapes jackanap +jackas jacka +jackdaw jackdaw +jackdaws jackdaw +jacket jacket +jackets jacket +jacks jack +jackson jackson +jacob jacob +jacuitque jacuitqu +jaculation jacul +jade jade +jaded jade +jading jade +jag jag +jagged jag +jago jago +jaguar jaguar +jaguars jaguar +jail jail +jailer jailer +jajuel jajuel +jam jam +jamaica jamaica +james jame +jammed jam +jams jam +jan jan +jane jane +janeiro janeiro +janes jane +jangled jangl +jangling jangl +january januari +japan japan +jar jar +jargon jargon +jargonelle jargonell +jarnders jarnder +jarndyce jarndyc +jarndyces jarndyc +jarodyce jarodyc +jarring jar +jasmine jasmin +jaundice jaundic +jaundiced jaundic +jaunt jaunt +jauntily jauntili +jauntiness jaunti +jaunty jaunti +java java +javelin javelin +jaw jaw +jawed jaw +jawlly jawlli +jaws jaw +je je +jea jea +jealous jealous +jealousies jealousi +jealously jealous +jealousy jealousi +jean jean +jeanie jeani +jeer jeer +jeered jeer +jeering jeer +jeeringly jeer +jeers jeer +jell jell +jelly jelli +jellyby jellybi +jellybys jellybi +jemmy jemmi +jenkins jenkin +jennings jen +jenny jenni +jennys jenni +jenyns jenyn +jeopardy jeopardi +jeremy jeremi +jericho jericho +jerk jerk +jerked jerk +jerkily jerkili +jerking jerk +jerks jerk +jerky jerki +jerry jerri +jerusalem jerusalem +jest jest +jesting jest +jestingly jest +jests jest +jesuit jesuit +jesuitical jesuit +jesus jesus +jet jet +jets jet +jew jew +jewby jewbi +jewel jewel +jeweler jewel +jewelled jewel +jeweller jewel +jewellers jewel +jewellery jewelleri +jewels jewel +jewess jewess +jewish jewish +jews jew +jezebel jezebel +jilted jilt +jingle jingl +jingled jingl +jingles jingl +jingling jingl +jist jist +jo jo +joan joan +joanna joanna +job job +jobbed job +jobling jobl +jobs job +jockey jockey +jocose jocos +jocosely jocos +jocoseness jocos +jocular jocular +jocularity jocular +jocularly jocular +jocundity jocund +joe joe +joful joful +jog jog +jogg jogg +jogged jog +jogging jog +johann johann +john john +johnnie johnni +johnny johnni +johnson johnson +join join +joined join +joinin joinin +joining join +joins join +joint joint +jointly joint +joints joint +joke joke +joked joke +joker joker +jokers joker +jokes joke +joking joke +jolliest jolliest +jollity jolliti +jolly jolli +jolquera jolquera +jolt jolt +jolted jolt +jolter jolter +jolting jolt +jolts jolt +jones jone +joneses jones +joodle joodl +jordan jordan +jorullo jorullo +jose jose +joseph joseph +joshua joshua +jostle jostl +jostled jostl +jostling jostl +jot jot +jour jour +journ journ +journal journal +journalist journalist +journalistic journalist +journals journal +journey journey +journeyed journey +journeying journey +journeyings journey +journeyman journeyman +journeys journey +jove jove +jovial jovial +joviality jovial +jowl jowl +joy joy +joyed joy +joyful joy +joyfully joy +joyous joyous +joyously joyous +joyousness joyous +joys joy +juan juan +judah judah +judge judg +judged judg +judgement judgement +judges judg +judging judg +judgment judgment +judgments judgment +judicial judici +judicious judici +judiciously judici +judith judith +judy judi +juffy juffi +jug jug +juggle juggl +juggled juggl +juggler juggler +jugglery juggleri +jugs jug +jugular jugular +juice juic +juices juic +juicy juici +juillet juillet +julia julia +julian julian +juliet juliet +julius julius +july juli +jumble jumbl +jumbled jumbl +jumbling jumbl +jump jump +jumped jump +jumping jump +jumps jump +junction junction +juncture junctur +juncus juncus +june june +jungle jungl +jungles jungl +junior junior +juniorest juniorest +juniors junior +junk junk +jupiter jupit +jura jura +juries juri +jurisprudence jurisprud +juror juror +jurors juror +jury juri +juryman juryman +jurymen jurymen +just just +juster juster +justest justest +justice justic +justifiable justifi +justification justif +justifications justif +justified justifi +justifies justifi +justify justifi +justifying justifi +justitia justitia +justly just +jute jute +juvenile juvenil +juxtaposition juxtaposit +k k +kalydor kalydor +kammerjunker kammerjunk +kampfes kampf +kamtschatka kamtschatka +kangaroo kangaroo +kapernaumov kapernaumov +kapernaumovs kapernaumov +karl karl +karros karro +kate kate +kater kater +katerina katerina +katharina katharina +katia katia +kattymaly kattymali +kauri kauri +kazan kazan +keane kean +keating keat +keeling keel +keen keen +keener keener +keenest keenest +keenly keen +keenness keen +keep keep +keeper keeper +keepers keeper +keeping keep +keeps keep +keepsake keepsak +keepsakes keepsak +keine kein +kelp kelp +ken ken +kendall kendal +kenge keng +kennel kennel +kennels kennel +kennington kennington +kensington kensington +kent kent +kentish kentish +kenwigs kenwig +kenwigses kenwigs +kepler kepler +kept kept +kerchief kerchief +kerguelen kerguelen +kernel kernel +kerr kerr +kerrig kerrig +kettle kettl +kettles kettl +key key +keyhole keyhol +keyholes keyhol +keyne keyn +keys key +khan khan +kick kick +kicked kick +kicking kick +kicks kick +kid kid +kidnapped kidnap +kidnapper kidnapp +kidnapping kidnap +kidney kidney +kilda kilda +kill kill +killed kill +killer killer +killing kill +kills kill +kiln kiln +kilns kiln +kilt kilt +kimbo kimbo +kimiri kimiri +kimpelled kimpel +kin kin +kind kind +kinder kinder +kindest kindest +kindhearted kindheart +kindle kindl +kindled kindl +kindles kindl +kindlier kindlier +kindliest kindliest +kindliness kindli +kindling kindl +kindly kind +kindness kind +kindnesses kind +kindred kindr +kinds kind +king king +kingdom kingdom +kingdoms kingdom +kingfisher kingfish +kingly king +kings king +kingston kingston +kinkajou kinkajou +kinsman kinsman +kirby kirbi +kiss kiss +kissed kiss +kisses kiss +kissing kiss +kit kit +kitchen kitchen +kitchens kitchen +kitchin kitchin +kite kite +kitten kitten +kittlitz kittlitz +kitty kitti +klopstock klopstock +knack knack +knackeries knackeri +knacks knack +knag knag +knave knave +knaves knave +knavish knavish +kneaded knead +kneading knead +knee knee +kneel kneel +kneeled kneel +kneeling kneel +kneels kneel +knees knee +knell knell +knelt knelt +knew knew +knick knick +knif knif +knife knife +knight knight +knightly knight +knights knight +knit knit +knits knit +knitted knit +knitting knit +knives knive +knob knob +knobs knob +knock knock +knocked knock +knocker knocker +knockers knocker +knocking knock +knocks knock +knopp knopp +knot knot +knots knot +knotted knot +knotty knotti +know know +knowa knowa +knowd knowd +knowed know +knowest knowest +knoweth knoweth +knowin knowin +knowing know +knowledg knowledg +knowledge knowledg +known known +knows know +knuckle knuckl +knuckleboy knuckleboy +knuckles knuckl +kobelev kobelev +kobilatnikov kobilatnikov +koch koch +koeldwethout koeldwethout +kolomensky kolomenski +kolya kolya +kong kong +konig konig +koodle koodl +kororadika kororadika +kotzebue kotzebu +kozel kozel +krestovsky krestovski +kriegsrath kriegsrath +krook krook +kryukov kryukov +kuffy kuffi +l l +la la +label label +labelled label +labillardiere labillardier +laborious labori +laboriously labori +labour labour +laboured labour +labourer labour +labourers labour +labouring labour +labourious labouri +labours labour +laburnum laburnum +labyrinth labyrinth +labyrinths labyrinth +lace lace +laced lace +lacerate lacer +lacerta lacerta +laches lach +lachrymatories lachrymatori +lachrymose lachrymos +lacing lace +lack lack +lackadaisical lackadais +lacked lack +lacking lack +lacks lack +laconic lacon +lacquered lacquer +lad lad +ladder ladder +ladders ladder +lade lade +laden laden +laderas ladera +ladies ladi +ladle ladl +lads lad +lady ladi +ladyhood ladyhood +ladylike ladylik +ladyship ladyship +lag lag +laggard laggard +lagged lag +lagging lag +lagoa lagoa +lagoon lagoon +lagoons lagoon +lagostomus lagostomus +lags lag +laguna laguna +laid laid +lain lain +lair lair +laissez laissez +laity laiti +lajdak lajdak +lake lake +lakes lake +lalegraicavalca lalegraicavalca +lall lall +lalla lalla +lama lama +lamarck lamarck +lamb lamb +lambert lambert +lambeth lambeth +lambs lamb +lame lame +lamed lame +lamellicorn lamellicorn +lameness lame +lament lament +lamentable lament +lamentably lament +lamentation lament +lamentations lament +lamented lament +lamenting lament +laments lament +laminae lamina +lamp lamp +lamplight lamplight +lamplighter lamplight +lamps lamp +lampyridae lampyrida +lampyris lampyri +lancashire lancashir +lancaster lancast +lance lanc +lancerated lancer +land land +landed land +landing land +landings land +landlady landladi +landlord landlord +landmark landmark +landmarks landmark +landowner landown +landowners landown +lands land +landscape landscap +landseer landseer +landsman landsman +lane lane +lanes lane +langsdorff langsdorff +language languag +languages languag +languid languid +languidly languid +languish languish +languished languish +languishing languish +languor languor +langwedge langwedg +lank lank +lanky lanki +lantern lantern +lanterns lantern +lap lap +lapel lapel +lappel lappel +laps lap +lapse laps +lapsed laps +lapses laps +lapsing laps +lar lar +larcenerer larcener +larch larch +larg larg +large larg +largely larg +largeness larg +larger larger +largest largest +lark lark +larking lark +larks lark +larming larm +larry larri +larvae larva +las las +lash lash +lashed lash +lashes lash +lashing lash +lass lass +lassie lassi +lassitude lassitud +lassoit lassoit +lassonthwaite lassonthwait +lassonthwayte lassonthwayt +last last +lasted last +lasting last +lastly last +lasts last +lat lat +latch latch +latched latch +late late +latel latel +lately late +lateness late +latent latent +later later +lateral later +laterally later +latest latest +lath lath +lathered lather +latin latin +latinity latin +latitude latitud +latitudes latitud +latreille latreill +latro latro +latte latt +latter latter +latterly latter +latther latther +latthers latther +lattice lattic +latticed lattic +lattle lattl +laud laud +laudable laudabl +laudamus laudamus +laudation laudat +laudatory laudatori +lauded laud +laugh laugh +laughable laughabl +laughed laugh +laughing laugh +laughingly laugh +laughs laugh +laughter laughter +launch launch +launched launch +launching launch +laundry laundri +laura laura +laurance lauranc +laurel laurel +laurels laurel +laurence laurenc +lauzun lauzun +lav lav +lava lava +laval laval +lavas lava +lavender lavend +lavish lavish +lavished lavish +lavishly lavish +law law +lawful law +lawgiver lawgiv +lawk lawk +lawn lawn +lawns lawn +lawrence lawrenc +laws law +lawson lawson +lawstationers lawstation +lawsuit lawsuit +lawver lawver +lawyer lawyer +lawyers lawyer +lax lax +laxity laxiti +lay lay +layer layer +layers layer +layin layin +laying lay +laylec laylec +lays lay +layton layton +laz laz +lazarus lazarus +lazily lazili +laziness lazi +lazo lazo +lazoed lazo +lazos lazo +lazy lazi +lazzeretto lazzeretto +le le +lead lead +leaden leaden +leadenhall leadenhal +leader leader +leaders leader +leadership leadership +leading lead +leads lead +leaf leaf +leafed leaf +leafless leafless +leafy leafi +league leagu +leagued leagu +leagues leagu +leaked leak +lean lean +leaned lean +leaning lean +leanness lean +leans lean +leant leant +leap leap +leaped leap +leaper leaper +leaping leap +leapings leap +leapt leapt +lear lear +learn learn +learned learn +learners learner +learning learn +learns learn +learnt learnt +lease leas +leases leas +least least +leastways leastway +leather leather +leathern leathern +leave leav +leaves leav +leaving leav +lebanon lebanon +leben leben +lebeziatnikov lebeziatnikov +lecherousness lecher +lecture lectur +lectured lectur +lecturer lectur +lectures lectur +lecturing lectur +led led +ledge ledg +ledger ledger +ledgers ledger +ledges ledg +ledrook ledrook +leech leech +leek leek +leer leer +leered leer +leering leer +leetle leetl +leeuwin leeuwin +leeward leeward +left left +leg leg +legacy legaci +legal legal +legality legal +legally legal +legatee legate +legatees legate +legend legend +legendary legendari +legends legend +legged leg +leggings leg +legh legh +legibility legibl +legible legibl +legibly legibl +legion legion +legislation legisl +legislative legisl +legislator legisl +legislators legisl +legislature legislatur +legitimacy legitimaci +legitimate legitim +legs leg +leguminosae leguminosa +leicester leicest +leicestershire leicestershir +leighton leighton +leisure leisur +leisurely leisur +lemen lemen +lemon lemon +lemonade lemonad +lemons lemon +lemuel lemuel +lemuy lemuy +len len +lend lend +lender lender +lenders lender +lending lend +lends lend +length length +lengthen lengthen +lengthened lengthen +lengths length +lengthy lengthi +lenient lenient +leniently lenient +lenning len +lenou lenou +lens len +lent lent +lentils lentil +lenville lenvill +leone leon +leoneros leonero +leoville leovill +lepidoptera lepidoptera +lepus lepus +les les +leslie lesli +less less +lessen lessen +lessened lessen +lessening lessen +lesser lesser +lesson lesson +lessons lesson +lest lest +let let +lethargic letharg +lethargy lethargi +lethe leth +lets let +lett lett +letter letter +letters letter +letting let +lettres lettr +lettuce lettuc +lettuces lettuc +leurs leur +levanted levant +leve leve +levees leve +level level +levelle levell +levelled level +levelling level +levels level +levers lever +levities leviti +levity leviti +lewes lew +lewis lewi +li li +liabilities liabil +liability liabil +liable liabl +liana liana +liar liar +libation libat +libel libel +liberal liber +liberalism liber +liberality liber +liberally liber +liberals liber +liberate liber +liberated liber +liberates liber +liberties liberti +libertine libertin +libertines libertin +liberty liberti +librarian librarian +libraries librari +library librari +lice lice +licence licenc +licences licenc +license licens +licensed licens +licenses licens +licentious licenti +licentiousness licenti +lichen lichen +lichens lichen +lichtenstein lichtenstein +licked lick +licking lick +lid lid +lida lida +lids lid +lie lie +liebig liebig +lied lie +lies lie +liesk liesk +lieu lieu +lieut lieut +lieutenancies lieuten +lieutenant lieuten +lieutenants lieuten +life life +lifeless lifeless +lifetime lifetim +lift lift +lifted lift +lifting lift +lifts lift +ligament ligament +ligaments ligament +ligh ligh +light light +lighted light +lighten lighten +lightened lighten +lightening lighten +lightens lighten +lighter lighter +lightest lightest +lightheaded lighthead +lighthearted lightheart +lighthouse lighthous +lighthouses lighthous +lighting light +lightly light +lightness light +lightning lightn +lights light +lightsome lightsom +lignite lignit +lignum lignum +lii lii +liii liii +lik lik +like like +liked like +likelier likeli +likelihood likelihood +likely like +likened liken +likeness like +likenesses like +likes like +likewise likewis +liking like +likings like +lilac lilac +lilaceous lilac +lilacs lilac +liliaceous liliac +lilies lili +lilliput lilliput +lillyvick lillyvick +lillyvicks lillyvick +lily lili +lima lima +limache limach +limb limb +limbs limb +lime lime +limes lime +limestone limeston +limit limit +limited limit +limiting limit +limits limit +limnaea limnaea +limp limp +limped limp +limpet limpet +limpid limpid +limping limp +lin lin +lincoln lincoln +lincolnshire lincolnshir +line line +linea linea +lineage lineag +lineament lineament +lineaments lineament +linear linear +lined line +linen linen +linendraper linendrap +lines line +linger linger +lingered linger +lingering linger +lingerings linger +lingers linger +linguist linguist +lining line +linings line +link link +linked link +linking link +linkinwater linkinwat +links link +linn linn +linnaean linnaean +linnean linnean +linnets linnet +lintels lintel +lion lion +lioness lioness +lions lion +lip lip +lippevechsel lippevechsel +lipping lip +lips lip +liquid liquid +liquidating liquid +liquor liquor +liquorish liquorish +liquors liquor +lisbon lisbon +lisp lisp +list list +listed list +listen listen +listened listen +listener listen +listeners listen +listening listen +listenings listen +listens listen +listless listless +listlessly listless +listlessness listless +lists list +lit lit +litany litani +literal liter +literally liter +literary literari +literature literatur +lithe lith +lithographic lithograph +litigation litig +litigious litigi +litter litter +littered litter +littering litter +littl littl +little littl +littleness littl +littlenesses littl +littlest littlest +littoral littor +liv liv +live live +lived live +livelier liveli +liveliest liveliest +livelihood livelihood +liveliness liveli +livelong livelong +lively live +liver liver +liveried liveri +liveries liveri +liverpool liverpool +livers liver +livery liveri +lives live +livest livest +liveth liveth +livid livid +living live +livingstone livingston +lix lix +liz liz +lizard lizard +lizards lizard +lizaveta lizaveta +lizzie lizzi +lizzy lizzi +ll ll +llama llama +llandaff llandaff +llanos llano +lloyd lloyd +llth llth +lmmediately lmmediat +lo lo +load load +loaded load +loading load +loads load +loaf loaf +loam loam +loan loan +loans loan +loath loath +loathe loath +loathed loath +loathing loath +loathsome loathsom +loathsomeness loathsom +loaves loav +lobbies lobbi +lobby lobbi +lobster lobster +lobsters lobster +local local +locality local +locations locat +lochness loch +lock lock +locked lock +locket locket +locking lock +lockouts lockout +locks lock +locksmiths locksmith +lockyer lockyer +locock locock +lococks locock +locomotion locomot +locomotive locomot +locomotives locomot +locust locust +locusts locust +lod lod +lodge lodg +lodged lodg +lodger lodger +lodgers lodger +lodges lodg +lodging lodg +lodgings lodg +loft loft +loftiest loftiest +loftily loftili +loftiness lofti +lofty lofti +log log +loggerheaded loggerhead +loggerheads loggerhead +logic logic +logical logic +logically logic +logs log +loight loight +loike loik +loikewise loikewis +loins loin +loiter loiter +loitered loiter +loiterer loiter +loiterers loiter +loitering loiter +loix loix +loll loll +lolling loll +lombard lombard +lombardic lombard +lon lon +lond lond +london london +lone lone +lonelier loneli +loneliness loneli +lonely lone +lonesome lonesom +long long +longbarns longbarn +longed long +longer longer +longest longest +longevity longev +longing long +longings long +longitude longitud +longitudinal longitudin +longitudinally longitudin +longs long +longwood longwood +loo loo +looder looder +loodgin loodgin +loodle loodl +look look +looked look +lookee looke +looker looker +lookers looker +looking look +looks look +lookye looky +loom loom +loomed loom +looming loom +looms loom +loonching loonch +loone loon +loop loop +loopholes loophol +loose loos +loosed loos +loosely loos +loosen loosen +loosened loosen +looseness loos +loosening loosen +looser looser +loosing loos +loov loov +lop lop +lopez lopez +lopezes lopez +lopezites lopezit +lopped lop +loppings lop +loquacious loquaci +lor lor +lord lord +lordlings lordl +lordly lord +lords lord +lordship lordship +lordships lordship +lorenzo lorenzo +los los +lose lose +loser loser +losers loser +loses lose +losing lose +loss loss +losses loss +lost lost +lot lot +lothbury lothburi +lots lot +lottery lotteri +loud loud +louder louder +loudest loudest +loudly loud +loudness loud +louis loui +louisa louisa +lounge loung +lounged loung +lounger lounger +loungers lounger +lounges loung +lounging loung +lous lous +louse lous +louvain louvain +lovable lovabl +love love +loveable loveabl +loved love +lovelier loveli +loveliest loveliest +loveliness loveli +lovely love +lover lover +lovers lover +loves love +loving love +lovingly love +lovingness loving +low low +lower lower +lowered lower +lowering lower +lowers lower +lowest lowest +lowland lowland +lowliest lowliest +lowliness lowli +lowly lowli +lowness low +loyal loyal +loyalty loyalti +lozenge lozeng +lozenges lozeng +lt lt +lubricates lubric +lucanee lucane +lucia lucia +luciano luciano +lucid lucid +lucidly lucid +lucifer lucif +lucifers lucif +luck luck +luckiest luckiest +luckily luckili +luckless luckless +lucky lucki +lucrative lucrat +lucre lucr +lucy luci +lud lud +ludgate ludgat +ludicrous ludicr +ludicrously ludicr +ludship ludship +ludwigovna ludwigovna +luffy luffi +luggage luggag +lugged lug +lui lui +luis lui +luise luis +lukewarm lukewarm +lukin lukin +lull lull +lullaby lullabi +lulled lull +lulling lull +lulls lull +lumb lumb +lumbagers lumbag +lumber lumber +lumbering lumber +lumbey lumbey +luminary luminari +luminosus luminosus +luminous lumin +lumley lumley +lump lump +lumpkin lumpkin +lumps lump +lumpy lumpi +lunacy lunaci +lunatic lunat +lunch lunch +luncheon luncheon +lunches lunch +lund lund +lunge lung +lungs lung +lunnun lunnun +lupton lupton +lurch lurch +lurched lurch +lure lure +lured lure +lures lure +lurid lurid +luring lure +lurk lurk +lurked lurk +lurking lurk +luscious luscious +lustfahrt lustfahrt +lustier lustier +lustily lustili +lustre lustr +lustreless lustreless +lustrous lustrous +lusts lust +lusty lusti +lute lute +luxan luxan +luxuriance luxuri +luxuriant luxuri +luxuriantly luxuri +luxuriate luxuri +luxuriating luxuri +luxuries luxuri +luxurious luxuri +luxuriously luxuri +luxury luxuri +luzhin luzhin +lv lv +lvi lvi +lvii lvii +lviii lviii +lx lx +lxi lxi +lxii lxii +lxiii lxiii +lxiv lxiv +lxv lxv +lxvi lxvi +lxvii lxvii +ly ly +lycosa lycosa +lycurgus lycurgus +lyell lyell +lying lie +lymington lymington +lymph lymph +lynne lynn +lynx lynx +lyra lyra +lyre lyre +lyres lyre +m m +ma ma +macadam macadam +macae maca +macbeth macbeth +maccoort maccoort +maccoorts maccoort +macculloch macculloch +mace mace +maces mace +macfuzlem macfuzlem +macgregor macgregor +machina machina +machine machin +machinery machineri +mack mack +mackenzie mackenzi +maclaren maclaren +macpherson macpherson +macphersons macpherson +macquarie macquari +macquarrie macquarri +macrauchenia macrauchenia +macrocystis macrocysti +mactrae mactra +maculata maculata +mad mad +madagascar madagascar +madam madam +madame madam +madcaps madcap +madchen madchen +madden madden +maddened madden +maddening madden +madder madder +maddest maddest +made made +madeira madeira +madeline madelin +mademoiselle mademoisell +madhouse madhous +madly mad +madman madman +madmen madmen +madness mad +madonna madonna +madras madra +madre madr +madrid madrid +madrina madrina +madrinas madrina +madwoman madwoman +mag mag +magalonyx magalonyx +magazine magazin +magazines magazin +magdalen magdalen +magellan magellan +magellanica magellanica +magellanicus magellanicus +maggot maggot +maggots maggot +magic magic +magical magic +magically magic +magician magician +magistrate magistr +magistrates magistr +magnanimity magnanim +magnanimous magnanim +magnanimously magnanim +magnate magnat +magnates magnat +magnesium magnesium +magnetic magnet +magnetized magnet +magnificence magnific +magnificent magnific +magnificently magnific +magnified magnifi +magnifies magnifi +magnify magnifi +magnifying magnifi +magnirostris magnirostri +magnitude magnitud +magnum magnum +magog magog +magpie magpi +magpies magpi +mahdoo mahdoo +mahlos mahlo +mahogany mahogani +mahomedan mahomedan +mahomet mahomet +mahony mahoni +mai mai +maid maid +maiden maiden +maidenly maiden +maidens maiden +maidish maidish +maids maid +maidservants maidserv +mail mail +maim maim +maimed maim +main main +mainland mainland +mainly main +mainspring mainspr +mainstay mainstay +maintain maintain +maintained maintain +maintaining maintain +maintenance mainten +maire mair +maitre maitr +majestic majest +majestically majest +majesty majesti +major major +majorities major +majority major +mak mak +make make +maker maker +makers maker +makes make +making make +maktng maktng +mal mal +malacca malacca +malady maladi +malaria malaria +malay malay +malaya malaya +malays malay +malcolmson malcolmson +malcontents malcont +maldiva maldiva +maldonado maldonado +male male +malediction maledict +maledictions maledict +malefactors malefactor +males male +malevolent malevol +malgre malgr +malice malic +malicious malici +maliciously malici +malignance malign +malignant malign +malignantly malign +maligned malign +malignity malign +mall mall +malleable malleabl +mallowford mallowford +malouines malouin +malt malt +malta malta +malte malt +maltreatment maltreat +malty malti +mama mama +mamas mama +mameluke mameluk +mamma mamma +mammalia mammalia +mammals mammal +mammiferous mammifer +mammifers mammif +mammillated mammil +mammon mammon +mammy mammi +man man +manage manag +manageable manag +managed manag +management manag +manager manag +manageress manageress +managers manag +manages manag +managing manag +manatee manate +manchester manchest +mandate mandat +mandetiba mandetiba +mandibl mandibl +mandible mandibl +mandioca mandioca +mane mane +manes mane +manful man +manfully man +manganese manganes +manger manger +mangering manger +mangle mangl +mangles mangl +mangling mangl +mango mango +mangostin mangostin +mangot mangot +mangroves mangrov +mangy mangi +manhood manhood +mania mania +maniac maniac +maniacs maniac +manie mani +manifest manifest +manifestation manifest +manifestations manifest +manifested manifest +manifesting manifest +manifestly manifest +manifests manifest +manifold manifold +manipulated manipul +manipulation manipul +mankind mankind +manliness manli +manly man +manne mann +manned man +manner manner +mannered manner +manners manner +mannish mannish +manoeuvre manoeuvr +manoeuvred manoeuvr +manoeuvres manoeuvr +manoeuvring manoeuvr +manor manor +mansion mansion +mansions mansion +manslaughtering manslaught +mansos manso +mantalini mantalini +mantel mantel +mantelpiece mantelpiec +mantelshelf mantelshelf +mantie manti +mantle mantl +mantled mantl +mantles mantl +mantling mantl +manual manual +manuals manual +manuel manuel +manufactories manufactori +manufactory manufactori +manufacture manufactur +manufactured manufactur +manufacturers manufactur +manufacturing manufactur +manure manur +manured manur +manuring manur +manuscript manuscript +manuscripts manuscript +many mani +map map +mapped map +maps map +mar mar +marbl marbl +marble marbl +marbles marbl +march march +marchantiae marchantia +marched march +marches march +marching march +mare mare +mares mare +marfa marfa +margate margat +marge marg +margin margin +marginal margin +margins margin +mari mari +maria maria +mariano mariano +marica marica +marie mari +marine marin +mariners marin +marines marin +marital marit +maritime maritim +mark mark +marked mark +marker marker +market market +marketing market +marketplace marketplac +markets market +marking mark +marks mark +marl marl +marlborough marlborough +marly mar +marmalade marmalad +marmeladov marmeladov +marmeladovs marmeladov +marquess marquess +marquis marqui +marquises marquis +marred mar +marriage marriag +marriages marriag +married marri +marries marri +marring mar +marrow marrow +marrows marrow +marry marri +marrying marri +mars mar +marsden marsden +marseilles marseill +marsh marsh +marshal marshal +marshalled marshal +marshes marsh +marshy marshi +marstone marston +marstones marston +marsupial marsupi +mart mart +martens marten +martha martha +martial martial +martin martin +martindale martindal +martindales martindal +martins martin +martlets martlet +martyr martyr +martyrdom martyrdom +marvel marvel +marvelled marvel +marvelling marvel +marvellous marvel +marvellously marvel +marvels marvel +mary mari +marylebone marylebon +marys mari +mascariensis mascariensi +masculine masculin +mashes mash +mask mask +masonry masonri +masquerading masquerad +mass mass +massacre massacr +massacred massacr +massacres massacr +masse mass +masses mass +massive massiv +massively massiv +mast mast +mastadon mastadon +masted mast +master master +mastered master +masterful master +mastering master +masterly master +masterpieces masterpiec +masters master +mastery masteri +masthead masthead +mastiff mastiff +mastodon mastodon +mastodons mastodon +masts mast +mat mat +mata mata +mataco mataco +matador matador +matavai matavai +match match +matched match +matches match +matching match +mate mate +material materi +materially materi +materials materi +maternal matern +mates mate +mathematical mathemat +mathematically mathemat +mathematics mathemat +matilda matilda +matins matin +matlock matlock +matricide matricid +matrimonial matrimoni +matrimonially matrimoni +matrimony matrimoni +matrix matrix +matron matron +matronly matron +matrons matron +mats mat +matted mat +matter matter +mattered matter +matters matter +matther matther +matthew matthew +matthews matthew +matting mat +mattress mattress +mattresses mattress +mature matur +matured matur +maturely matur +maturer matur +maturity matur +matutina matutina +matvey matvey +maun maun +maunder maunder +maurice mauric +mauritius mauritius +maurua maurua +mausoleum mausoleum +mausoleums mausoleum +mauvais mauvai +mawkish mawkish +maxillae maxilla +maxim maxim +may may +maybe mayb +maydickle maydickl +mayfair mayfair +mayhap mayhap +mayn mayn +mayo mayo +mayor mayor +maypu maypu +mayst mayst +maze maze +mazeppa mazeppa +mazes maze +mazurka mazurka +mazy mazi +me me +meadow meadow +meadows meadow +meads mead +meagre meagr +meal meal +meals meal +mean mean +meandering meander +meanest meanest +meaning mean +meaningless meaningless +meanings mean +meanly mean +meanness mean +means mean +meant meant +meantime meantim +meanwhile meanwhil +measles measl +measther measther +measthers measther +measure measur +measured measur +measurement measur +measurements measur +measurer measur +measures measur +measuring measur +meat meat +meats meat +mechanic mechan +mechanical mechan +mechanically mechan +mechanics mechan +mechanism mechan +mecum mecum +medal medal +medallions medallion +meddle meddl +meddled meddl +meddlers meddler +meddlesome meddlesom +meddling meddl +mediaeval mediaev +mediate mediat +mediation mediat +mediator mediat +medical medic +medicinal medicin +medicine medicin +medicines medicin +mediocrity mediocr +meditate medit +meditated medit +meditates medit +meditating medit +meditation medit +meditations medit +meditative medit +meditatively medit +mediterranean mediterranean +medium medium +medley medley +medusae medusa +meek meek +meekest meekest +meekly meek +meekness meek +meet meet +meeting meet +meetings meet +meets meet +megalonyx megalonyx +megalosaurus megalosaurus +megapodius megapodius +megatherium megatherium +megatheroid megatheroid +mehr mehr +melancholy melancholi +melanops melanop +melanotis melanoti +melasoma melasoma +melchisedech melchisedech +melindres melindr +mell mell +mellifluousness melliflu +mellow mellow +mellowed mellow +mellows mellow +melodious melodi +melodiously melodi +melodrama melodrama +melodramatic melodramat +melody melodi +melolonthidae melolonthida +melons melon +melt melt +melted melt +melteth melteth +melting melt +melts melt +melvilleson melvilleson +mem mem +member member +members member +membrane membran +membranous membran +mememto mememto +memoir memoir +memoirs memoir +memorable memor +memoranda memoranda +memorandum memorandum +memorial memori +memorials memori +memories memori +memory memori +men men +menace menac +menacing menac +menage menag +menchicoff menchicoff +mend mend +mended mend +mending mend +mendoza mendoza +mendozinos mendozino +mends mend +menfion menfion +menfioning menfion +mental mental +mentally mental +mention mention +mentioned mention +mentioning mention +mentions mention +mentor mentor +mercantile mercantil +mercedes merced +mercenary mercenari +mercers mercer +merchandise merchandis +merchant merchant +merchants merchant +mercie merci +mercies merci +merciful merci +mercifully merci +merciless merciless +mercilessly merciless +mercuries mercuri +mercury mercuri +mercy merci +mere mere +merely mere +merest merest +merged merg +merging merg +merid merid +meridian meridian +merit merit +merited merit +meritorious meritori +meritoriously meritori +merits merit +mermaid mermaid +mero mero +merrier merrier +merriest merriest +merrily merrili +merriment merriment +merry merri +merveille merveill +mervyn mervyn +mesalliance mesalli +mesh mesh +meshes mesh +mesmerism mesmer +mess mess +message messag +messages messag +messenger messeng +messengers messeng +messes mess +messiah messiah +messrs messr +met met +metal metal +metallic metal +metalliferous metallifer +metals metal +metamorphic metamorph +metamorphosed metamorphos +metaphorically metaphor +metaphysical metaphys +metaphysics metaphys +meteor meteor +meteorological meteorolog +meteors meteor +method method +methodical method +methodically method +methodist methodist +methods method +methoozellers methoozel +methuselah methuselah +metropolis metropoli +metropolitan metropolitan +mettle mettl +mew mew +mewlinn mewlinn +mewlinnwillinwodd mewlinnwillinwodd +mews mew +mexican mexican +mexico mexico +mezzotinto mezzotinto +miasma miasma +mica mica +micaceous micac +mice mice +michael michael +michaelmas michaelma +michell michel +mickle mickl +microbes microb +microscope microscop +microscopic microscop +microscopical microscop +mid mid +midday midday +middl middl +middle middl +middlesex middlesex +middleton middleton +middling middl +midnight midnight +midshipmen midshipmen +midst midst +midsummer midsumm +midway midway +midwives midwiv +mien mien +miers mier +might might +mightier mightier +mightily mightili +mightn mightn +mighty mighti +mignonette mignonett +migrate migrat +migrated migrat +migrates migrat +migrating migrat +migration migrat +migrations migrat +migratorius migratorius +migratory migratori +mihail mihail +mihailovitch mihailovitch +mihailovsky mihailovski +mikolka mikolka +milch milch +mild mild +milder milder +mildest mildest +mildewed mildew +mildly mild +mildmay mildmay +mildness mild +mile mile +miles mile +milestone mileston +milestones mileston +military militari +militia militia +milk milk +milked milk +milking milk +milkmaid milkmaid +milkman milkman +milkpot milkpot +milksop milksop +milky milki +mill mill +millennium millennium +millenniums millennium +millepois millepoi +millepora millepora +miller miller +milleypoise milleypois +milliner millin +milliners millin +millinery millineri +milling mill +million million +millionaire millionair +millions million +millionth millionth +mills mill +millstone millston +milton milton +mimicking mimick +mimicry mimicri +mimics mimic +mimosa mimosa +mimosae mimosa +mimosas mimosa +mimus mimus +minaret minaret +minas mina +mince minc +minced minc +mincefenille mincefenill +mincing minc +mincingly minc +mind mind +minded mind +mindedly mind +mindedness minded +mindful mind +minding mind +minds mind +mine mine +miner miner +mineral miner +mineralogical mineralog +miners miner +minerva minerva +mines mine +mingle mingl +mingled mingl +mingles mingl +mingling mingl +miniature miniatur +miniatures miniatur +minimum minimum +mining mine +minions minion +minister minist +ministered minist +ministerial ministeri +ministerialist ministerialist +ministers minist +ministership ministership +ministration ministr +ministrations ministr +ministress ministress +ministries ministri +ministry ministri +minnit minnit +minor minor +minorities minor +minority minor +minster minster +minstrel minstrel +mint mint +minute minut +minutely minut +minuteness minut +minutes minut +minutest minutest +minutus minutus +minx minx +miracle miracl +miraculous miracul +mirage mirag +miranda miranda +mire mire +mirror mirror +mirrored mirror +mirrors mirror +mirth mirth +mirthful mirth +mirthfulness mirth +miry miri +misanthrope misanthrop +misanthropical misanthrop +misapprehend misapprehend +misapprehended misapprehend +misbehave misbehav +misbehaved misbehav +misbehaving misbehav +misbestowed misbestow +miscalculated miscalcul +miscalculation miscalcul +miscalled miscal +miscarried miscarri +miscellaneous miscellan +mischance mischanc +mischances mischanc +mischeevious mischeevi +mischief mischief +mischievous mischiev +misconception misconcept +misconduct misconduct +misconstruction misconstruct +misconstructions misconstruct +misconstrued misconstru +misconstruing misconstru +miscreant miscreant +misdeed misde +misdeeds misde +misdemeanor misdemeanor +misdemeanour misdemeanour +misdemeanours misdemeanour +misdirected misdirect +misdirecting misdirect +misdirections misdirect +miser miser +miserable miser +miserably miser +misericordia misericordia +miseries miseri +miserly miser +misers miser +misery miseri +misfortune misfortun +misfortunes misfortun +misgave misgav +misgiving misgiv +misgivings misgiv +mishap mishap +misinformed misinform +misinterpreted misinterpret +misjudged misjudg +misjudges misjudg +mislaid mislaid +mislead mislead +misled misl +mismanaged mismanag +mismanagement mismanag +misplaced misplac +misrepresent misrepres +misrepresentations misrepresent +misrepresenting misrepres +miss miss +missed miss +misses miss +missile missil +missing miss +mission mission +missionaries missionari +missionary missionari +missiones mission +missions mission +missis missi +missive missiv +misspent misspent +missus missus +missy missi +mist mist +mistake mistak +mistaken mistaken +mistakenly mistaken +mistakes mistak +mistaking mistak +miste mist +mister mister +misther misther +mistily mistili +mistiness misti +mistoo mistoo +mistook mistook +mistress mistress +mistresses mistress +mistrust mistrust +mistrusted mistrust +mistrustful mistrust +mistrustfully mistrust +mistrusting mistrust +mistrusts mistrust +mists mist +misty misti +misunderstand misunderstand +misunderstanding misunderstand +misunderstood misunderstood +misused misus +misuses misus +mitchell mitchel +mite mite +mites mite +mitigation mitig +mitka mitka +mitrofanievsky mitrofanievski +mitten mitten +mix mix +mixed mix +mixer mixer +mixes mix +mixing mix +mixtur mixtur +mixture mixtur +mizzle mizzl +mlud mlud +mm mm +mmd mmd +mo mo +moan moan +moaned moan +moaning moan +moanings moan +moans moan +moat moat +mob mob +mobbed mob +mobbs mobb +mobile mobil +mock mock +mocked mock +mockeries mockeri +mockery mockeri +mocking mock +mockingly mock +mode mode +model model +modelled model +modelling model +models model +moderate moder +moderated moder +moderately moder +moderation moder +modern modern +modes mode +modest modest +modestly modest +modesty modesti +modifications modif +modified modifi +modify modifi +mogley mogley +mogul mogul +mohair mohair +moi moi +moiler moiler +moind moind +moins moin +moist moist +moisten moisten +moistened moisten +moistening moisten +moisture moistur +molar molar +molasses molass +moldavia moldavia +mole mole +molest molest +molestation molest +molested molest +molesting molest +moliere molier +molina molina +mollified mollifi +mollify mollifi +mollifying mollifi +mollusca mollusca +molluscous mollusc +molluscs mollusc +molothrus molothrus +molten molten +momen momen +moment moment +momentarily momentarili +momentary momentari +momentous moment +moments moment +momentum momentum +mon mon +monarch monarch +monarchs monarch +monastery monasteri +monats monat +monceaux monceaux +mond mond +monday monday +mondays monday +monde mond +monetary monetari +money money +moneyed money +moneys money +monge mong +mongering monger +mongrel mongrel +mongrels mongrel +mongrober mongrob +monied moni +monitions monit +monk monk +monkey monkey +monkeyish monkeyish +monkeys monkey +monks monk +monneyment monney +monoceros monocero +monocotyledonous monocotyledon +monodonta monodonta +monogram monogram +monologues monologu +monomania monomania +monomaniac monomaniac +monomaniacs monomaniac +monopolising monopolis +monopolist monopolist +monopolize monopol +monopoly monopoli +monosyllabic monosyllab +monosyllable monosyl +monosyllables monosyl +monotonous monoton +monotonously monoton +monotony monotoni +monsieur monsieur +monsoon monsoon +monster monster +monsters monster +monsther monsther +monstrous monstrous +monstrously monstrous +mont mont +montagne montagn +monte mont +monter monter +montes mont +month month +monthly month +months month +monument monument +monumental monument +monuments monument +mood mood +moodily moodili +moodiness moodi +moodle moodl +moods mood +moody moodi +moon moon +mooney mooney +mooning moon +moonlight moonlight +moonlighted moonlight +moons moon +moonshine moonshin +moonths moonth +moor moor +moored moor +moorings moor +moorish moorish +moorland moorland +moors moor +moot moot +mooted moot +mooth mooth +moothers moother +mope mope +moped mope +moping mope +mor mor +moraine morain +moral moral +moralise moralis +moralised moralis +moralising moralis +moralisings moralis +morality moral +moralizes moral +moralizing moral +morally moral +morals moral +morass morass +morbid morbid +morbidly morbid +morbury morburi +more more +moreover moreov +moresby moresbi +moreton moreton +morgan morgan +morgenfruh morgenfruh +morleena morleena +morn morn +morning morn +mornings morn +mornmg mornmg +morocco morocco +morose moros +morosely moros +moroseness moros +morpheus morpheus +morrow morrow +morsel morsel +morsels morsel +mortal mortal +mortality mortal +mortally mortal +mortals mortal +mortar mortar +mortgage mortgag +mortgages mortgag +mortgaging mortgag +mortification mortif +mortified mortifi +mortify mortifi +mortifying mortifi +mortimer mortim +morton morton +mos mos +moscow moscow +mosquitoes mosquito +moss moss +mosses moss +mossy mossi +most most +mostly most +moth moth +mother mother +motherless motherless +motherly mother +mothers mother +moths moth +motion motion +motioned motion +motioning motion +motionles motionl +motionless motionless +motions motion +motive motiv +motives motiv +motley motley +mottled mottl +mottles mottl +motto motto +mouchoir mouchoir +mould mould +moulded mould +moulder moulder +mouldering moulder +moulding mould +moulds mould +mouldy mouldi +moun moun +mound mound +mounds mound +mount mount +mountain mountain +mountainous mountain +mountains mountain +mountebanks mountebank +mounted mount +mounting mount +mounts mount +mourn mourn +mourned mourn +mourner mourner +mourners mourner +mournful mourn +mournfully mourn +mournfulness mourn +mourning mourn +mourns mourn +mouse mous +moustache moustach +moustached moustach +moustaches moustach +moustachios moustachio +mouth mouth +mouthed mouth +mouthful mouth +mouthfuls mouth +mouthing mouth +mouthpiece mouthpiec +mouths mouth +mov mov +movables movabl +move move +moveable moveabl +moved move +movemen movemen +movement movement +movements movement +mover mover +moves move +moving move +mowed mow +mown mown +mozart mozart +mp mp +mps mps +mr mr +mrs mrs +ms ms +mt mt +muc muc +much much +muchisimas muchisima +mucilaginous mucilagin +mucker mucker +mud mud +muddiest muddiest +muddle muddl +muddled muddl +muddles muddl +muddocks muddock +muddy muddi +muddying muddi +mudie mudi +mudlike mudlik +muffin muffin +muffins muffin +muffle muffl +muffled muffl +muffles muffl +muffling muffl +muffy muffi +mug mug +mugeres muger +mugs mug +mulatto mulatto +mulberry mulberri +mulcted mulct +mule mule +mules mule +muleteer mulet +muleteers mulet +mulita mulita +mullins mullin +multimaculatus multimaculatus +multiplication multipl +multiplicity multipl +multiplied multipli +multiplier multipli +multiply multipli +multiplying multipli +multitude multitud +multitudes multitud +multitudinous multitudin +mum mum +mumbled mumbl +mumbling mumbl +mummery mummeri +mummy mummi +mun mun +munchausen munchausen +munches munch +munching munch +mundane mundan +mungo mungo +munich munich +municipal municip +municipalities municip +munificence munific +munificent munific +muniz muniz +muntle muntl +muntlehiney muntlehiney +murder murder +murdered murder +murderer murder +murderers murder +murderess murderess +murdering murder +murderous murder +murders murder +muriate muriat +muriates muriat +murinus murinus +murky murki +murmur murmur +murmured murmur +murmuring murmur +murmuringly murmur +murmurings murmur +murmurs murmur +murphy murphi +murray murray +murrumbidgee murrumbidge +mus mus +muscle muscl +muscles muscl +muscular muscular +muse muse +mused muse +muses muse +museum museum +musgrave musgrav +mushroom mushroom +mushrooms mushroom +music music +musical music +musician musician +musing muse +musingly muse +musk musk +musket musket +musketry musketri +muskets musket +muslin muslin +muslins muslin +musn musn +musquitoes musquito +muss muss +mussel mussel +must must +mustaches mustach +mustard mustard +muster muster +mustered muster +mustn mustn +musty musti +mute mute +mutilated mutil +mutilates mutil +mutinous mutin +mutiny mutini +mutter mutter +muttered mutter +muttering mutter +mutterings mutter +mutters mutter +mutton mutton +mutual mutual +mutually mutual +muy muy +muzzle muzzl +my my +myiobius myiobius +mylodon mylodon +myopotamus myopotamus +myriads myriad +myrmidons myrmidon +myrtle myrtl +myrtus myrtus +myself myself +mysteries mysteri +mysterieuse mysterieus +mysterious mysteri +mysteriously mysteri +mystery mysteri +mystic mystic +mystification mystif +mystified mystifi +mystify mystifi +mythische mythisch +myths myth +mytilus mytilus +n n +na na +nae nae +nag nag +nags nag +nail nail +nailed nail +nails nail +naive naiv +naively naiv +naked nake +nakedness naked +nam nam +name name +named name +nameless nameless +namely name +names name +namesake namesak +naming name +nankeen nankeen +nanus nanus +nap nap +nape nape +napkin napkin +naples napl +napoleon napoleon +napoleons napoleon +narborough narborough +narcissus narcissus +narr narr +narrated narrat +narrates narrat +narration narrat +narrative narrat +narratives narrat +narrow narrow +narrowed narrow +narrower narrow +narrowest narrowest +narrowing narrow +narrowly narrowli +narrowness narrow +narrows narrow +nasal nasal +nassa nassa +nastasya nastasya +nastiness nasti +nasturtions nasturt +nasty nasti +nat nat +nata nata +natalya natalya +nate nate +nateral nater +naterally nater +nation nation +national nation +nationality nation +nations nation +native nativ +natives nativ +natur natur +natural natur +naturalest naturalest +naturalist naturalist +naturalista naturalista +naturalists naturalist +naturalized natur +naturally natur +naturalness natur +nature natur +natured natur +naturedly natur +naturelles naturell +natures natur +naughtiest naughtiest +naughtiness naughti +naughty naughti +nausea nausea +nauseous nauseous +nautical nautic +naval naval +navarin navarin +nave nave +navedad navedad +navel navel +navies navi +navigate navig +navigating navig +navigation navig +navigator navig +navigators navig +navy navi +nay nay +nayver nayver +nd nd +ne ne +nea nea +neame neam +neaming neam +neane nean +near near +neared near +nearer nearer +nearest nearest +nearl nearl +nearly near +nearness near +nearsighted nearsight +neat neat +neatest neatest +neath neath +neatly neat +neatness neat +nebulous nebul +necesary necesari +necesidad necesidad +necessaries necessari +necessarily necessarili +necessary necessari +necessitate necessit +necessitated necessit +necessitates necessit +necessities necess +necessity necess +neck neck +neckcloth neckcloth +neckcloths neckcloth +necked neck +neckerchief neckerchief +neckett neckett +neckkerchief neckkerchief +necklace necklac +necklaced necklac +necklaces necklac +necks neck +necktie neckti +necromancer necromanc +necrophagous necrophag +nectar nectar +nectarine nectarin +nectarines nectarin +ned ned +neeburs neebur +need need +needed need +needful need +needing need +needle needl +needless needless +needlework needlework +needn needn +needs need +needy needi +neeght neeght +nefarious nefari +negative negat +neglect neglect +neglected neglect +neglectful neglect +neglecting neglect +negligemment negligem +negligence neglig +negligent neglig +negligently neglig +negotiable negoti +negotiate negoti +negotiating negoti +negotiation negoti +negotiations negoti +negress negress +negro negro +negroes negro +negus negus +neigh neigh +neighborhood neighborhood +neighbour neighbour +neighbourhood neighbourhood +neighbouring neighbour +neighbourly neighbour +neighbours neighbour +neighing neigh +neight neight +neither neither +nekrassov nekrassov +nelly nelli +nemo nemo +nemophilas nemophila +neophyte neophyt +nepean nepean +nephew nephew +nephews nephew +ner ner +nereidae nereida +nereidous nereid +nero nero +nerve nerv +nerves nerv +nerving nerv +nervous nervous +nervously nervous +nervousness nervous +nervure nervur +nervures nervur +nesbit nesbit +nest nest +nestled nestl +nestling nestl +nestlings nestl +nestor nestor +nests nest +net net +nether nether +nets net +netted net +nettle nettl +nettled nettl +nettles nettl +neuralgia neuralgia +neuroptera neuroptera +neuter neuter +neutral neutral +neva neva +neve neve +never never +nevertheless nevertheless +nevew nevew +nevsky nevski +new new +newark newark +newcastle newcastl +newcomers newcom +newer newer +newest newest +newgate newgat +newly newli +newman newman +newmarket newmarket +newness new +news news +newsmen newsmen +newspaper newspap +newspapers newspap +newton newton +next next +ney ney +neyver neyver +nezhin nezhin +ni ni +niagaras niagara +niata niata +niatas niata +nib nib +nice nice +nicely nice +niceness nice +nicer nicer +nicest nicest +nicety niceti +niche nich +nicher nicher +niches nich +nicholas nichola +nick nick +nickelby nickelbi +nickleby nicklebi +nicklebys nicklebi +nickname nicknam +nicolas nicola +nictitating nictit +nidification nidif +niebla niebla +niece niec +nieces niec +niente nient +niger niger +nigger nigger +niggering nigger +niggers nigger +nigh nigh +night night +nightcap nightcap +nightcaps nightcap +nightfall nightfal +nightingale nightingal +nightingales nightingal +nightly night +nightmare nightmar +nights night +nigra nigra +nigricans nigrican +nigricollis nigricolli +nihil nihil +nihilist nihilist +nihilists nihilist +nikiforovna nikiforovna +nikodim nikodim +nikolaevsky nikolaevski +nikolay nikolay +nil nil +nile nile +nillandoo nillandoo +nimble nimbl +nimbly nimbl +nimrod nimrod +nine nine +ninepence ninep +ninepin ninepin +nines nine +nineteen nineteen +nineteenth nineteenth +ninetta ninetta +ninety nineti +ninevite ninevit +ninnies ninni +ninth ninth +niobe niob +nipped nip +nipping nip +nips nip +nitrate nitrat +nitric nitric +nivalis nivali +nixon nixon +nixt nixt +no no +noa noa +noabody noabodi +noah noah +nobbiest nobbiest +nobility nobil +noble nobl +nobleman nobleman +noblemen noblemen +nobleness nobl +nobler nobler +noblesse nobless +noblest noblest +nobly nobli +nobodies nobodi +nobody nobodi +nobodys nobodi +nocturna nocturna +nocturnal nocturn +nod nod +nodded nod +noddies noddi +nodding nod +noddings nod +noddy noddi +nods nod +nodules nodul +noes noe +nogg nogg +noggs nogg +noice noic +noir noir +noire noir +noise nois +noised nois +noiseless noiseless +noiselessly noiseless +noises nois +noisier noisier +noisily noisili +noisome noisom +noisy noisi +nokolay nokolay +nolasko nolasko +nomadically nomad +nomads nomad +nomenclature nomenclatur +nominal nomin +nominally nomin +nominate nomin +nominated nomin +nomination nomin +nominative nomin +nominee nomine +non non +nonce nonc +nonchalance nonchal +nonchalant nonchal +none none +nonentity nonent +nonpareil nonpareil +nonsense nonsens +nonsensical nonsens +noo noo +noodle noodl +noodles noodl +nook nook +nooks nook +noon noon +noonday noonday +noose noos +nooses noos +nor nor +nore nore +normal normal +normally normal +norman norman +normously normous +noronha noronha +north north +northampton northampton +northerly norther +northern northern +northward northward +northwards northward +norval norval +norway norway +nose nose +nosed nose +nosegay nosegay +nosegays nosegay +noses nose +nostril nostril +nostrils nostril +not not +notable notabl +notably notabl +notaphus notaphus +notary notari +notched notch +notches notch +note note +notebook notebook +notebooks notebook +noted note +notes note +noteworthy noteworthi +nothin nothin +nothing noth +nothings noth +nothink nothink +nothura nothura +notic notic +notice notic +noticeable notic +noticeably notic +noticed notic +notices notic +noticing notic +notification notif +notified notifi +noting note +notion notion +notions notion +notopods notopod +notoriety notorieti +notorious notori +notoriously notori +notre notr +notwithstanding notwithstand +nou nou +nough nough +nought nought +noun noun +nourish nourish +nourished nourish +nourishment nourish +nous nous +nov nov +novae nova +novel novel +novelist novelist +novels novel +novelties novelti +novelty novelti +november novemb +novice novic +novices novic +novitiate noviti +novos novo +now now +nowadays nowaday +noways noway +nowhere nowher +nowheres nowher +nowise nowis +nowt nowt +noxious noxious +nozzle nozzl +nt nt +nucleus nucleus +nudge nudg +nudged nudg +nudges nudg +nudging nudg +nuisance nuisanc +nulla nulla +nulliporae nullipora +numb numb +numbed numb +number number +numbered number +numberless numberless +numbers number +numerical numer +numerous numer +nummularia nummularia +numskull numskul +nun nun +nunnery nunneri +nuptial nuptial +nuptials nuptial +nurse nurs +nursed nurs +nursemaid nursemaid +nursery nurseri +nurses nurs +nursing nurs +nurture nurtur +nurtured nurtur +nuss nuss +nut nut +nutcrackers nutcrack +nutmeg nutmeg +nutriment nutriment +nutritious nutriti +nuts nut +nutshell nutshel +nutshells nutshel +nymph nymph +nymphs nymph +o o +oaf oaf +oak oak +oaken oaken +oaks oak +oar oar +oars oar +oarsman oarsman +oasis oasi +oath oath +oaths oath +oats oat +oban oban +obduracy obduraci +obdurate obdur +obdurately obdur +obedience obedi +obedient obedi +obediently obedi +obedt obedt +obeisance obeis +obeisances obeis +obelisk obelisk +obelisks obelisk +obesity obes +obey obey +obeyed obey +obeyeth obeyeth +obeying obey +obeys obey +obispo obispo +obits obit +object object +objected object +objecting object +objection object +objectionable objection +objections object +objectless objectless +objects object +obleege obleeg +obleeging obleeg +obligation oblig +obligations oblig +oblige oblig +obliged oblig +obliges oblig +obliging oblig +obligingly oblig +obligingness obliging +oblique obliqu +obliterate obliter +obliterated obliter +obliterating obliter +obliteration obliter +oblivion oblivion +oblivious oblivi +oblong oblong +obscene obscen +obscenity obscen +obscure obscur +obscured obscur +obscurely obscur +obscures obscur +obscuring obscur +obscurity obscur +obsequious obsequi +obsequiousness obsequi +observa observa +observable observ +observaciones observacion +observance observ +observant observ +observation observ +observations observ +observe observ +observed observ +observer observ +observers observ +observes observ +observing observ +obsession obsess +obsolete obsolet +obstacle obstacl +obstacles obstacl +obstinacy obstinaci +obstinate obstin +obstinately obstin +obstructed obstruct +obstructing obstruct +obstruction obstruct +obtain obtain +obtainable obtain +obtained obtain +obtaining obtain +obtains obtain +obtruded obtrud +obtruding obtrud +obtrusive obtrus +obtrusively obtrus +obtuse obtus +obviating obviat +obvious obvious +obviously obvious +occasion occas +occasional occasion +occasionally occasion +occasioned occas +occasioning occas +occasions occas +occidentalis occidentali +occupancy occup +occupant occup +occupants occup +occupation occup +occupations occup +occupied occupi +occupier occupi +occupiers occupi +occupies occupi +occupy occupi +occupying occupi +occur occur +occurred occur +occurrence occurr +occurrences occurr +occurring occur +occurs occur +ocean ocean +oceanic ocean +oceans ocean +och och +octave octav +octavia octavia +octavo octavo +october octob +octopus octopus +ocular ocular +odd odd +odder odder +oddest oddest +oddities odditi +oddity odditi +oddly odd +oddness odd +odds odd +ode ode +odious odious +odiously odious +odium odium +odoriferous odorifer +odour odour +odours odour +ods od +oens oen +oesophagus oesophagus +oeuvre oeuvr +of of +off off +offal offal +offe off +offence offenc +offences offenc +offend offend +offended offend +offender offend +offending offend +offends offend +offense offens +offensive offens +offensively offens +offer offer +offered offer +offering offer +offerings offer +offers offer +office offic +officer offic +officered offic +officers offic +offices offic +official offici +officially offici +officials offici +officiates offici +officier offici +officious offici +officiously offici +offing of +offshoots offshoot +offspring offspr +oft oft +often often +oftener often +oftenest oftenest +oftentimes oftentim +ogles ogl +ogre ogr +ogreish ogreish +oh oh +ohnglaube ohnglaub +oho oho +oil oil +oiliness oili +oilskin oilskin +oily oili +ointment ointment +ojection oject +ojos ojo +old old +older older +oldest oldest +ole ole +olfactory olfactori +olfersia olfersia +olinda olinda +oliva oliva +olivasea olivasea +olive oliv +olives oliv +olivia olivia +ologies olog +olympus olympus +ombu ombu +omen omen +ominous omin +omission omiss +omissions omiss +omit omit +omitted omit +omitting omit +omnibus omnibus +omnibuses omnibus +omnipotence omnipot +omnipotent omnipot +omniscience omnisci +omniscient omnisci +omnium omnium +omnivorous omnivor +on on +once onc +one one +oneness one +onerous oner +ones one +oneself oneself +onion onion +onions onion +oniscia oniscia +only onli +ont ont +onthophagus onthophagus +onto onto +onus onus +onward onward +onwards onward +onwholesome onwholesom +ony oni +oo oo +ooman ooman +oop oop +oot oot +oother oother +ootside ootsid +ooze ooz +oozed ooz +oozes ooz +opaque opaqu +ope ope +open open +opened open +opener open +opening open +openings open +openly open +openness open +opens open +opera opera +operas opera +operate oper +operated oper +operating oper +operation oper +operations oper +operative oper +operator oper +operculum operculum +opetiorhynchi opetiorhynchi +opetiorhynchus opetiorhynchus +ophrys ophri +opiate opiat +opimon opimon +opined opin +opining opin +opinion opinion +opinionated opinion +opinionative opinion +opinions opinion +opinlon opinlon +opium opium +opossum opossum +opossums opossum +opp opp +opponent oppon +opponents oppon +opportune opportun +opportunely opportun +opportunities opportun +opportunity opportun +oppose oppos +opposed oppos +opposing oppos +opposite opposit +opposites opposit +opposition opposit +oppress oppress +oppressed oppress +oppression oppress +oppressive oppress +oppressor oppressor +opprobrious opprobri +optic optic +optical optic +opulence opul +opulent opul +opuntia opuntia +opuntias opuntia +or or +oracle oracl +oracularly oracular +oraison oraison +orange orang +orangeman orangeman +oranges orang +oration orat +orations orat +orator orat +orators orat +oratory oratori +orb orb +orbigny orbigni +orbignyi orbignyi +orbingy orbingi +orchard orchard +orchards orchard +orchestra orchestra +orchideae orchidea +orchideous orchid +orchids orchid +orchis orchi +ordained ordain +ordeal ordeal +order order +ordered order +ordering order +orderly order +orders order +ordinance ordin +ordinances ordin +ordinarily ordinarili +ordinary ordinari +ore ore +ores ore +organ organ +organic organ +organically organ +organisation organis +organise organis +organised organis +organism organ +organization organ +organizations organ +organized organ +organs organ +orgies orgi +oriels oriel +oriental orient +orifice orific +orifices orific +origin origin +original origin +originality origin +originally origin +originals origin +originate origin +originated origin +originates origin +originating origin +originatinin originatinin +orinoco orinoco +orlando orlando +orlandos orlando +ormolu ormolu +ornament ornament +ornamental ornament +ornamented ornament +ornamenting ornament +ornaments ornament +ornithologist ornithologist +ornithologists ornithologist +ornithology ornitholog +ornithorhynchus ornithorhynchus +orphan orphan +orphaned orphan +orphanhood orphanhood +orphans orphan +orpheus orpheus +orsono orsono +orth orth +orthodox orthodox +orthography orthographi +orthoptera orthoptera +oruro oruro +oryctes oryct +oryzivorus oryzivorus +oscillated oscil +oscillates oscil +oscillating oscil +oscillation oscil +oscillations oscil +osorno osorno +ossemens ossemen +osseous osseous +ostend ostend +ostensible ostens +ostensibly ostens +ostentation ostent +ostentatious ostentati +ostentatiously ostentati +ostler ostler +ostlers ostler +ostrich ostrich +ostriches ostrich +ostrov ostrov +oswald oswald +osyth osyth +otaheite otaheit +othe oth +othello othello +other other +othered other +others other +otherwise otherwis +otter otter +otters otter +otto otto +ottoman ottoman +ottomans ottoman +otus otus +ou ou +ought ought +oughtn oughtn +oughts ought +ouly ouli +oun oun +ounce ounc +ounces ounc +our our +ourangoutang ourangoutang +ours our +oursel oursel +ourselves ourselv +ouse ous +ousting oust +out out +outbidden outbidden +outbreak outbreak +outburst outburst +outcast outcast +outcasts outcast +outcries outcri +outcry outcri +outdie outdi +outdone outdon +outer outer +outerest outerest +outermost outermost +outerside outersid +outfit outfit +outgoing outgo +outgoings outgo +outgrown outgrown +outhouse outhous +outlandish outlandish +outlaw outlaw +outlaws outlaw +outlay outlay +outlet outlet +outlets outlet +outliers outlier +outline outlin +outlines outlin +outlive outliv +outlived outliv +outlook outlook +outlying out +outposts outpost +outpouring outpour +outpourings outpour +outr outr +outrage outrag +outraged outrag +outrageous outrag +outrageously outrag +outrages outrag +outraging outrag +outre outr +outrigeously outrig +outright outright +outrun outrun +outs out +outset outset +outshine outshin +outshone outshon +outside outsid +outsider outsid +outsiders outsid +outsides outsid +outskirting outskirt +outskirts outskirt +outspoken outspoken +outspread outspread +outstanding outstand +outstep outstep +outstretched outstretch +outstripping outstrip +outward outward +outwardly outward +outwards outward +outweigh outweigh +outweighed outweigh +outweighing outweigh +ova ova +oval oval +ovarium ovarium +ove ove +oven oven +ovens oven +over over +overawe overaw +overawed overaw +overbalancing overbalanc +overbearing overbear +overblown overblown +overboard overboard +overborne overborn +overburdened overburden +overcame overcam +overcast overcast +overcoat overcoat +overcome overcom +overcoming overcom +overcrowed overcrow +overdid overdid +overdo overdo +overdoes overdo +overdoing overdo +overdone overdon +overdriven overdriven +overdue overdu +overflow overflow +overflowed overflow +overflowing overflow +overflows overflow +overgrown overgrown +overhanging overhang +overhangs overhang +overhaul overhaul +overhead overhead +overhear overhear +overheard overheard +overhearing overhear +overhung overhung +overjoyed overjoy +overlaid overlaid +overleap overleap +overleaping overleap +overloaded overload +overlook overlook +overlooked overlook +overlookers overlook +overlooking overlook +overlying over +overmuch overmuch +overnight overnight +overpowered overpow +overpowering overpow +overpoweringly overpow +overpowers overpow +overrated overr +overreached overreach +overreaching overreach +overruled overrul +overrun overrun +overset overset +overshadowed overshadow +overshadowing overshadow +overshadows overshadow +oversleep oversleep +oversleeping oversleep +overslept overslept +overspreading overspread +overspreads overspread +overstated overst +overstating overst +overstep overstep +overstepped overstep +overstepping overstep +overstrained overstrain +overtake overtak +overtaken overtaken +overtakes overtak +overtaking overtak +overtask overtask +overtasked overtask +overthrew overthrew +overthrow overthrow +overthrown overthrown +overthrows overthrow +overtime overtim +overtook overtook +overtures overtur +overturn overturn +overturned overturn +overturning overturn +overturns overturn +overweening overween +overwhelm overwhelm +overwhelmed overwhelm +overwhelming overwhelm +overwhelmingly overwhelm +overwhelms overwhelm +overworked overwork +overwrought overwrought +ovules ovul +ow ow +owdacious owdaci +owe owe +owed owe +owen owen +ower ower +owes owe +owing owe +owl owl +owlish owlish +owls owl +own own +owned own +owner owner +owners owner +ownership ownership +owning own +owns own +owor owor +ox ox +oxen oxen +oxford oxford +oxidate oxid +oxides oxid +oxyurus oxyurus +oyster oyster +oysters oyster +p p +pa pa +pace pace +paced pace +paces pace +pachydermata pachydermata +pachydermatous pachydermat +pachydermous pachyderm +pacific pacif +pacified pacifi +pacify pacifi +pacifying pacifi +pacing pace +pack pack +package packag +packages packag +packed pack +packer packer +packet packet +packets packet +packhorse packhors +packing pack +packs pack +pad pad +padded pad +paddled paddl +paddles paddl +paddling paddl +paddock paddock +padlock padlock +padlocked padlock +padlocking padlock +padre padr +padres padr +pagan pagan +page page +pageant pageant +pageants pageant +pages page +pah pah +pahia pahia +paid paid +pail pail +pailfuls pail +pain pain +pained pain +painful pain +painfullest painfullest +painfully pain +pains pain +painstaking painstak +paint paint +painted paint +painter painter +painters painter +painting paint +paintings paint +paints paint +pair pair +paired pair +pairing pair +pairs pair +palace palac +palaces palac +paladin paladin +palaeologos palaeologo +palaeotherium palaeotherium +palais palai +palanquin palanquin +palatable palat +palate palat +palates palat +pale pale +paled pale +palely pale +paleness pale +paler paler +palings pale +pall pall +palladium palladium +pallas palla +palliate palliat +palliated palliat +palliation palliat +pallid pallid +palliser pallis +pallisers pallis +pallor pallor +palm palm +palmer palmer +palmerston palmerston +palmes palm +palms palm +palmy palmi +palpable palpabl +palpably palpabl +palpitate palpit +palpitated palpit +palpitating palpit +palpitation palpit +palpitations palpit +pals pal +palsy palsi +paltry paltri +paludina paludina +pampaean pampaean +pampas pampa +pampean pampean +pamper pamper +pampered pamper +pamphlet pamphlet +pamphlets pamphlet +pamplemousses pamplemouss +pan pan +panacea panacea +panama panama +pancake pancak +pancakes pancak +pandanus pandanus +pandemoniac pandemoniac +pandemonium pandemonium +pane pane +panel panel +panelled panel +panelling panel +panels panel +panes pane +pang pang +pangs pang +pani pani +panic panic +panics panic +panke pank +pannikins pannikin +panoply panopli +panorama panorama +pans pan +pansies pansi +pant pant +pantaloons pantaloon +panted pant +panther panther +panting pant +pantomime pantomim +pantomimes pantomim +pantomimist pantomimist +pantry pantri +pants pant +panza panza +papa papa +papal papal +papawa papawa +paper paper +papered paper +papering paper +papers paper +papiete papiet +papilio papilio +papillae papilla +papin papin +papist papist +paposo paposo +par par +parable parabl +parabola parabola +parade parad +paraded parad +parades parad +paradise paradis +paradox paradox +paradoxical paradox +paradoxus paradoxus +paragon paragon +paragraph paragraph +paragraphs paragraph +paraguay paraguay +parallel parallel +parallelism parallel +paralyse paralys +paralysed paralys +paralysis paralysi +paralytic paralyt +paramatta paramatta +paramount paramount +parana parana +parapet parapet +parapets parapet +parasha parasha +parasite parasit +parasites parasit +parasitic parasit +parasitical parasit +parasol parasol +parasols parasol +parcel parcel +parcels parcel +parchappe parchapp +parched parch +parchment parchment +parchments parchment +parchmentses parchments +pardiggle pardiggl +pardiggles pardiggl +pardon pardon +pardonable pardon +pardoned pardon +pardoning pardon +pardons pardon +pared pare +parenchymatous parenchymat +parent parent +parentage parentag +parental parent +parentheses parenthes +parenthesis parenthesi +parenthetically parenthet +parents parent +pariah pariah +paris pari +parish parish +parishes parish +parishioner parishion +parisian parisian +parisians parisian +park park +parker parker +parkers parker +parks park +parlance parlanc +parlay parlay +parlaying parlay +parley parley +parlez parlez +parliament parliament +parliamentary parliamentari +parliaments parliament +parlour parlour +parlours parlour +parochial parochi +parole parol +paroxysm paroxysm +paroxysms paroxysm +parried parri +parrot parrot +parrots parrot +parry parri +parsimonious parsimoni +parsimony parsimoni +parsley parsley +parson parson +parsonage parsonag +part part +partake partak +partaken partaken +partaker partak +partakes partak +partaking partak +parted part +parterre parterr +parthenon parthenon +parti parti +partial partial +partiality partial +partially partial +participate particip +participated particip +participation particip +particle particl +particles particl +particular particular +particularised particularis +particularity particular +particularly particular +particulars particular +parties parti +parting part +partings part +partisans partisan +partisanship partisanship +partition partit +partitioned partit +partitions partit +partly part +partner partner +partners partner +partnership partnership +partnerships partnership +partook partook +partridge partridg +partridges partridg +parts part +party parti +parvula parvula +parvulus parvulus +pas pas +pashenka pashenka +pass pass +passable passabl +passage passag +passages passag +passed pass +passee passe +passees passe +passenger passeng +passengers passeng +passer passer +passerby passerbi +passers passer +passes pass +passin passin +passing pass +passion passion +passionate passion +passionately passion +passionless passionless +passions passion +passive passiv +passively passiv +passport passport +passports passport +passwords password +past past +pasteboard pasteboard +pasted past +pasthry pasthri +pastime pastim +pastoral pastor +pastors pastor +pastry pastri +pastrycook pastrycook +pasturage pasturag +pasture pastur +pastures pastur +pasty pasti +pat pat +patachonica patachonica +patagones patagon +patagonia patagonia +patagonian patagonian +patagonians patagonian +patagonica patagonica +patagonicus patagonicus +patch patch +patched patch +patches patch +patchwork patchwork +patellae patella +patelliform patelliform +patent patent +paternal patern +paternally patern +path path +pathetic pathet +pathetically pathet +pathetics pathet +pathos patho +paths path +pathway pathway +pathways pathway +patience patienc +patient patient +patienter patient +patiently patient +patients patient +patriarch patriarch +patriarchal patriarch +patriarchs patriarch +patrician patrician +patrick patrick +patrimonial patrimoni +patrimony patrimoni +patriot patriot +patriotic patriot +patriotism patriot +patrolling patrol +patron patron +patronage patronag +patroness patro +patronesses patro +patronise patronis +patronised patronis +patronising patronis +patronize patron +patronized patron +patronizing patron +patronizingly patron +patrons patron +pats pat +patted pat +pattening patten +pattens patten +patter patter +pattered patter +pattering patter +pattern pattern +patternless patternless +patterns pattern +patting pat +patula patula +paucity pauciti +paul paul +pauline paulin +paunch paunch +paunchy paunchi +pauper pauper +paupers pauper +pause paus +paused paus +pauses paus +pausilippo pausilippo +pausing paus +pave pave +paved pave +pavement pavement +pavements pavement +pavilion pavilion +paving pave +paviour paviour +pavlitch pavlitch +pavlovitch pavlovitch +pavlovna pavlovna +paw paw +pawn pawn +pawnbroker pawnbrok +pawnbrokers pawnbrok +pawned pawn +paws paw +pay pay +payable payabl +paying pay +payment payment +payments payment +paypote paypot +pays pay +pe pe +pea pea +peace peac +peaceable peaceabl +peaceably peaceabl +peaceful peac +peacefully peac +peacefulness peac +peach peach +peaches peach +peachy peachi +peacock peacock +peacocks peacock +peak peak +peaked peak +peaks peak +peal peal +pealed peal +peals peal +pear pear +pearl pearl +pearls pearl +pearly pear +pears pear +peas pea +peasant peasant +peasantry peasantri +peasants peasant +pease peas +peat peat +peaty peati +pebble pebbl +pebbles pebbl +pecado pecado +peccari peccari +peccaries peccari +peccet peccet +peck peck +pecker pecker +pecking peck +pecoris pecori +pectoral pector +peculation pecul +peculiar peculiar +peculiarities peculiar +peculiarity peculiar +peculiarly peculiar +pecuniarily pecuniarili +pecuniary pecuniari +pedagogue pedagogu +pedantry pedantri +pedestal pedest +pedestrian pedestrian +pedigree pedigre +pediment pediment +pedlar pedlar +pedlars pedlar +pedro pedro +peel peel +peeled peel +peeling peel +peep peep +peeped peep +peeping peep +peeps peep +peepy peepi +peer peer +peerage peerag +peerages peerag +peered peer +peeresses peeress +peering peer +peerless peerless +peers peer +peevish peevish +peevishly peevish +peevishness peevish +peewit peewit +peewits peewit +peffer peffer +peg peg +pegasus pegasus +pegged peg +pegs peg +pelacanoides pelacanoid +pelagic pelag +pelham pelham +pelisse peliss +pell pell +pelt pelt +pelted pelt +pelting pelt +peltirogus peltirogus +peltiroguses peltirogus +peludo peludo +pembroke pembrok +pen pen +penal penal +penalties penalti +penalty penalti +penance penanc +penas pena +pence penc +pencil pencil +pencilled pencil +pencils pencil +pendant pendant +pending pend +pendulum pendulum +penetrable penetr +penetrate penetr +penetrated penetr +penetrates penetr +penetrating penetr +penetration penetr +penguin penguin +penguins penguin +peninsula peninsula +peninsular peninsular +penitence penit +penitent penit +penitential penitenti +penitents penit +penknife penknif +penn penn +penned pen +penniless penniless +penny penni +pennyworth pennyworth +pens pen +pension pension +pensioner pension +pensioners pension +pensioning pension +pensions pension +pensive pensiv +pensively pensiv +pensiveness pensiv +pent pent +pentland pentland +penton penton +pentonville pentonvill +penultimate penultim +penury penuri +peony peoni +people peopl +peopled peopl +peoples peopl +pepper pepper +pepsis pepsi +per per +perceive perceiv +perceived perceiv +perceives perceiv +perceiving perceiv +percent percent +percentage percentag +percentages percentag +perceptible percept +perceptibly percept +perception percept +perceptions percept +percepts percept +perch perch +percha percha +perchance perchanc +perched perch +perches perch +percival perciv +percolates percol +percolating percol +percolation percol +percy perci +perdition perdit +peremptorily peremptorili +peremptory peremptori +perennial perenni +perennially perenni +perfecfly perfecfli +perfect perfect +perfected perfect +perfection perfect +perfections perfect +perfectly perfect +perfidy perfidi +perforate perfor +perforated perfor +perforce perforc +perform perform +performance perform +performances perform +performed perform +performer perform +performers perform +performing perform +performs perform +perfume perfum +perfumed perfum +perfumery perfumeri +perfumes perfum +perhaps perhap +periagua periagua +perianth perianth +pericardium pericardium +peril peril +perilled peril +perilous peril +perilously peril +perils peril +period period +periodical period +periodically period +periodicals period +periods period +perish perish +perishable perish +perished perish +perishing perish +perjured perjur +perjury perjuri +perkins perkin +perlen perlen +permanence perman +permanent perman +permanently perman +permeated permeat +permissable permiss +permissible permiss +permission permiss +permit permit +permitted permit +permitting permit +pernambuco pernambuco +pernety perneti +pernicious pernici +peron peron +peroration peror +perpendicular perpendicular +perpendicularly perpendicular +perpetrated perpetr +perpetration perpetr +perpetrator perpetr +perpetrators perpetr +perpetual perpetu +perpetually perpetu +perpetuate perpetu +perpetuated perpetu +perpetuating perpetu +perpetuity perpetu +perplex perplex +perplexed perplex +perplexing perplex +perplexities perplex +perplexity perplex +perquisition perquisit +perquisitions perquisit +pers per +persecute persecut +persecuted persecut +persecuting persecut +persecution persecut +persecutions persecut +persecutor persecutor +persecutors persecutor +perseverance persever +persevere persever +persevered persev +perseveres persever +persevering persev +perseveringly persev +persia persia +persian persian +persist persist +persisted persist +persistence persist +persistency persist +persistent persist +persistently persist +persisting persist +persists persist +person person +personage personag +personages personag +personal person +personality person +personally person +personate person +personated person +personification personif +personified personifi +persons person +perspective perspect +perspiration perspir +perspired perspir +perspires perspir +persuadable persuad +persuade persuad +persuaded persuad +persuading persuad +persuasion persuas +persuasions persuas +persuasive persuas +persuasively persuas +pert pert +perthshire perthshir +pertinacious pertinaci +pertinaciously pertinaci +pertinacity pertinac +perturbation perturb +perturbed perturb +peru peru +perusal perus +perusals perus +peruse perus +perused perus +perusing perus +peruvian peruvian +peruvians peruvian +pervade pervad +pervaded pervad +pervades pervad +pervading pervad +perverse pervers +perversely pervers +perverseness pervers +perversion pervers +perversity pervers +perverted pervert +pervious pervious +perwerse perwers +peski peski +pest pest +pester pester +pestered pester +pestering pester +pestiferous pestifer +pestilence pestil +pestilent pestil +pestilential pestilenti +pestle pestl +pestryakov pestryakov +pet pet +petals petal +peter peter +petersburg petersburg +petersham petersham +petioles petiol +petise petis +petises petis +petition petit +petitioned petit +petitioners petition +petitioning petit +petitions petit +petorca petorca +petowker petowk +petrel petrel +petrels petrel +petrified petrifi +petrovitch petrovitch +petrovna petrovna +petrovsky petrovski +petruchio petruchio +pets pet +petted pet +petticoat petticoat +petticoats petticoat +pettifoggers pettifogg +pettifogging pettifog +pettiness petti +petting pet +pettish pettish +pettishly pettish +petty petti +petulance petul +petulant petul +petulantly petul +peuquenes peuquen +pew pew +pewter pewter +pfoo pfoo +phaeton phaeton +phairy phairi +phalanstery phalansteri +phallus phallus +phanaeus phanaeus +phantom phantom +phantoms phantom +pharaoh pharaoh +pharisees pharise +phases phase +pheasants pheasant +phenomena phenomena +phenomenal phenomen +phenomenally phenomen +phenomenes phenomen +phenomenon phenomenon +phenomenons phenomenon +phew phew +phib phib +phil phil +philandering philand +philanthropic philanthrop +philanthropical philanthrop +philanthropist philanthropist +philanthropists philanthropist +philanthropy philanthropi +philip philip +philippe philipp +philippines philippin +phillippensis phillippensi +philo philo +philos philo +philosoph philosoph +philosopher philosoph +philosophers philosoph +philosophical philosoph +philosophically philosoph +philosophies philosophi +philosophy philosophi +phineas phinea +phlegmatic phlegmat +pho pho +phoebe phoeb +phoenix phoenix +phonolite phonolit +phosphate phosphat +phosphorescence phosphoresc +phosphorescent phosphoresc +phosphoric phosphor +phosphorus phosphorus +phosphuretted phosphuret +photographer photograph +phrase phrase +phrased phrase +phraseology phraseolog +phrases phrase +phrenological phrenolog +phryniscus phryniscus +physalia physalia +physic physic +physical physic +physically physic +physician physician +physicians physician +physicking physick +physiognomist physiognomist +physiognomy physiognomi +physiol physiol +physiological physiolog +physiology physiolog +physique physiqu +phytolitharia phytolitharia +piano piano +pianoforte pianofort +pianos piano +picaninnies picaninni +picaninny picaninni +piccadilly piccadilli +pichy pichi +pick pick +pickaxe pickax +picked pick +pickers picker +picking pick +pickings pick +pickle pickl +pickled pickl +pickles pickl +pickling pickl +pickpocket pickpocket +pickpockets pickpocket +picks pick +pickwick pickwick +picnic picnic +picnics picnic +picter picter +pictorial pictori +picture pictur +pictured pictur +pictures pictur +picturesque picturesqu +picturing pictur +piderit piderit +pie pie +piebald piebald +piebalds piebald +piece piec +pieced piec +piecemeal piecem +pieces piec +piecework piecework +pieman pieman +pier pier +pierce pierc +pierced pierc +pierces pierc +piercing pierc +piercingly pierc +pierre pierr +pierres pierr +piers pier +pies pie +pietras pietra +piety pieti +pig pig +pigeon pigeon +pigeons pigeon +pigmies pigmi +pigmy pigmi +pigs pig +pigsties pigsti +pigtail pigtail +pigtails pigtail +pikestaff pikestaff +pile pile +piled pile +piles pile +pilfering pilfer +pilger pilger +pilgrim pilgrim +pilgrimage pilgrimag +piling pile +pill pill +pillar pillar +pillars pillar +pillow pillow +pillowed pillow +pillows pillow +pills pill +pilot pilot +piloted pilot +pilots pilot +pimlico pimlico +pimple pimpl +pimples pimpl +pimply pimpli +pin pin +pinafore pinafor +pincers pincer +pinch pinch +pinched pinch +pincheira pincheira +pinches pinch +pinching pinch +pincushions pincushion +pine pine +pineapple pineappl +pined pine +pines pine +pining pine +pinion pinion +pinions pinion +pink pink +pinked pink +pinker pinker +pinkish pinkish +pinnace pinnac +pinnacle pinnacl +pinnacled pinnacl +pinnacles pinnacl +pinned pin +pinning pin +pins pin +pint pint +pints pint +pious pious +pipe pipe +pipeclayed pipeclay +pipelight pipelight +piper piper +pipes pipe +piping pipe +pips pip +piquancy piquanc +piquant piquant +pique piqu +piqued piqu +piquet piquet +pirouette pirouett +pisagua pisagua +pise pise +pish pish +pistil pistil +pistol pistol +pistoling pistol +pistolling pistol +pistols pistol +pit pit +pitcairn pitcairn +pitch pitch +pitched pitch +pitcher pitcher +pitchers pitcher +pitchfork pitchfork +pitching pitch +pitchy pitchi +piteous piteous +piteously piteous +pitfall pitfal +pitfalls pitfal +pith pith +pithy pithi +pitiable pitiabl +pitiably pitiabl +pitied piti +pities piti +pitiful piti +pitilessly pitiless +pitmen pitmen +pits pit +pitt pitt +pittance pittanc +pittances pittanc +pitted pit +pitty pitti +pity piti +pitying piti +pivot pivot +pizzaro pizzaro +pla pla +plac plac +placard placard +placarded placard +placards placard +place place +placed place +places place +placid placid +placidity placid +placidly placid +placing place +plagiarists plagiarist +plague plagu +plagued plagu +plagues plagu +plaguing plagu +plaid plaid +plain plain +plainer plainer +plainest plainest +plainly plain +plainness plain +plains plain +plaint plaint +plaintiff plaintiff +plaintiffs plaintiff +plaintive plaintiv +plaintively plaintiv +plaintiveness plaintiv +plaire plair +plaisir plaisir +plait plait +plaited plait +plaits plait +plan plan +planaria planaria +planariae planaria +plane plane +planed plane +planet planet +planing plane +plank plank +planks plank +planned plan +planning plan +plans plan +plant plant +plantagenet plantagenet +plantation plantat +plantations plantat +planted plant +planter planter +planting plant +plants plant +planty planti +plashing plash +plaster plaster +plastered plaster +plat plat +plata plata +plate plate +plateau plateau +plated plate +plates plate +platform platform +platforms platform +platforna platforna +platina platina +platitudes platitud +platters platter +plaudits plaudit +plausible plausibl +plausibly plausibl +play play +playbill playbil +playbills playbil +played play +player player +players player +playfellow playfellow +playfellows playfellow +playful play +playfully play +playfulness play +playing play +playmate playmat +playmates playmat +plays play +playsure playsur +plaything playth +playthings playth +playwright playwright +plaza plaza +plea plea +pleace pleac +plead plead +pleaded plead +pleader pleader +pleaders pleader +pleading plead +pleadingly plead +pleads plead +pleasant pleasant +pleasanter pleasant +pleasantest pleasantest +pleasantly pleasant +pleasantness pleasant +pleasantry pleasantri +please pleas +pleased pleas +pleases pleas +pleasing pleas +pleasurable pleasur +pleasure pleasur +pleasures pleasur +pleasuring pleasur +plebeian plebeian +pledge pledg +pledged pledg +pledges pledg +pledging pledg +plentiful plenti +plentifully plenti +plenty plenti +plestcheiev plestcheiev +pliability pliabil +plicata plicata +plied pli +plies pli +plight plight +plighting plight +plodding plod +plot plot +plots plot +plotted plot +plotter plotter +plotters plotter +plotting plot +plough plough +ploughboy ploughboy +ploughed plough +ploughing plough +ploughman ploughman +ploughs plough +ploughshare ploughshar +ploughshares ploughshar +plover plover +pluck pluck +plucked pluck +plucking pluck +plucks pluck +plug plug +pluies plui +plum plum +plumage plumag +plumbago plumbago +plumed plume +pluming plume +plummets plummet +plump plump +plumpest plumpest +plumpness plump +plums plum +plunder plunder +plundered plunder +plundering plunder +plunge plung +plunged plung +plunges plung +plunging plung +plural plural +plurality plural +plus plus +plutonic pluton +ply pli +plying pli +plymouth plymouth +pm pm +poached poach +poaching poach +poast poast +pock pock +pocket pocket +pocketbook pocketbook +pocketed pocket +pocketing pocket +pockets pocket +pods pod +poem poem +poems poem +poet poet +poetic poetic +poetical poetic +poetizing poetiz +poetry poetri +poets poet +poignant poignant +poin poin +poins poin +point point +pointed point +pointedly point +pointing point +pointless pointless +points point +poised pois +poising pois +poison poison +poisoned poison +poisoning poison +poisonous poison +poke poke +poked poke +poker poker +pokers poker +pokes poke +poking poke +pokorev pokorev +polanco polanco +polar polar +pole pole +polecat polecat +polemical polem +polenka polenka +poles pole +police polic +policeman policeman +policemen policemen +policies polici +policy polici +polish polish +polished polish +polishes polish +polishing polish +polit polit +polite polit +politely polit +politeness polit +politest politest +politic polit +political polit +politically polit +politician politician +politicians politician +politics polit +polking polk +poll poll +pollard pollard +pollewt pollewt +polling poll +pollis polli +pollute pollut +polluted pollut +pollutions pollut +polly polli +pollys polli +poltroon poltroon +polya polya +polybori polybori +polyborus polyborus +polygastrica polygastrica +polygon polygon +polynesia polynesia +polynesian polynesian +polypi polypi +polypus polypus +polysyllable polysyl +pomaded pomad +pomarre pomarr +pomatum pomatum +pommel pommel +pomp pomp +pompey pompey +pomposities pompos +pompous pompous +pompously pompous +pomps pomp +poncho poncho +ponchos poncho +pond pond +ponder ponder +pondered ponder +pondering ponder +ponderous ponder +ponders ponder +ponds pond +poniard poniard +ponies poni +ponsonby ponsonbi +pony poni +pooder pooder +poodle poodl +poof poof +pooh pooh +pool pool +pools pool +poonded poond +poop poop +poor poor +poorer poorer +poorest poorest +poorly poor +poorness poor +pop pop +pope pope +popery poperi +poplars poplar +popolorum popolorum +popped pop +poppet poppet +popping pop +popular popular +popularity popular +populated popul +population popul +populous popul +porch porch +porches porch +porcupine porcupin +pore pore +pored pore +pores pore +porfiry porfiri +poring pore +pork pork +porous porous +porphyries porphyri +porphyrio porphyrio +porphyry porphyri +porpoises porpois +porridge porridg +porson porson +port port +portable portabl +portal portal +portend portend +portended portend +portentous portent +porter porter +porterage porterag +porters porter +portfolio portfolio +portfolios portfolio +porth porth +portico portico +portillo portillo +portion portion +portionless portionless +portions portion +portland portland +portly port +portmanteau portmanteau +portmanteaus portmanteaus +porto porto +portrait portrait +portraits portrait +portrayed portray +ports port +portsmouth portsmouth +portugal portug +portuguese portugues +pose pose +posed pose +poses pose +posession posess +posing pose +position posit +positions posit +positive posit +positively posit +positiveness posit +possess possess +possesse possess +possessed possess +possesses possess +possessin possessin +possessing possess +possession possess +possessions possess +possessive possess +possessor possessor +possessors possessor +possibilities possibl +possibility possibl +possible possibl +possibly possibl +post post +posta posta +postage postag +postas posta +posted post +poster poster +posterior posterior +posterity poster +postern postern +posters poster +posthouse posthous +postilion postilion +posting post +postman postman +postmaster postmast +postmen postmen +postpone postpon +postponed postpon +postponement postpon +postpones postpon +postponing postpon +posts post +postscript postscript +posture postur +postures postur +posuit posuit +pot pot +potanchikov potanchikov +potash potash +potations potat +potato potato +potatoes potato +potatoless potatoless +potboy potboy +potchinkov potchinkov +potent potent +potentate potent +pothouse pothous +potion potion +potosi potosi +potrero potrero +pots pot +potted pot +potter potter +potteries potteri +pottery potteri +pouce pouc +pouch pouch +pouches pouch +poultry poultri +pounce pounc +pounced pounc +pounces pounc +pouncing pounc +pound pound +pounded pound +pounder pounder +pounds pound +pountney pountney +pountneys pountney +pour pour +poured pour +pouring pour +pours pour +pout pout +pouted pout +pouting pout +poverty poverti +powder powder +powdered powder +powderin powderin +powe pow +powell powel +power power +powerful power +powerfully power +powerless powerless +powers power +pox pox +pp pp +pr pr +practicability practic +practicable practic +practical practic +practicality practic +practically practic +practice practic +practices practic +practise practis +practised practis +practiser practis +practises practis +practising practis +practitioner practition +practitioners practition +prae prae +praetorian praetorian +praia praia +prairies prairi +praise prais +praised prais +praises prais +praiseworthy praiseworthi +praising prais +prance pranc +prancing pranc +pranks prank +prasant prasant +praskovya praskovya +prattlings prattl +pratty pratti +prawn prawn +prawns prawn +pray pray +praya praya +prayed pray +prayer prayer +prayers prayer +prayfession prayfess +prayin prayin +praying pray +prays pray +pre pre +preach preach +preached preach +preacher preacher +preachers preacher +preaching preach +prebendary prebendari +precarious precari +precaution precaut +precautions precaut +precede preced +preceded preced +precedence preced +precedent preced +precedents preced +preceding preced +precept precept +preceptor preceptor +precepts precept +precincts precinct +precious precious +preciousest preciousest +precipice precipic +precipices precipic +precipitate precipit +precipitated precipit +precipitately precipit +precipitation precipit +precipitous precipit +precise precis +precisely precis +precision precis +precluded preclud +precocious precoci +precociously precoci +preconceived preconceiv +preconcerted preconcert +predecessor predecessor +predecessors predecessor +predestined predestin +predicament predica +predicaments predica +predict predict +predicted predict +predicting predict +prediction predict +predictions predict +predilections predilect +predisposition predisposit +predominant predomin +predominate predomin +predominated predomin +preening preen +preface prefac +prefacing prefac +prefatory prefatori +prefer prefer +preferable prefer +preference prefer +preferer prefer +preferment prefer +preferred prefer +preferring prefer +prefers prefer +prefixed prefix +prehensile prehensil +prehensilis prehensili +prejudge prejudg +prejudice prejudic +prejudiced prejud +prejudices prejudic +prejudicial prejudici +preliminaries preliminari +preliminary preliminari +prelude prelud +premature prematur +prematurely prematur +premeditated premedit +premeditation premedit +premier premier +premiers premier +premiership premiership +premise premis +premised premis +premises premis +premium premium +prentice prentic +prentices prentic +preoccupation preoccup +preoccupations preoccup +preoccupied preoccupi +preordained preordain +preparation prepar +preparations prepar +preparatory preparatori +prepare prepar +prepared prepar +prepares prepar +preparing prepar +prepense prepens +preponderance preponder +preponderated preponder +preponderates preponder +preponderating preponder +prepossessed prepossess +prepossessing prepossess +prepossession prepossess +prepossessions prepossess +preposterous preposter +presbyterian presbyterian +prescribe prescrib +prescribed prescrib +prescription prescript +prescriptive prescript +presence presenc +presenfty presenfti +present present +presentable present +presentation present +presented present +presentime presentim +presentiment presenti +presentiments presenti +presenting present +presently present +presentments present +presents present +preservation preserv +preserve preserv +preserved preserv +preserver preserv +preserves preserv +preserving preserv +preside presid +presided presid +presidency presid +president presid +presidents presid +presidentship presidentship +presiding presid +press press +pressed press +presses press +pressing press +pressingly press +pressure pressur +prestige prestig +presumably presum +presume presum +presumed presum +presumes presum +presuming presum +presumption presumpt +presumptuous presumptu +presumptuously presumptu +presupposes presuppos +pretence pretenc +pretences pretenc +pretend pretend +pretended pretend +pretending pretend +pretends pretend +pretension pretens +pretensions pretens +pretentious pretenti +preternatural preternatur +pretext pretext +pretexts pretext +prett prett +prettier prettier +prettiest prettiest +prettily prettili +prettiness pretti +prettinesses pretti +pretty pretti +prevail prevail +prevailed prevail +prevailing prevail +prevails prevail +prevalent preval +prevaricate prevar +prevent prevent +prevented prevent +preventing prevent +prevents prevent +previous previous +previously previous +prevost prevost +prey prey +preyed prey +preying prey +preys prey +price price +priceless priceless +prices price +prick prick +pricked prick +pricking prick +prickles prickl +prickly prick +pricks prick +pride pride +pries pri +priest priest +priesthood priesthood +priestly priest +priests priest +prig prig +prilukov prilukov +prim prim +primarily primarili +primary primari +prime prime +primer primer +primera primera +primeval primev +primitive primit +primogeniture primogenitur +primrose primros +prince princ +princely princ +princes princ +princess princess +princesses princess +principal princip +principally princip +principals princip +principle principl +principles principl +prinking prink +print print +printed print +printers printer +printing print +prints print +prionotus prionotus +prior prior +prioress prioress +priority prioriti +priory priori +priscilla priscilla +prismatic prismat +prison prison +prisoner prison +prisoners prison +prisons prison +pritchard pritchard +pritchards pritchard +privacy privaci +private privat +privateer privat +privately privat +privation privat +privations privat +privilege privileg +privileged privileg +privileges privileg +privy privi +prize prize +prized prize +prizes prize +pro pro +probabilities probabl +probability probabl +probable probabl +probably probabl +probation probat +probing probe +problem problem +problematical problemat +problems problem +proboscis probosci +procedure procedur +proceed proceed +proceeded proceed +proceeding proceed +proceedings proceed +proceeds proceed +procellaria procellaria +process process +processes process +procession process +proclaim proclaim +proclaimed proclaim +proclaiming proclaim +proclaims proclaim +proclamation proclam +procrastinates procrastin +procrastination procrastin +proctotretus proctotretus +procurable procur +procure procur +procured procur +procuring procur +prodigal prodig +prodigality prodig +prodigieux prodigieux +prodigious prodigi +prodigiously prodigi +prodigy prodigi +produce produc +produced produc +produces produc +producible produc +producing produc +product product +production product +productions product +productive product +productiveness product +products product +profanation profan +profane profan +profanely profan +profaning profan +profess profess +professed profess +professes profess +professing profess +profession profess +professional profession +professionally profession +professionals profession +professionaly professionali +professions profess +professor professor +professors professor +professorship professorship +proffer proffer +proffered proffer +proficiency profici +proficient profici +profile profil +profit profit +profitable profit +profited profit +profiting profit +profitless profitless +profits profit +profligacy profligaci +profligate proflig +profligately proflig +profligates proflig +profound profound +profoundest profoundest +profoundly profound +profundity profund +profuse profus +profusely profus +profusion profus +progenitive progenit +progenitors progenitor +progne progn +prognostications prognost +programme programm +progress progress +progressed progress +progressing progress +progression progress +progressive progress +progressively progress +progressives progress +prohibited prohibit +prohibiting prohibit +prohibition prohibit +project project +projected project +projecting project +projection project +projector projector +projects project +prokofitch prokofitch +prolific prolif +prolix prolix +prolixities prolix +prolixity prolix +prolong prolong +prolongation prolong +prolonged prolong +prolonging prolong +promenade promenad +promethean promethean +prominent promin +prominently promin +promise promis +promised promis +promises promis +promisin promisin +promising promis +promissory promissori +promontories promontori +promontory promontori +promote promot +promoted promot +promoter promot +promotes promot +promoting promot +promotion promot +prompt prompt +prompted prompt +prompter prompter +prompters prompter +prompting prompt +promptitude promptitud +promptly prompt +promptness prompt +prompts prompt +prone prone +proneness prone +pronoun pronoun +pronounce pronounc +pronounced pronounc +pronounces pronounc +pronouncing pronounc +proodest proodest +proof proof +proofs proof +prop prop +propaganda propaganda +propagated propag +propagates propag +propagation propag +propensity propens +proper proper +properly proper +properties properti +property properti +propertyless propertyless +prophecy propheci +prophesied prophesi +prophesying prophesi +prophet prophet +prophetic prophet +prophetical prophet +prophetically prophet +propitiate propiti +propitiated propiti +propitiation propiti +propitiatory propitiatori +propitious propiti +proportion proport +proportionably proportion +proportional proport +proportionally proport +proportionate proportion +proportionately proportion +proportioned proport +proportions proport +propos propo +proposal propos +proposals propos +propose propos +proposed propos +proposes propos +proposing propos +proposition proposit +propositions proposit +propound propound +propounded propound +propounding propound +propoundlng propoundlng +propounds propound +propped prop +propping prop +proprieties proprieti +proprietor proprietor +proprietorship proprietorship +proprietress proprietress +propriety proprieti +prorogation prorog +prosaic prosaic +proscenium proscenium +proscribed proscrib +prose prose +prosecute prosecut +prosecuted prosecut +prosecution prosecut +prosecutor prosecutor +prosing prose +prospect prospect +prospective prospect +prospects prospect +prospectus prospectus +prosper prosper +prospered prosper +prospering prosper +prosperity prosper +prosperous prosper +prosperously prosper +prostrate prostrat +prostrated prostrat +prostration prostrat +prosy prosi +protect protect +protected protect +protecting protect +protection protect +protective protect +protector protector +protectors protector +protegee protege +proteges proteg +protest protest +protestant protest +protestantism protestant +protestation protest +protestations protest +protested protest +protesting protest +protests protest +proteus proteus +protococcus protococcus +prototype prototyp +prototypes prototyp +protract protract +protracted protract +protrude protrud +protruded protrud +protrudes protrud +protruding protrud +proud proud +prouder prouder +proudest proudest +proudhon proudhon +proudly proud +prov prov +prove prove +proved prove +proverb proverb +proves prove +provide provid +provided provid +providence provid +providential providenti +providentially providenti +provider provid +provides provid +providing provid +province provinc +provinces provinc +provincial provinci +proving prove +provision provis +provisional provision +provisions provis +proviso proviso +provocation provoc +provocative provoc +provoke provok +provoked provok +provokes provok +provoking provok +provokingly provok +prow prow +prowess prowess +prowl prowl +prowled prowl +prowling prowl +proximity proxim +proxy proxi +proxying proxi +prudence prudenc +prudent prudent +prudently prudent +prudery pruderi +prudish prudish +pruning prune +prunings prune +prurient prurient +prussian prussian +prussians prussian +prussic prussic +pry pri +psalm psalm +psalms psalm +psammophis psammophi +pselaphus pselaphus +pseudo pseudo +psha psha +pshaw pshaw +psyche psych +psychological psycholog +psychologically psycholog +psychologist psychologist +psychology psycholog +pt pt +ptarmigans ptarmigan +pterophorus pterophorus +pteropoda pteropoda +pteroptochos pteroptocho +public public +publicans publican +publication public +publications public +publicity public +publicly public +publish publish +published publish +publisher publish +publishers publish +publishing publish +puckered pucker +puddick puddick +pudding pud +puddings pud +puddle puddl +puddles puddl +puente puent +puff puff +puffed puf +puffing puf +puffinus puffinus +puffs puff +puffy puffi +pug pug +pugilistic pugilist +pugnacious pugnaci +pugnacity pugnac +pugstyles pugstyl +pul pul +pulcheria pulcheria +pull pull +pulled pull +pulling pull +pulls pull +pulp pulp +pulperia pulperia +pulpit pulpit +pulpy pulpi +pulse puls +pulses puls +pum pum +puma puma +pumas puma +pumice pumic +pumiceous pumic +pumila pumila +pummelled pummel +pummelling pummel +pump pump +pumping pump +pumpkin pumpkin +pumps pump +pun pun +puna puna +punch punch +punched punch +punches punch +punchinello punchinello +punching punch +punctatissima punctatissima +punctilious punctili +punctiliousness punctili +punctual punctual +punctuality punctual +punctually punctual +punctuation punctuat +puncture punctur +punctured punctur +pundit pundit +pundits pundit +punish punish +punished punish +punishing punish +punishment punish +punt punt +punta punta +puny puni +pupil pupil +pupils pupil +pupker pupker +puppet puppet +puppies puppi +puppy puppi +puppyism puppyism +purblind purblind +purchas purcha +purchase purchas +purchased purchas +purchaser purchas +purchases purchas +purchasing purchas +pure pure +purechurch purechurch +purely pure +purer purer +purest purest +purge purg +purified purifi +purify purifi +purity puriti +purple purpl +purplish purplish +purport purport +purporting purport +purpose purpos +purposed purpos +purposeless purposeless +purposely purpos +purposes purpos +purpura purpura +purpurea purpurea +purr purr +purring pur +purse purs +pursed purs +purser purser +purses purs +pursing purs +pursuance pursuanc +pursuant pursuant +pursue pursu +pursued pursu +pursuer pursuer +pursuers pursuer +pursues pursu +pursuing pursu +pursuit pursuit +pursuits pursuit +pursult pursult +purvided purvid +push push +pushed push +pushes push +pushing push +pushkin pushkin +pusillanimity pusillanim +puss puss +pussy pussi +pustules pustul +put put +putrefaction putrefact +putrefying putrefi +putrid putrid +putridity putrid +puts put +puttin puttin +putting put +puzzle puzzl +puzzled puzzl +puzzles puzzl +puzzling puzzl +py py +pye pye +pygmy pygmi +pyke pyke +pyotr pyotr +pyramid pyramid +pyramids pyramid +pyrard pyrard +pyre pyre +pyrenees pyrene +pyrifera pyrifera +pyrites pyrit +pyrocephalus pyrocephalus +pyrophorus pyrophorus +pyrosma pyrosma +q q +qc qc +qu qu +quaccha quaccha +quack quack +quadra quadra +quadrangle quadrangl +quadrangular quadrangular +quadras quadra +quadrille quadrill +quadruped quadrup +quadrupeds quadrup +quadruple quadrupl +quadrupled quadrupl +quagmire quagmir +quagmires quagmir +quail quail +quailed quail +quailing quail +quails quail +quaint quaint +quaintly quaint +quaintness quaint +quake quak +quaked quak +quakes quak +quaking quak +quakings quak +quale qual +qualification qualif +qualifications qualif +qualified qualifi +qualify qualifi +qualifying qualifi +qualities qualiti +quality qualiti +quand quand +quantite quantit +quantities quantiti +quantity quantiti +quarrel quarrel +quarrelled quarrel +quarrelling quarrel +quarrels quarrel +quarrelsome quarrelsom +quarry quarri +quart quart +quarter quarter +quartered quarter +quartering quarter +quarterly quarter +quartermaster quartermast +quartern quartern +quarters quarter +quarther quarther +quartz quartz +quatre quatr +quaver quaver +quavering quaver +quay quay +que que +quebec quebec +quebrantahuesos quebrantahueso +quedius quedius +queen queen +queens queen +queer queer +queerest queerest +queerness queer +quell quell +quelled quell +quench quench +quenched quench +quenching quench +queries queri +querulous querul +query queri +quest quest +question question +questionable question +questioned question +questioner question +questioning question +questionings question +questions question +quibble quibbl +quick quick +quicken quicken +quickened quicken +quickens quicken +quicker quicker +quickest quickest +quickly quick +quickness quick +quicksilver quicksilv +quidnuncs quidnunc +quien quien +quiescence quiescenc +quiescent quiescent +quiet quiet +quieted quiet +quieter quieter +quietest quietest +quietly quiet +quietness quiet +quiets quiet +quietude quietud +quilimari quilimari +quillay quillay +quillota quillota +quills quill +quilmes quilm +quilt quilt +quince quinc +quinchao quinchao +quintero quintero +quints quint +quintus quintus +quiriquina quiriquina +quit quit +quite quit +quito quito +quits quit +quitted quit +quitting quit +quiver quiver +quivered quiver +quivering quiver +quivers quiver +quixote quixot +quixotic quixot +quixotism quixot +quizzical quizzic +quizzing quizz +quizzings quizz +qulte qult +quo quo +quondam quondam +quoodle quoodl +quotation quotat +quotations quotat +quote quot +quoted quot +quotes quot +quoth quoth +quoting quot +quoy quoy +r r +ra ra +raa raa +rabbit rabbit +rabbits rabbit +rabidly rabid +race race +racehorses racehors +racers racer +races race +rachael rachael +rachel rachel +racing race +rack rack +racked rack +racket racket +racketing racket +racking rack +rackings rack +radack radack +radiance radianc +radiant radiant +radiantly radiant +radiata radiata +radiate radiat +radiated radiat +radiating radiat +radiation radiat +radical radic +radicalism radic +radicals radic +radii radii +radish radish +radishchev radishchev +radishes radish +rads rad +rafael rafael +raff raff +raffaelite raffaelit +raffaelites raffaelit +raffaelitism raffaelit +raft raft +rafters rafter +rafts raft +rag rag +rage rage +raged rage +rages rage +ragged rag +raging rage +rags rag +rail rail +railed rail +railing rail +railings rail +raillery railleri +railroad railroad +railroads railroad +rails rail +railway railway +railways railway +rain rain +rainbow rainbow +raindrops raindrop +rained rain +raining rain +rains rain +rainy raini +raise rais +raised rais +raises rais +raising rais +raisins raisin +rake rake +raked rake +rakes rake +raking rake +rakish rakish +rakishly rakish +rakishness rakish +ral ral +rallied ralli +rallus rallus +rally ralli +rallying ralli +ralph ralph +ram ram +ramble rambl +rambled rambl +rambles rambl +rambling rambl +ramification ramif +ramirez ramirez +rammer rammer +rampant rampant +rampart rampart +ramsden ramsden +ramsgate ramsgat +ran ran +rana rana +rancagua rancagua +ranche ranch +rancho rancho +ranchos rancho +rancorous rancor +rancorously rancor +rancour rancour +randal randal +randall randal +random random +rang rang +range rang +ranged rang +rangees range +ranges rang +ranging rang +rank rank +ranked rank +rankled rankl +rankling rankl +rankness rank +ranks rank +ransack ransack +ransacked ransack +ransacking ransack +rap rap +rapacious rapaci +rapacity rapac +raphael raphael +rapid rapid +rapidity rapid +rapidly rapid +rapine rapin +rapping rap +raps rap +rapt rapt +rapture raptur +raptures raptur +rapturous raptur +rapturously raptur +rare rare +rarefied rarefi +rarely rare +rarer rarer +rarest rarest +rarity rariti +rascal rascal +rascality rascal +rascally rascal +rascals rascal +rash rash +rasher rasher +rashly rash +rashness rash +raskolnikov raskolnikov +raspberries raspberri +raspberry raspberri +rasper rasper +rastro rastro +rat rat +rate rate +rated rate +rates rate +rathe rath +rather rather +ratio ratio +rational ration +rationally ration +rations ration +rats rat +rattle rattl +rattled rattl +rattler rattler +rattlers rattler +rattles rattl +rattlesnake rattlesnak +rattling rattl +rattus rattus +ravaged ravag +ravages ravag +ravaging ravag +rave rave +raved rave +raven raven +ravenous raven +ravenously raven +ravens raven +ravine ravin +ravines ravin +raving rave +ravings rave +ravins ravin +ravishing ravish +raw raw +rawest rawest +ray ray +rays ray +razor razor +razors razor +razsudkin razsudkin +razumihin razumihin +razumihins razumihin +rd rd +re re +rea rea +reach reach +reached reach +reaches reach +reaching reach +reaction reaction +reactionaries reactionari +reactionary reactionari +read read +reader reader +readers reader +readied readi +readiest readiest +readil readil +readily readili +readiness readi +reading read +readings read +readjourned readjourn +readjust readjust +readjusted readjust +readjusts readjust +reads read +ready readi +real real +realisation realis +realise realis +realised realis +realising realis +realit realit +realities realiti +reality realiti +realize realiz +realized realiz +realizes realiz +realizing realiz +reall reall +really realli +realm realm +realms realm +reals real +realty realti +ream ream +reams ream +reanimate reanim +reap reap +reaped reap +reaping reap +reappear reappear +reappearance reappear +reappeared reappear +reappearing reappear +reappears reappear +rear rear +reared rear +rearing rear +rearrange rearrang +rearrangements rearrang +rears rear +reascended reascend +reascending reascend +reason reason +reasonable reason +reasonableness reason +reasonably reason +reasoned reason +reasoners reason +reasoning reason +reasons reason +reassume reassum +reassurance reassur +reassure reassur +reassured reassur +reassures reassur +reassuring reassur +reassuringly reassur +reaumur reaumur +rebel rebel +rebelled rebel +rebelling rebel +rebellion rebellion +rebellious rebelli +rebellyon rebellyon +rebels rebel +rebound rebound +rebounded rebound +rebounding rebound +rebuff rebuff +rebuffed rebuf +rebuilding rebuild +rebuilt rebuilt +rebuke rebuk +rebuked rebuk +rec rec +recado recado +recall recal +recalled recal +recalling recal +recalls recal +recantation recant +recapitulate recapitul +recapitulation recapitul +rece rece +receded reced +receding reced +receipt receipt +receipts receipt +receive receiv +received receiv +receiver receiv +receives receiv +receiving receiv +recent recent +recently recent +reception recept +receptions recept +recess recess +recesses recess +recipe recip +recipient recipi +recipro recipro +reciprocal reciproc +reciprocate reciproc +reciprocated reciproc +reciprocating reciproc +reciprocity reciproc +recital recit +recitals recit +recite recit +recited recit +reckless reckless +recklessly reckless +recklessness reckless +reckon reckon +reckoned reckon +reckoners reckon +reckoning reckon +reckonings reckon +reclaim reclaim +reclaimed reclaim +reclined reclin +reclines reclin +reclining reclin +reclosing reclos +recluse reclus +recognisant recognis +recognise recognis +recognised recognis +recognising recognis +recognition recognit +recognize recogn +recognized recogn +recognizes recogn +recognizing recogn +recoil recoil +recoiled recoil +recoiling recoil +recoils recoil +recollect recollect +recollected recollect +recollecting recollect +recollection recollect +recollections recollect +recollects recollect +recommenced recommenc +recommences recomm +recommend recommend +recommendation recommend +recommended recommend +recommending recommend +recompense recompens +recompenses recompens +recomposed recompos +recomposing recompos +reconcilable reconcil +reconcile reconcil +reconciled reconcil +reconcilements reconcil +reconciliation reconcili +reconciling reconcil +reconnoitre reconnoitr +reconnoitred reconnoitr +reconsider reconsid +reconsideration reconsider +reconsidering reconsid +reconsigning reconsign +reconsignment reconsign +recopied recopi +record record +recorded record +recording record +records record +recount recount +recounted recount +recounting recount +recouped recoup +recourse recours +recover recov +recovered recov +recovering recov +recovers recov +recovery recoveri +recreation recreat +recreative recreat +recrimination recrimin +recriminations recrimin +recross recross +recrossed recross +recrossing recross +recruit recruit +recruited recruit +rectified rectifi +rectify rectifi +rectifying rectifi +rectitude rectitud +rectly rect +rector rector +rectory rectori +recumbent recumb +recuperative recup +recur recur +recurred recur +recurrence recurr +recurrent recurr +recurring recur +recurs recur +recuvver recuvv +red red +reddened redden +reddening redden +redder redder +reddest reddest +reddish reddish +reddy reddi +redecorated redecor +redeem redeem +redeemed redeem +redeemer redeem +redeeming redeem +redemption redempt +redistribution redistribut +redly red +redolent redol +redouble redoubl +redoubled redoubl +redoubling redoubl +redoubtable redoubt +redound redound +redounded redound +redress redress +reduce reduc +reduced reduc +reduces reduc +reducidos reducido +reducing reduc +reduction reduct +reductions reduct +reduvius reduvius +reed reed +reeds reed +reef reef +reefs reef +reeght reeght +reek reek +reeked reek +reeking reek +reeks reek +reel reel +reeled reel +reeling reel +ref ref +refer refer +referable refer +reference refer +references refer +referred refer +referring refer +refers refer +refine refin +refined refin +refinement refin +refinements refin +refines refin +refit refit +reflect reflect +reflected reflect +reflectin reflectin +reflecting reflect +reflection reflect +reflections reflect +reflective reflect +reflector reflector +reflects reflect +refolding refold +refolds refold +reform reform +reformation reform +reformed reform +reformer reform +reforming reform +reforms reform +refraction refract +refractory refractori +refrain refrain +refrained refrain +refrains refrain +refresh refresh +refreshed refresh +refreshes refresh +refreshing refresh +refreshingly refresh +refreshment refresh +refreshments refresh +refrigerator refriger +refuge refug +refugees refuge +refulgent refulg +refund refund +refunded refund +refurnish refurnish +refusal refus +refuse refus +refused refus +refuses refus +refusest refusest +refusing refus +refutation refut +refute refut +reg reg +regain regain +regained regain +regaining regain +regains regain +regal regal +regale regal +regaled regal +regaling regal +regard regard +regarded regard +regardful regard +regarding regard +regardless regardless +regards regard +regeneration regener +regent regent +regimen regimen +regiment regiment +regimental regiment +reginald reginald +region region +regions region +register regist +registered regist +registrar registrar +registries registri +regression regress +regret regret +regretful regret +regretfully regret +regrets regret +regretted regret +regretting regret +regular regular +regularity regular +regularly regular +regulars regular +regulate regul +regulated regul +regulates regul +regulating regul +regulation regul +rehearsal rehears +rehearse rehears +rehearsed rehears +reid reid +reign reign +reigned reign +reigning reign +reigns reign +reimbursed reimburs +rein rein +reindeer reindeer +reined rein +reinforced reinforc +reining rein +reins rein +reinstated reinstat +reinstating reinstat +reiterated reiter +reiterates reiter +reiteration reiter +reithrodon reithrodon +reject reject +rejected reject +rejecting reject +rejection reject +rejects reject +rejoice rejoic +rejoiced rejoic +rejoices rejoic +rejoicing rejoic +rejoicings rejoic +rejoin rejoin +rejoinder rejoind +rejoinders rejoind +rejoined rejoin +rejoining rejoin +rejoins rejoin +rekindled rekindl +relapse relaps +relapsed relaps +relapses relaps +relapsing relaps +relate relat +related relat +relates relat +relating relat +relation relat +relations relat +relationship relationship +relative relat +relatively relat +relatives relat +relax relax +relaxation relax +relaxations relax +relaxe relax +relaxed relax +relaxes relax +relaxing relax +relays relay +release releas +released releas +releases releas +releasing releas +relent relent +relented relent +relenting relent +relentless relentless +relents relent +reliable reliabl +reliance relianc +reliant reliant +relic relic +relics relic +relict relict +relied reli +relief relief +reliefs relief +relies reli +relieve reliev +relieved reliev +relieves reliev +relieving reliev +religion religion +religions religion +religious religi +religiously religi +relinquish relinquish +relinquished relinquish +relinquishing relinquish +relinquishment relinquish +reliques reliqu +relish relish +relished relish +relishing relish +reluctance reluct +reluctant reluct +reluctantly reluct +rely reli +relying reli +remain remain +remainder remaind +remaine remain +remained remain +remaining remain +remains remain +remand remand +remanded remand +remands remand +remark remark +remarkable remark +remarkably remark +remarked remark +remarkedly remark +remarking remark +remarks remark +remedies remedi +remedy remedi +remember rememb +remembered rememb +remembering rememb +remembers rememb +remembrance remembr +remembrances remembr +remensher remensh +remind remind +reminded remind +reminder remind +reminders remind +reminding remind +remindingmanfact remindingmanfact +reminds remind +reminiscence reminisc +reminiscences reminisc +reminiscent reminisc +remiss remiss +remit remit +remittance remitt +remitting remit +remnant remnant +remnants remnant +remonstrance remonstr +remonstrances remonstr +remonstrate remonstr +remonstrated remonstr +remonstrates remonstr +remonstrating remonstr +remonstrative remonstr +remorse remors +remorseful remors +remote remot +remotely remot +remoteness remot +remotest remotest +remounted remount +removal remov +removals remov +remove remov +removed remov +removes remov +removing remov +remplir remplir +remunerate remuner +remunerated remuner +remuneration remuner +rend rend +render render +rendered render +rendering render +renders render +rendezvous rendezv +rending rend +rendus rendus +renegade renegad +renew renew +renewable renew +renewal renew +renewals renew +renewed renew +renewing renew +renews renew +rengger rengger +renounce renounc +renounced renounc +renouncing renounc +renous renous +renovation renov +renown renown +renowned renown +rent rent +rents rent +renunciation renunci +repacked repack +repaid repaid +repair repair +repaired repair +repairing repair +repairs repair +reparation repar +repartee reparte +repass repass +repassed repass +repassing repass +repast repast +repay repay +repaying repay +repayment repay +repays repay +repeal repeal +repealed repeal +repeat repeat +repeated repeat +repeatedly repeat +repeater repeat +repeating repeat +repeats repeat +repeatually repeatu +repel repel +repelled repel +repellent repel +repelling repel +repent repent +repentance repent +repentant repent +repented repent +repenteth repenteth +repenting repent +repents repent +reperusal reperus +repetition repetit +repetitions repetit +rephed reph +repine repin +repined repin +repines repin +repining repin +replace replac +replaced replac +replaces replac +replacing replac +replenishing replenish +replete replet +repletion replet +replied repli +replies repli +reply repli +replying repli +report report +reported report +reporter report +reporters report +reporting report +reports report +repose repos +reposed repos +reposes repos +reposing repos +repository repositori +repossess repossess +repossession repossess +reprehensible reprehens +reprehension reprehens +represent repres +representation represent +representations represent +representative repres +representatives repres +represented repres +representing repres +represents repres +repress repress +repressed repress +repressing repress +reprieve repriev +reprint reprint +reprinted reprint +reproach reproach +reproached reproach +reproaches reproach +reproachful reproach +reproachfully reproach +reproaching reproach +reprobate reprob +reprobates reprob +reprobation reprob +reproduce reproduc +reproduced reproduc +reproducing reproduc +reproof reproof +reproofs reproof +reprove reprov +reproved reprov +reprovingly reprov +reptile reptil +reptiles reptil +republic republ +republican republican +republicanism republican +republicans republican +republics republ +republished republish +repudiate repudi +repudiated repudi +repudiating repudi +repudiation repudi +repugnance repugn +repugnant repugn +repulse repuls +repulsed repuls +repulsion repuls +repulsive repuls +reputable reput +reputation reput +reputations reput +repute reput +reputed reput +request request +requested request +requesting request +requests request +requiem requiem +require requir +required requir +requirements requir +requires requir +requiring requir +requisite requisit +requisites requisit +requisition requisit +requite requit +reread reread +rescue rescu +rescued rescu +rescuers rescuer +rescuing rescu +research research +researches research +resemblance resembl +resemble resembl +resembled resembl +resembles resembl +resembling resembl +resent resent +resented resent +resentful resent +resentfully resent +resenting resent +resentment resent +resentments resent +resents resent +reservation reserv +reservations reserv +reserve reserv +reserved reserv +reserves reserv +reserving reserv +reservoir reservoir +reservoirs reservoir +resettles resettl +resfless resfless +reside resid +resided resid +residence resid +residences resid +resident resid +residents resid +resides resid +residing resid +residue residu +resign resign +resignation resign +resignations resign +resigned resign +resigning resign +resigns resign +resin resin +resinous resin +resist resist +resistance resist +resisted resist +resisting resist +resists resist +resoled resol +resolute resolut +resolutely resolut +resolution resolut +resolutions resolut +resolve resolv +resolved resolv +resolves resolv +resolving resolv +resonant reson +resort resort +resorted resort +resorting resort +resorts resort +resound resound +resounded resound +resounding resound +resource resourc +resourcefulness resourc +resources resourc +respect respect +respectabilities respect +respectability respect +respectable respect +respectably respect +respected respect +respectful respect +respectfully respect +respecting respect +respective respect +respectively respect +respects respect +respiration respir +respite respit +resplendent resplend +resplendently resplend +respond respond +responded respond +responding respond +responds respond +response respons +responsibilities respons +responsibility respons +responsible respons +responsive respons +resslich resslich +rest rest +restaurant restaur +restaurants restaur +rested rest +restful rest +resting rest +restitution restitut +restive restiv +restless restless +restlessly restless +restlessness restless +restoration restor +restorative restor +restoratives restor +restore restor +restored restor +restores restor +restoring restor +restrain restrain +restrained restrain +restraining restrain +restrains restrain +restraint restraint +restraints restraint +restrictions restrict +rests rest +resuit resuit +result result +resultant result +resulted result +resulting result +results result +resume resum +resumed resum +resumes resum +resuming resum +resumption resumpt +resurrected resurrect +resurrection resurrect +resurrections resurrect +resuscitated resuscit +retail retail +retain retain +retained retain +retainer retain +retainers retain +retaining retain +retains retain +retaliate retali +retaliated retali +retaliation retali +retard retard +retarded retard +retches retch +retention retent +reticence retic +reticent retic +reticles reticl +reticule reticul +reticules reticul +retinue retinu +retire retir +retired retir +retirement retir +retirements retir +retires retir +retiring retir +retored retor +retort retort +retorted retort +retorting retort +retorts retort +retouching retouch +retrace retrac +retraced retrac +retraces retrac +retract retract +retracted retract +retraction retract +retreat retreat +retreated retreat +retreating retreat +retreats retreat +retrenchment retrench +retrenchments retrench +retribution retribut +retributive retribut +retrievable retriev +retrieve retriev +retrieved retriev +retrieving retriev +retrograde retrograd +retrograding retrograd +retrorsum retrorsum +retrospect retrospect +retrospective retrospect +return return +returned return +returning return +returns return +retzch retzch +reunion reunion +rev rev +reveal reveal +revealed reveal +revealing reveal +revel revel +revelation revel +revelations revel +revelled revel +revellers revel +revelling revel +revelry revelri +revels revel +revenge reveng +revenged reveng +revengeful reveng +revenges reveng +revenging reveng +revenue revenu +reverberate reverber +reverberated reverber +reverberates reverber +reverberating reverber +reverberation reverber +revered rever +reverence rever +reverenced reverenc +reverend reverend +reverends reverend +reverent rever +reverential reverenti +reverentially reverenti +reverently rever +reverie reveri +reversal revers +reverse revers +reversed revers +reverses revers +reversion revers +revert revert +reverted revert +reverting revert +reverts revert +reviendra reviendra +review review +reviewal review +reviewing review +reviews review +revile revil +reviled revil +reviling revil +revilings revil +revise revis +revision revis +revisit revisit +revisited revisit +revival reviv +revive reviv +revived reviv +reviving reviv +revivingly reviv +revoke revok +revoked revok +revolt revolt +revolted revolt +revolting revolt +revolts revolt +revolution revolut +revolutionary revolutionari +revolutionist revolutionist +revolutionized revolution +revolutions revolut +revolve revolv +revolved revolv +revolver revolv +revolves revolv +revolving revolv +revulsion revuls +reward reward +rewarded reward +rewarding reward +rewards reward +rewashed rewash +rex rex +rexes rex +rhapsody rhapsodi +rhea rhea +rheims rheim +rhetoric rhetor +rheumatic rheumat +rheumatics rheumat +rheumatism rheumat +rhine rhine +rhinoceros rhinocero +rhinoceroses rhinoceros +rhododendron rhododendron +rhododendrons rhododendron +rhubarb rhubarb +rhyme rhyme +rhymes rhyme +rhynchops rhynchop +rhyncophora rhyncophora +rhythmically rhythmic +ri ri +rib rib +ribbed rib +ribbentrop ribbentrop +ribbon ribbon +ribbons ribbon +ribeira ribeira +ribs rib +rice rice +rich rich +richard richard +richardson richardson +richer richer +riches rich +richest richest +richly rich +richmond richmond +richness rich +rick rick +rickety ricketi +rickworth rickworth +rid rid +riddance riddanc +ridden ridden +ridding rid +riddle riddl +riddles riddl +ride ride +ridendus ridendus +rider rider +riders rider +rides ride +ridg ridg +ridge ridg +ridges ridg +ridicule ridicul +ridiculed ridicul +ridiculous ridicul +ridiculously ridicul +riding ride +ridinghood ridinghood +rife rife +riff riff +rifle rifl +rifles rifl +rifling rifl +rig rig +rigamarole rigamarol +riggers rigger +rigging rig +right right +righted right +righteous righteous +righteousness righteous +rightly right +rights right +rigid rigid +rigidity rigid +rigidly rigid +rigorous rigor +rigour rigour +rigueur rigueur +rill rill +rim rim +rims rim +rimsky rimski +rincon rincon +ring ring +ringed ring +ringer ringer +ringing ring +ringleaders ringlead +ringlets ringlet +rings ring +rinse rins +rinsing rins +rio rio +rios rio +riot riot +riotous riotous +rip rip +ripe ripe +ripen ripen +ripened ripen +ripening ripen +ripens ripen +ripped rip +ripple rippl +rippled rippl +ripples rippl +rippling rippl +rise rise +risen risen +risers riser +rises rise +risible risibl +risin risin +rising rise +risingham risingham +risk risk +risked risk +risking risk +risks risk +risky riski +rite rite +rites rite +rival rival +rivalled rival +rivalry rivalri +rivals rival +rivalship rivalship +rive rive +river river +rivers river +rivet rivet +riveted rivet +riveting rivet +rivetted rivet +riviere rivier +rivoli rivoli +rivulet rivulet +rivulets rivulet +ro ro +road road +roads road +roadside roadsid +roam roam +roamed roam +roaming roam +roams roam +roan roan +roar roar +roared roar +roarer roarer +roaring roar +roast roast +roasted roast +roasting roast +rob rob +robbed rob +robber robber +robberies robberi +robbers robber +robbery robberi +robbing rob +robe robe +robed robe +robert robert +roberto roberto +robes robe +robin robin +robing robe +robinson robinson +robs rob +robust robust +robustly robust +robustus robustus +roby robi +robys robi +rochester rochest +rock rock +rocked rock +rocket rocket +rockets rocket +rocking rock +rocks rock +rocky rocki +rod rod +rode rode +rodent rodent +rodentia rodentia +rodents rodent +rodeo rodeo +rodion rodion +rodionovitch rodionovitch +rods rod +rodya rodya +roe roe +roger roger +rogers roger +rogue rogu +roguery rogueri +rogues rogu +roi roi +rokeby rokebi +role role +roles role +roll roll +rolle roll +rolled roll +roller roller +rollicking rollick +rolling roll +rollings roll +rolls roll +rolor rolor +roman roman +romance romanc +romancing romanc +romanovitch romanovitch +romanovna romanovna +romans roman +romantic romant +romantically romant +rome rome +romeo romeo +romish romish +romp romp +romping romp +roof roof +roofed roof +roofs roof +rooge roog +rook rook +rookery rookeri +rookh rookh +rooks rook +room room +roomed room +roomer roomer +rooms room +roomy roomi +roon roon +roonaway roonaway +roosher roosher +roost roost +roosting roost +root root +rooted root +rooteth rooteth +roots root +rope rope +ropemakers ropemak +ropes rope +rosa rosa +rosary rosari +rosas rosa +rose rose +roseate roseat +rosebud rosebud +roses rose +rosettes rosett +rosewood rosewood +rosina rosina +rosinas rosina +ross ross +rosy rosi +rot rot +rotation rotat +rotatory rotatori +rote rote +rotted rot +rotten rotten +rottenness rotten +rotting rot +rouble roubl +roubles roubl +roue roue +rouge roug +rouged roug +rough rough +roughening roughen +rougher rougher +roughest roughest +roughing rough +roughly rough +roughness rough +roughs rough +roulette roulett +rounceweil rounceweil +rouncewell rouncewel +rouncewells rouncewel +round round +roundabout roundabout +rounde round +rounded round +rounder rounder +roundest roundest +rounding round +roundly round +roundness round +rounds round +rouse rous +roused rous +rousing rous +rousseau rousseau +rout rout +route rout +routed rout +routes rout +routine routin +rover rover +roving rove +row row +rowed row +rowel rowel +rowing row +rowland rowland +rowling rowl +rows row +roy roy +royal royal +royalists royalist +royalty royalti +roystering royster +royston royston +rozario rozario +rt rt +ruat ruat +rub rub +rubbed rub +rubber rubber +rubbers rubber +rubbing rub +rubbish rubbish +rubbishing rubbish +rubbishly rubbish +rubecula rubecula +rubicund rubicund +rubies rubi +rubinstein rubinstein +rubrum rubrum +rubs rub +ruby rubi +ruck ruck +ruddier ruddier +ruddle ruddl +ruddy ruddi +rude rude +rudely rude +rudeness rude +ruder ruder +rudest rudest +rudimentary rudimentari +rudiments rudiment +rue rue +rueful rueful +ruefully ruefulli +ruff ruff +ruffian ruffian +ruffianly ruffian +ruffians ruffian +ruffle ruffl +ruffled ruffl +rug rug +rugged rug +rugs rug +ruin ruin +ruinas ruina +ruined ruin +ruining ruin +ruinous ruinous +ruins ruin +rule rule +ruled rule +ruler ruler +rulers ruler +rules rule +ruling rule +rum rum +rumble rumbl +rumbled rumbl +rumbling rumbl +rumicivorus rumicivorus +ruminant rumin +ruminants rumin +ruminate rumin +ruminated rumin +ruminates rumin +ruminating rumin +ruminations rumin +rummage rummag +rummaged rummag +rummaging rummag +rummest rummest +rummiest rummiest +rummy rummi +rumour rumour +rumoured rumour +rumours rumour +rumpling rumpl +rums rum +run run +runaway runaway +runaways runaway +rung rung +running run +runs run +rupture ruptur +ruptured ruptur +rural rural +rush rush +rushed rush +rushes rush +rushing rush +rushlight rushlight +russell russel +russet russet +russia russia +russian russian +russians russian +rust rust +rusted rust +rustic rustic +rusticated rustic +rusticities rustic +rustily rustili +rusting rust +rustle rustl +rustled rustl +rustling rustl +rusty rusti +rut rut +ruthlessly ruthless +ry ry +ryazan ryazan +ryde ryde +rylstone rylston +s s +sa sa +sabbatarian sabbatarian +sabbath sabbath +sabe sabe +sabine sabin +sable sabl +sabre sabr +sabres sabr +sac sac +sachet sachet +sack sack +sackcloth sackcloth +sackcloths sackcloth +sacked sack +sacking sack +sacks sack +sacrament sacrament +sacramiento sacramiento +sacred sacr +sacredly sacr +sacrifice sacrific +sacrificed sacrif +sacrifices sacrific +sacrificing sacrif +sacrilege sacrileg +sad sad +saddened sadden +saddening sadden +saddle saddl +saddled saddl +saddler saddler +saddling saddl +sadly sad +sadness sad +sadovy sadovi +saeugethiere saeugethier +safe safe +safeguard safeguard +safeguards safeguard +safely safe +safer safer +safes safe +safest safest +safety safeti +saffron saffron +sagacious sagaci +sagacity sagac +sage sage +sago sago +said said +sail sail +sailed sail +sailing sail +sailor sailor +sailors sailor +sails sail +saint saint +sainted saint +saintly saint +saints saint +saisis saisi +sait sait +saith saith +sak sak +sake sake +sakes sake +sal sal +sala sala +saladillo saladillo +salado salado +salaried salari +salary salari +sald sald +sale sale +salesman salesman +saliferous salifer +salina salina +salinas salina +saline salin +salinus salinus +salitral salitr +salitrales salitral +saliva saliva +sallied salli +sallies salli +sallow sallow +sally salli +sallys salli +salmon salmon +salon salon +saloon saloon +saloons saloon +salt salt +salta salta +salted salt +saltenfiord saltenfiord +salting salt +saltire saltir +saltpeter saltpet +saltpetre saltpetr +salts salt +salubrity salubr +salutary salutari +salutation salut +salutations salut +salute salut +saluted salut +salutes salut +saluting salut +salvador salvador +salvation salvat +salvator salvat +salver salver +sam sam +samaritan samaritan +same same +sameness same +samovar samovar +samovars samovar +sampler sampler +samples sampl +samson samson +san san +sancho sancho +sanctified sanctifi +sanction sanction +sanctions sanction +sanctity sanctiti +sanctuary sanctuari +sanctum sanctum +sand sand +sandal sandal +sandaled sandal +sandalled sandal +sandals sandal +sanded sand +sandpiper sandpip +sands sand +sandstone sandston +sandstones sandston +sandwich sandwich +sandwiches sandwich +sandy sandi +sane sane +sang sang +sanger sanger +sangsby sangsbi +sanguinary sanguinari +sanguine sanguin +saniem saniem +sanity saniti +sank sank +sant sant +santa santa +santiago santiago +sap sap +sapient sapient +sapling sapl +sapped sap +sapphire sapphir +sapphires sapphir +sar sar +saracen saracen +saracenic saracen +saracens saracen +sarah sarah +sarandis sarandi +sarcasm sarcasm +sarcastic sarcast +sarcastically sarcast +sarcophagus sarcophagus +sarmiento sarmiento +sart sart +sash sash +sashed sash +sasiated sasiat +sassafras sassafra +sat sat +satan satan +sated sate +satellite satellit +satellites satellit +satin satin +satins satin +satire satir +satirical satir +satirically satir +satisfaction satisfact +satisfactorily satisfactorili +satisfactory satisfactori +satisfied satisfi +satisfies satisfi +satisfy satisfi +satisfying satisfi +satrap satrap +satraps satrap +saturated satur +saturation satur +saturday saturday +saturdays saturday +saturnine saturnin +satyr satyr +sauce sauc +saucepan saucepan +saucepans saucepan +saucer saucer +saucers saucer +saucily saucili +saucy sauci +saul saul +saunter saunter +sauntered saunter +saunterer saunter +sauntering saunter +saunters saunter +saurophagus saurophagus +sausage sausag +sausages sausag +sauvages sauvag +savage savag +savagely savag +savages savag +savana savana +savannahs savannah +save save +saved save +saves save +saving save +savings save +saviour saviour +savoir savoir +savour savour +savoured savour +savouries savouri +savours savour +savoury savouri +saw saw +sawdust sawdust +saws saw +sawyer sawyer +saxon saxon +say say +saying say +sayings say +says say +scabra scabra +scabs scab +scaffold scaffold +scaffolding scaffold +scaffolds scaffold +scagliola scagliola +scald scald +scalded scald +scalding scald +scale scale +scaled scale +scales scale +scalesia scalesia +scaley scaley +scaling scale +scallops scallop +scalping scalp +scaly scali +scamander scamand +scamp scamp +scamper scamper +scampered scamper +scamps scamp +scan scan +scandal scandal +scandalising scandalis +scandalized scandal +scandalizing scandal +scandalous scandal +scandals scandal +scanned scan +scanning scan +scant scant +scantier scantier +scantiest scantiest +scantily scantili +scantiness scanti +scanty scanti +scape scape +scapegoat scapegoat +scapegrace scapegrac +scar scar +scarabaeus scarabaeus +scarce scarc +scarcel scarcel +scarcely scarc +scarcer scarcer +scarcity scarciti +scare scare +scarecrow scarecrow +scarecrows scarecrow +scared scare +scarf scarf +scarfs scarf +scarlet scarlet +scarred scar +scars scar +scarum scarum +scarus scarus +scatter scatter +scattered scatter +scattering scatter +scavengers scaveng +scelidotherium scelidotherium +scene scene +scenery sceneri +scenes scene +scent scent +scented scent +scentless scentless +scents scent +sceptic sceptic +sceptical sceptic +sceptics sceptic +schedule schedul +schegolskoy schegolskoy +scheme scheme +schemer schemer +schemes scheme +scheming scheme +schiller schiller +schilleresque schilleresqu +schirdel schirdel +schleswig schleswig +scholar scholar +scholarly scholar +scholars scholar +scholarship scholarship +scholastic scholast +schone schone +schonsten schonsten +school school +schoolboy schoolboy +schooldays schoolday +schooled school +schoolfellow schoolfellow +schoolfellows schoolfellow +schooling school +schoolmaster schoolmast +schoolmasters schoolmast +schoolmate schoolmat +schoolmeasther schoolmeasth +schoolroom schoolroom +schools school +schooner schooner +schwach schwach +scienc scienc +science scienc +sciences scienc +scientific scientif +scimitar scimitar +scintillate scintil +scintillation scintil +scions scion +scissor scissor +scissors scissor +sclater sclater +scoff scoff +scoffed scof +scoffers scoffer +scold scold +scolded scold +scolding scold +scolds scold +scoondrel scoondrel +scoondrels scoondrel +scoop scoop +scooped scoop +scooping scoop +scoops scoop +scope scope +scorch scorch +scorched scorch +scorches scorch +scorching scorch +scorchingly scorch +score score +scored score +scores score +scoresby scoresbi +scoriaceous scoriac +scoriae scoria +scorn scorn +scorned scorn +scornful scorn +scornfully scorn +scorning scorn +scorns scorn +scorpion scorpion +scorpions scorpion +scot scot +scotch scotch +scotched scotch +scotland scotland +scott scott +scoundrel scoundrel +scoundrelly scoundrelli +scoundrels scoundrel +scour scour +scoured scour +scourge scourg +scourges scourg +scouring scour +scours scour +scout scout +scouted scout +scouts scout +scowl scowl +scowled scowl +scowling scowl +scowls scowl +scramble scrambl +scrambled scrambl +scrambling scrambl +scrap scrap +scrapbook scrapbook +scrape scrape +scraped scrape +scraper scraper +scrapes scrape +scraping scrape +scraps scrap +scratch scratch +scratched scratch +scratches scratch +scratching scratch +scrawl scrawl +scrawled scrawl +scrawls scrawl +scream scream +screamed scream +screaming scream +screams scream +screeched screech +screeches screech +screeching screech +screen screen +screened screen +screening screen +screens screen +screw screw +screwdriver screwdriv +screwdrivers screwdriv +screwed screw +screwing screw +screws screw +scribble scribbl +scribbled scribbl +scribe scribe +scrip scrip +scripter scripter +scriptural scriptur +scripture scriptur +scrivener scriven +scrofulous scroful +scrolls scroll +scrope scrope +scrub scrub +scrubbed scrub +scrubbing scrub +scrubbs scrubb +scrubby scrubbi +scrubs scrub +scruple scrupl +scruples scrupl +scrupulous scrupul +scrupulously scrupul +scrutinise scrutinis +scrutinised scrutinis +scrutinising scrutinis +scrutinizing scrutin +scrutiny scrutini +scudded scud +scuffle scuffl +scuffling scuffl +scullery sculleri +scullions scullion +sculptor sculptor +sculptured sculptur +sculptures sculptur +scum scum +scurvy scurvi +scuttle scuttl +scuttling scuttl +scytalopus scytalopus +se se +sea sea +seacoast seacoast +seafowl seafowl +seal seal +sealed seal +sealer sealer +sealers sealer +sealing seal +seals seal +seaman seaman +seame seam +seamed seam +seamen seamen +seams seam +seaport seaport +sear sear +search search +searched search +searches search +searching search +seas sea +seashells seashel +seaside seasid +season season +seasoned season +seasons season +seat seat +seated seat +seating seat +seats seat +seaward seaward +seawards seaward +seaweed seawe +secede seced +secession secess +seclude seclud +secluded seclud +seclusion seclus +seco seco +second second +secondary secondari +seconded second +secondly second +seconds second +secrecy secreci +secret secret +secretaries secretari +secretary secretari +secretaryship secretaryship +secretaryships secretaryship +secrete secret +secreted secret +secretes secret +secreting secret +secretion secret +secretly secret +secrets secret +sect sect +sectio sectio +section section +sections section +secular secular +secure secur +secured secur +securely secur +secures secur +securing secur +securities secur +security secur +sed sed +sedate sedat +sedately sedat +sedateness sedat +sedative sedat +sedentary sedentari +sedes sede +sedge sedg +sediment sediment +sedimentary sedimentari +sediments sediment +sedley sedley +seduced seduc +seducer seduc +seductive seduct +seductively seduct +sedulous sedul +sedulously sedul +see see +seed seed +seeds seed +seeing see +seek seek +seeker seeker +seekers seeker +seeking seek +seeks seek +seem seem +seeme seem +seemed seem +seeming seem +seemingly seem +seems seem +seen seen +sees see +seetzen seetzen +segment segment +segments segment +sehr sehr +sein sein +seize seiz +seized seiz +seizes seiz +seizing seiz +seizure seizur +seldom seldom +select select +selected select +selecting select +selection select +selections select +self self +selfish selfish +selfishness selfish +sell sell +seller seller +sellers seller +selling sell +sellings sell +sells sell +selves selv +semblance semblanc +semblances semblanc +semi semi +semicircle semicircl +semicircular semicircular +seminal semin +seminarists seminarist +semyon semyon +semyonova semyonova +semyonovitch semyonovitch +semyonovna semyonovna +semyonovsky semyonovski +senate senat +senator senat +senatorial senatori +senators senat +send send +sender sender +sending send +sends send +senhor senhor +senile senil +senior senior +seniority senior +seniors senior +senor senor +senoritas senorita +sensation sensat +sensational sensat +sensations sensat +sense sens +senseless senseless +senses sens +sensibilities sensibl +sensibility sensibl +sensible sensibl +sensibly sensibl +sensitive sensit +sensitiveness sensit +sensual sensual +sensualist sensualist +sensuality sensual +sent sent +sentence sentenc +sentenced sentenc +sentences sentenc +sententiously sententi +sentiment sentiment +sentimental sentiment +sentimentalism sentiment +sentimentality sentiment +sentimentally sentiment +sentiments sentiment +sentinel sentinel +sentinels sentinel +sentries sentri +sentry sentri +separate separ +separated separ +separately separ +separates separ +separating separ +separation separ +sept sept +septa septa +september septemb +septuagenarian septuagenarian +septum septum +sepulchral sepulchr +sepulchre sepulchr +sepultus sepultus +sequel sequel +sequence sequenc +sequestered sequest +ser ser +seraph seraph +seraphically seraph +seraphim seraphim +serces serc +serenades serenad +serene seren +serenely seren +serenity seren +serf serf +serfdom serfdom +serfs serf +sergeant sergeant +seriatim seriatim +series seri +serio serio +serious serious +seriously serious +seriousness serious +serjeant serjeant +serjeants serjeant +sermon sermon +sermonizing sermon +serpent serpent +serpentine serpentin +serpents serpent +serpulae serpula +serrated serrat +sertularia sertularia +servant servant +servants servant +serve serv +served serv +server server +serves serv +service servic +serviceable servic +serviceably servic +services servic +servile servil +servility servil +serving serv +servitor servitor +servitude servitud +servts servt +ses ses +session session +sessions session +set set +sets set +setten setten +setting set +settle settl +settled settl +settlement settlement +settlements settlement +settler settler +settlers settler +settles settl +settling settl +seul seul +sevastopol sevastopol +seven seven +sevenpence sevenp +sevens seven +seventeen seventeen +seventeenth seventeenth +seventh seventh +seventhly seventh +seventy seventi +seventysix seventysix +sever sever +severa severa +several sever +severally sever +severe sever +severed sever +severely sever +severer sever +severest severest +severity sever +severn severn +sevres sevr +sew sew +sewed sew +sewerage sewerag +sewerely sewer +sewing sew +sex sex +sexes sex +sexton sexton +sextus sextus +sexty sexti +seychelle seychell +seychelles seychell +sh sh +sha sha +shabbily shabbili +shabbiness shabbi +shabby shabbi +shade shade +shaded shade +shades shade +shading shade +shadow shadow +shadowed shadow +shadowless shadowless +shadows shadow +shadowy shadowi +shady shadi +shaft shaft +shafts shaft +shaggy shaggi +shak shak +shake shake +shaken shaken +shakes shake +shakespeare shakespear +shaking shake +shakings shake +shakspeare shakspear +shal shal +shall shall +shallow shallow +shallowest shallowest +shallows shallow +shalt shalt +sham sham +shambled shambl +shambles shambl +shambling shambl +shame shame +shamed shame +shamefaced shamefac +shameful shame +shamefully shame +shameless shameless +shamelessly shameless +shamming sham +shan shan +shanks shank +shanties shanti +shape shape +shaped shape +shapeless shapeless +shapely shape +shapes shape +shaping shape +shar shar +share share +shared share +shareholder sharehold +shareholders sharehold +sharer sharer +shares share +sharing share +shark shark +sharking shark +sharks shark +sharmer sharmer +sharp sharp +sharpen sharpen +sharpened sharpen +sharpening sharpen +sharpens sharpen +sharper sharper +sharpers sharper +sharpest sharpest +sharply sharpli +sharpness sharp +sharpshooters sharpshoot +shattered shatter +shave shave +shaved shave +shaven shaven +shaver shaver +shaves shave +shaving shave +shaw shaw +shawl shawl +shawls shawl +she she +sheake sheak +sheame sheam +shearing shear +sheath sheath +sheaves sheav +shed shed +shedding shed +sheds shed +sheen sheen +sheep sheep +sheepish sheepish +sheepskin sheepskin +sheer sheer +sheet sheet +sheets sheet +sheik sheik +shelf shelf +shell shell +shelley shelley +shellfish shellfish +shellfuls shell +shells shell +shelly shelli +shelopaev shelopaev +shelter shelter +sheltered shelter +sheltering shelter +shelters shelter +shelves shelv +shelving shelv +shepherd shepherd +shepherdess shepherdess +shepherdesses shepherdess +shepherds shepherd +sheriff sheriff +sherry sherri +shetland shetland +shh shh +shibboleth shibboleth +shied shi +shield shield +shielded shield +shielding shield +shields shield +shies shi +shift shift +shifted shift +shifting shift +shiftings shift +shifts shift +shil shil +shilling shill +shillings shill +shin shin +shine shine +shines shine +shingle shingl +shining shine +shiny shini +ship ship +shipbuilder shipbuild +shiploads shipload +shipped ship +shipping ship +ships ship +shipton shipton +shipwreck shipwreck +shipwrecked shipwreck +shipwrecks shipwreck +shire shire +shirk shirk +shirked shirk +shirking shirk +shirt shirt +shirts shirt +shiver shiver +shivered shiver +shivering shiver +shivers shiver +shoal shoal +shoaler shoaler +shoalness shoal +shoals shoal +shock shock +shocked shock +shocking shock +shockingly shock +shocks shock +shod shod +shoe shoe +shoed sho +shoeless shoeless +shoemaker shoemak +shoemakers shoemak +shoes shoe +shone shone +shongi shongi +shoohoo shoohoo +shook shook +shoon shoon +shoot shoot +shooters shooter +shooting shoot +shoots shoot +shop shop +shopkeeper shopkeep +shopkeepers shopkeep +shopman shopman +shopmen shopmen +shopofwomen shopofwomen +shops shop +shore shore +shoreham shoreham +shores shore +shorn shorn +short short +shortcoming shortcom +shortcomings shortcom +shorten shorten +shortened shorten +shortening shorten +shortens shorten +shorter shorter +shortest shortest +shortly short +shortness short +shorts short +shot shot +shots shot +should should +shoulder shoulder +shouldered shoulder +shouldering shoulder +shoulders shoulder +shouldest shouldest +shouldn shouldn +shouldst shouldst +shout shout +shouted shout +shouting shout +shouts shout +shove shove +shoved shove +shovel shovel +shoving shove +show show +showd showd +showed show +shower shower +showered shower +showering shower +showers shower +showery showeri +showing show +shown shown +shows show +showy showi +shrank shrank +shreds shred +shrew shrew +shrewd shrewd +shrewdly shrewd +shrewdness shrewd +shriek shriek +shrieked shriek +shrieking shriek +shrieks shriek +shrikes shrike +shrill shrill +shrillest shrillest +shrillness shrill +shrilly shrilli +shrimp shrimp +shrimps shrimp +shrine shrine +shrink shrink +shrinking shrink +shrinks shrink +shrivel shrivel +shrivelled shrivel +shropshire shropshir +shroud shroud +shrouded shroud +shrub shrub +shrubberies shrubberi +shrubbery shrubberi +shrubs shrub +shrug shrug +shrugged shrug +shrugging shrug +shrugs shrug +shrunk shrunk +shrunken shrunken +shudder shudder +shuddered shudder +shuddering shudder +shudders shudder +shuffle shuffl +shuffled shuffl +shufflers shuffler +shuffles shuffl +shuffling shuffl +shufflings shuffl +shuflle shufll +shun shun +shunned shun +shunning shun +shut shut +shuts shut +shutter shutter +shutters shutter +shutting shut +shy shi +shyer shyer +shyest shyest +shylock shylock +shyly shyli +shyness shyness +si si +siamese siames +siberia siberia +siberian siberian +sich sich +sick sick +sickened sicken +sickening sicken +sickens sicken +sickliness sickli +sickly sick +sickness sick +side side +sideboard sideboard +sided side +sidelong sidelong +sides side +sideway sideway +sideways sideway +sidewise sidewis +sidings side +sidle sidl +sidled sidl +sidles sidl +sidling sidl +siege sieg +sierra sierra +sieve siev +sift sift +sifter sifter +sigh sigh +sighed sigh +sighing sigh +sighs sigh +sight sight +sighted sight +sightedness sighted +sightless sightless +sights sight +sightseer sightseer +sign sign +signal signal +signalised signalis +signalize signal +signalling signal +signally signal +signals signal +signature signatur +signatures signatur +signed sign +significance signific +significancy signific +significant signific +significantly signific +signification signif +signified signifi +signifies signifi +signifieth signifieth +signify signifi +signifying signifi +signing sign +signoritas signorita +signs sign +sike sike +silence silenc +silenced silenc +silencing silenc +silent silent +silently silent +silex silex +siliceous silic +silicified silicifi +silk silk +silken silken +silkiness silki +silks silk +silkworm silkworm +silky silki +sill sill +sillier sillier +sillies silli +silliest silliest +silliman silliman +silliness silli +sills sill +silly silli +silurian silurian +silurus silurus +silver silver +silverbridge silverbridg +silvered silver +silversmith silversmith +silvery silveri +silworth silworth +similar similar +similarity similar +similarly similar +simile simil +similes simil +similitude similitud +simmering simmer +simmonds simmond +simper simper +simpered simper +simpering simper +simple simpl +simpler simpler +simplest simplest +simpleton simpleton +simpletons simpleton +simplex simplex +simplicity simplic +simplified simplifi +simplon simplon +simply simpli +simpson simpson +simul simul +simultaneous simultan +simultaneously simultan +sin sin +sinai sinai +sinbad sinbad +since sinc +sincere sincer +sincerely sincer +sincerest sincerest +sincerity sincer +sinecure sinecur +sinew sinew +sinews sinew +sinewy sinewi +sinful sin +sinfulness sin +sing sing +singapore singapor +singed sing +singeing sing +singer singer +singers singer +singing sing +single singl +singleness singl +singling singl +singly singl +sings sing +singula singula +singular singular +singularities singular +singularity singular +singularly singular +sinister sinist +sink sink +sinking sink +sinks sink +sinless sinless +sinlessly sinless +sinned sin +sinner sinner +sinners sinner +sinning sin +sins sin +sinuous sinuous +sip sip +siphon siphon +sipped sip +sipping sip +sips sip +sir sir +sire sire +siren siren +sirocco sirocco +sirrah sirrah +sister sister +sisterhood sisterhood +sisterly sister +sisters sister +sistine sistin +sit sit +site site +sites site +sitiwation sitiw +sitiwations sitiw +sits sit +sitter sitter +sitters sitter +sittin sittin +sitting sit +sittings sit +situ situ +situate situat +situated situat +situation situat +situations situat +siunmerson siunmerson +sivatherium sivatherium +six six +sixes six +sixieme sixiem +sixpen sixpen +sixpence sixpenc +sixpences sixpenc +sixpenny sixpenni +sixteen sixteen +sixteenth sixteenth +sixth sixth +sixthly sixth +sixty sixti +size size +sized size +sizes size +skampling skampl +skate skate +skaters skater +skating skate +skeen skeen +skein skein +skeleto skeleto +skeleton skeleton +skeletons skeleton +sketch sketch +sketched sketch +sketches sketch +sketchily sketchili +sketching sketch +skewer skewer +skiddaw skiddaw +skies sky +skilful skil +skilfully skil +skilfulness skil +skill skill +skilled skill +skilly skilli +skim skim +skimmed skim +skimming skim +skimpole skimpol +skims skim +skin skin +skinned skin +skinning skin +skinny skinni +skins skin +skip skip +skipped skip +skipper skipper +skipping skip +skips skip +skirmish skirmish +skirmished skirmish +skirmishes skirmish +skirmishing skirmish +skirt skirt +skirted skirt +skirts skirt +skittish skittish +skittle skittl +skittles skittl +skrimmage skrimmag +skul skul +skulk skulk +skulking skulk +skulks skulk +skull skull +skulls skull +skumpling skumpl +skunks skunk +skurry skurri +skuttle skuttl +sky sky +skye skye +skylark skylark +skylight skylight +skylights skylight +slab slab +slabs slab +slack slack +slacken slacken +slackened slacken +slackness slack +sladdery sladderi +slags slag +slain slain +slaked slake +slam slam +slammed slam +slammons slammon +slander slander +slandered slander +slanderer slander +slanderers slander +slandering slander +slang slang +slangular slangular +slanting slant +slap slap +slapped slap +slapping slap +slaps slap +slash slash +slashing slash +slat slat +slate slate +slatternly slattern +slaughter slaughter +slaughtered slaughter +slaughtering slaughter +slaughterous slaughter +slave slave +slaved slave +slavery slaveri +slaves slave +slavish slavish +slavishly slavish +slay slay +sledge sledg +sleek sleek +sleep sleep +sleeper sleeper +sleepers sleeper +sleepily sleepili +sleepiness sleepi +sleeping sleep +sleepless sleepless +sleeps sleep +sleepy sleepi +sleet sleet +sleeve sleev +sleeved sleev +sleeves sleev +sleight sleight +slender slender +slenderer slender +slenderly slender +slep slep +slept slept +slice slice +sliced slice +slices slice +slicing slice +slid slid +slide slide +slider slider +sliders slider +sliderskew sliderskew +slides slide +sliding slide +slight slight +slighted slight +slighter slighter +slightest slightest +slighting slight +slightly slight +slights slight +slim slim +slime slime +slimy slimi +sling sling +slings sling +slinking slink +slip slip +slipped slip +slipper slipper +slippered slipper +slippers slipper +slippery slipperi +slipping slip +slips slip +slipshod slipshod +slit slit +slits slit +sloane sloan +slocomb slocomb +slongs slong +slope slope +sloped slope +slopes slope +sloping slope +sloppy sloppi +slopseller slopsel +sloth sloth +sloths sloth +slouch slouch +slouching slouch +sloven sloven +slovenly sloven +slow slow +slower slower +slowly slowli +slowness slow +sludge sludg +slug slug +sluggish sluggish +slugs slug +sluices sluic +slumber slumber +slumbered slumber +slumbering slumber +slumbers slumber +slung slung +slunk slunk +slurring slur +slush slush +slut slut +sly sli +slyboots slyboot +slyly slyli +slyness slyness +smack smack +smacked smack +smacking smack +smacks smack +smal smal +small small +smallclothes smallcloth +smaller smaller +smallest smallest +smallness small +smalls small +smallweed smallwe +smallweeds smallwe +smallweedy smallweedi +smart smart +smartened smarten +smarting smart +smartly smart +smartness smart +smartnesses smart +smarts smart +smash smash +smashed smash +smashing smash +smattering smatter +smear smear +smeared smear +smearing smear +smears smear +smell smell +smelling smell +smells smell +smelt smelt +smelted smelt +smelting smelt +smiffeld smiffeld +smifligate smiflig +smifligation smiflig +smifser smifser +smike smike +smile smile +smiled smile +smiles smile +smilin smilin +smiling smile +smilingly smile +smirched smirch +smirk smirk +smirking smirk +smith smith +smithers smither +smithfield smithfield +smithson smithson +smiting smite +smitten smitten +smock smock +smoke smoke +smoked smoke +smoker smoker +smokes smoke +smoking smoke +smokings smoke +smoky smoki +smoldering smolder +smooth smooth +smoothed smooth +smoother smoother +smoothing smooth +smoothingly smooth +smoothings smooth +smoothly smooth +smoothness smooth +smooths smooth +smote smote +smothered smother +smothering smother +smothers smother +smouldering smoulder +smuggle smuggl +smuggler smuggler +smut smut +smutty smutti +snagsby snagsbi +snail snail +snails snail +snake snake +snakes snake +snap snap +snapped snap +snapper snapper +snapping snap +snappish snappish +snappishly snappish +snaps snap +snare snare +snares snare +snarl snarl +snarled snarl +snarling snarl +snarls snarl +snatch snatch +snatched snatch +snatches snatch +snatching snatch +snawley snawley +sneak sneak +sneaked sneak +sneaking sneak +sneaks sneak +sneer sneer +sneered sneer +sneering sneer +sneers sneer +sneeze sneez +sneezed sneez +sneezing sneez +snevellicci snevellicci +snewkes snewk +sniff sniff +sniffed snif +sniffing snif +sniffs sniff +snigger snigger +sniggered snigger +sniggering snigger +snipe snipe +snipping snip +snittle snittl +snobb snobb +snoog snoog +snooks snook +snore snore +snores snore +snoring snore +snort snort +snorted snort +snorting snort +snorts snort +snout snout +snow snow +snowed snow +snowflakes snowflak +snowing snow +snowstorm snowstorm +snowstorms snowstorm +snowy snowi +snub snub +snubbed snub +snubbing snub +snubs snub +snuff snuff +snuffed snuf +snuffers snuffer +snuffim snuffim +snuffing snuf +snuffling snuffl +snuffy snuffi +snug snug +snugly snug +so so +soaked soak +soaking soak +soap soap +soar soar +soared soar +soaring soar +soars soar +sob sob +sobbed sob +sobbing sob +sobbings sob +sober sober +sobered sober +sobering sober +soberly sober +sobre sobr +sobriety sobrieti +sobs sob +soc soc +socego socego +sociable sociabl +social social +socialist socialist +socialists socialist +sociality social +socially social +society societi +sock sock +socket socket +sockets socket +socks sock +soda soda +sodden sodden +soever soever +sofa sofa +sofas sofa +soft soft +soften soften +softened soften +softeners soften +softening soften +softens soften +softer softer +softest softest +softly soft +softness soft +sofy sofi +sofya sofya +soho soho +soie soie +soight soight +soil soil +soiled soil +soiree soire +soirees soire +soizable soizabl +soizes soiz +sojourn sojourn +sojourners sojourn +sojourning sojourn +sol sol +solace solac +solaced solac +solaces solac +solacing solac +solander soland +solar solar +sold sold +soldier soldier +soldiering soldier +soldierly soldier +soldiers soldier +sole sole +solecisms solec +solely sole +solemn solemn +solemnest solemnest +solemnities solemn +solemnity solemn +solemnly solemn +solen solen +solent solent +soles sole +solicitation solicit +solicitations solicit +solicited solicit +soliciting solicit +solicitor solicitor +solicitors solicitor +solicitous solicit +solicitously solicit +solicits solicit +solicitude solicitud +solid solid +solidified solidifi +solidities solid +solidity solid +solidness solid +soliloquies soliloqui +soliloquised soliloquis +soliloquize soliloqu +soliloquized soliloqu +soliloquy soliloquy +solitaries solitari +solitary solitari +solitude solitud +solitudes solitud +solo solo +solomon solomon +solon solon +solstice solstic +soluble solubl +solution solut +solve solv +solved solv +solvent solvent +solves solv +som som +sombre sombr +sombrero sombrero +some some +somebodies somebodi +somebody somebodi +someday someday +somehow somehow +someone someon +somers somer +something someth +somethings someth +somethink somethink +sometime sometim +sometimes sometim +someway someway +somewhat somewhat +somewhere somewher +somewheres somewher +somewhither somewhith +somnolent somnol +somnum somnum +son son +sondern sondern +sone sone +song song +songs song +sonia sonia +sonnets sonnet +sonorous sonor +sonorously sonor +sonourous sonour +sons son +soobjact soobjact +soodden soodden +sooffer sooffer +soom soom +soomat soomat +soon soon +sooner sooner +soonest soonest +soop soop +sooper sooper +soot soot +sooth sooth +soothe sooth +soothed sooth +soothing sooth +soothingly sooth +sooty sooti +sop sop +sophistry sophistri +soporific soporif +sopped sop +sorcery sorceri +sordid sordid +sore sore +sorely sore +soreness sore +sores sore +sorest sorest +sorrel sorrel +sorrow sorrow +sorrowful sorrow +sorrowfully sorrow +sorrowing sorrow +sorrows sorrow +sorry sorri +sort sort +sorted sort +sorting sort +sorts sort +sotto sotto +sought sought +soul soul +souled soul +souls soul +soun soun +sound sound +sounded sound +sounder sounder +sounding sound +soundings sound +soundly sound +soundness sound +sounds sound +soup soup +sour sour +source sourc +sources sourc +soured sour +souring sour +sourly sour +sous sous +soused sous +sousing sous +sout sout +south south +southampton southampton +southerly souther +southern southern +southfront southfront +southward southward +southwards southward +southwestern southwestern +sov sov +sovereign sovereign +sovereignest sovereignest +sovereigns sovereign +sovereignty sovereignti +sow sow +sowed sow +sowerby sowerbi +sowing sow +sown sown +sows sow +space space +spaces space +spacious spacious +spade spade +spain spain +spak spak +spake spake +spaletro spaletro +span span +spangled spangl +spaniard spaniard +spaniards spaniard +spaniels spaniel +spanish spanish +spanned span +spar spar +spare spare +spared spare +spares spare +sparing spare +sparingly spare +spark spark +sparking spark +sparkle sparkl +sparkled sparkl +sparklers sparkler +sparkles sparkl +sparkling sparkl +sparks spark +sparring spar +sparrow sparrow +sparrows sparrow +spartan spartan +spasm spasm +spasmodic spasmod +spasmodically spasmod +spasms spasm +spat spat +spattered spatter +spawn spawn +speak speak +speaker speaker +speaketh speaketh +speakin speakin +speaking speak +speaks speak +spear spear +spearhead spearhead +spearing spear +spears spear +spec spec +special special +specialist specialist +speciality special +specially special +specialty specialti +species speci +specific specif +specifically specif +specified specifi +specify specifi +specimen specimen +specimens specimen +specious specious +speck speck +speckelation speckel +speckled speckl +specks speck +spectacle spectacl +spectacled spectacl +spectacles spectacl +spectator spectat +spectators spectat +spectral spectral +spectre spectr +speculate specul +speculated specul +speculates specul +speculating specul +speculation specul +speculations specul +speculative specul +speculator specul +speculators specul +sped sped +speech speech +speeches speech +speechifying speechifi +speechless speechless +speechlessly speechless +speed speed +speediest speediest +speedily speedili +speedy speedi +spell spell +spelling spell +spells spell +spelt spelt +spence spenc +spencer spencer +spend spend +spending spend +spends spend +spendthrift spendthrift +spent spent +spermaceti spermaceti +sphere sphere +spheres sphere +spherical spheric +sphex sphex +sphinx sphinx +sphinxes sphinx +spice spice +spick spick +spicula spicula +spicy spici +spider spider +spiders spider +spied spi +spies spi +spigwiffin spigwiffin +spiked spike +spikes spike +spileing spile +spill spill +spilled spill +spilling spill +spilt spilt +spin spin +spinach spinach +spinal spinal +spindle spindl +spine spine +spines spine +spinners spinner +spinnies spinni +spinning spin +spinster spinster +spiny spini +spiral spiral +spirally spiral +spire spire +spires spire +spirit spirit +spirited spirit +spiritless spiritless +spirits spirit +spiritual spiritu +spirituous spiritu +spirt spirt +spirted spirt +spit spit +spite spite +spiteful spite +spitefully spite +spitefulness spite +spithead spithead +spits spit +spitting spit +spittoon spittoon +spittoons spittoon +spitzbergen spitzbergen +splash splash +splashed splash +splashes splash +splashin splashin +splashing splash +spleen spleen +splendid splendid +splendidly splendid +splendour splendour +splendours splendour +splenetic splenet +splinter splinter +split split +splitting split +sploiced sploic +splutter splutter +spluttering splutter +spo spo +spoil spoil +spoiled spoil +spoiling spoil +spoils spoil +spoilt spoilt +spoke spoke +spoken spoken +spokesman spokesman +spoliation spoliat +sponge spong +spongey spongey +sponsor sponsor +sponsorial sponsori +sponsors sponsor +spontaneous spontan +spontaneously spontan +spoon spoon +spoonbill spoonbil +spoonful spoon +spoonfuls spoon +spoons spoon +sport sport +sported sport +sporting sport +sportive sportiv +sportiveness sportiv +sports sport +sportsman sportsman +sportsmen sportsmen +sporules sporul +spot spot +spotless spotless +spots spot +spotted spot +spotty spotti +spouse spous +spout spout +spouting spout +spouts spout +spraining sprain +sprang sprang +sprawler sprawler +sprawls sprawl +spray spray +spread spread +spreading spread +spreads spread +spree spree +sprightliness sprightli +sprightly spright +spring spring +springing spring +springs spring +sprinkle sprinkl +sprinkled sprinkl +sprinkling sprinkl +sprite sprite +sprott sprott +sprout sprout +sprouter sprouter +sprouts sprout +spruce spruce +sprucely spruce +sprugeon sprugeon +sprugeons sprugeon +sprung sprung +spun spun +spur spur +spurn spurn +spurned spurn +spurred spur +spurs spur +spy spi +spying spi +squabble squabbl +squabbles squabbl +squabbling squabbl +squabs squab +squalid squalid +squall squall +squallingest squallingest +squalls squall +squally squalli +squalor squalor +squander squander +squandered squander +squandering squander +square squar +squared squar +squarely squar +squarer squarer +squares squar +squaring squar +squashed squash +squat squat +squatted squat +squatters squatter +squatting squat +squeak squeak +squeaked squeak +squeal squeal +squealed squeal +squealing squeal +squeals squeal +squeamishly squeamish +squeamishness squeamish +squeedged squeedg +squeedgin squeedgin +squeer squeer +squeers squeer +squeerses squeers +squeery squeeri +squeeze squeez +squeezed squeez +squeezes squeez +squeezing squeez +squib squib +squint squint +squire squir +squirearchy squirearchi +squires squir +squiress squiress +squirt squirt +squod squod +st st +stab stab +stabbed stab +stabbing stab +stability stabil +stable stabl +stabled stabl +stables stabl +stablewards stableward +stabling stabl +stack stack +stacks stack +staff staff +staffordshire staffordshir +staffs staff +stag stag +stage stage +stagecoach stagecoach +stager stager +stages stage +stagger stagger +staggered stagger +staggering stagger +staggers stagger +stagnant stagnant +stagnating stagnat +stagnation stagnat +stags stag +staid staid +staidness staid +stain stain +stained stain +stains stain +stair stair +staircase staircas +staircases staircas +stairs stair +stake stake +staked stake +stakes stake +staking stake +stalactical stalact +stalactitic stalactit +stale stale +staled stale +stalk stalk +stalked stalk +stalking stalk +stalks stalk +stall stall +stallion stallion +stallions stallion +stalwart stalwart +stamens stamen +stamford stamford +stammer stammer +stammered stammer +stammering stammer +stammers stammer +stamp stamp +stamped stamp +stamping stamp +stamps stamp +stan stan +stanch stanch +stand stand +standaloft standaloft +standard standard +standing stand +stands stand +standstill standstil +stanza stanza +staphylinidae staphylinida +staple stapl +star star +starch starch +starched starch +stare stare +stared stare +stares stare +staring stare +staringly stare +stark stark +starlight starlight +starling starl +starn starn +starred star +starry starri +stars star +start start +starte start +started start +starting start +startings start +startle startl +startled startl +startles startl +startling startl +starts start +starvation starvat +starve starv +starved starv +starvin starvin +starving starv +starwation starwat +state state +statecraft statecraft +stated state +stateliness stateli +stately state +statement statement +statements statement +statenland statenland +states state +statesman statesman +statesmanlike statesmanlik +statesmen statesmen +stating state +station station +stationary stationari +stationed station +stationer station +stationering station +stationers station +stationery stationeri +stations station +statu statu +statuary statuari +statue statu +statues statu +stature statur +status status +statute statut +staunch staunch +staunchly staunch +staunchness staunch +stave stave +staved stave +staves stave +staving stave +stay stay +stayed stay +staying stay +staylace staylac +stays stay +stead stead +steadfast steadfast +steadfastly steadfast +steadfastness steadfast +steadied steadi +steadier steadier +steadily steadili +steadiness steadi +steady steadi +steak steak +steal steal +stealing steal +stealings steal +steals steal +stealth stealth +stealthily stealthili +stealthy stealthi +steam steam +steamboat steamboat +steamboats steamboat +steamed steam +steamer steamer +steamers steamer +steaming steam +steams steam +steddy steddi +stee stee +steed steed +steeds steed +steel steel +steeled steel +steep steep +steeped steep +steeper steeper +steepest steepest +steeple steepl +steeplechase steeplechas +steepled steepl +steeples steepl +steeply steepli +steepness steep +steer steer +steered steer +steering steer +stem stem +stemming stem +stems stem +stench stench +stentorian stentorian +step step +stepdaughter stepdaught +stephenson stephenson +stepmother stepmoth +steppe stepp +stepped step +steppes stepp +stepping step +steps step +stepson stepson +stercovorous stercovor +sterile steril +sterilit sterilit +sterility steril +sterling sterl +stern stern +sterne stern +sterner sterner +sternest sternest +sternly stern +sternness stern +stertorous stertor +stertorously stertor +stethoscope stethoscop +stew stew +stewam stewam +steward steward +stewardship stewardship +stewart stewart +stewing stew +stic stic +stick stick +sticker sticker +sticking stick +stickler stickler +sticks stick +sticky sticki +stif stif +stiff stiff +stiffer stiffer +stiffest stiffest +stiffly stiffli +stiffness stiff +stifle stifl +stifled stifl +stifling stifl +stigmatised stigmatis +stigmatize stigmat +stigmatizing stigmat +still still +stillest stillest +stillness still +stilt stilt +stilts stilt +stimulant stimul +stimulants stimul +stimulate stimul +stimulated stimul +stimulates stimul +stimulating stimul +stimulation stimul +stimulus stimulus +sting sting +stinginess stingi +stinging sting +stings sting +stinketh stinketh +stinking stink +stinks stink +stipend stipend +stipendiaries stipendiari +stipulate stipul +stipulated stipul +stipulating stipul +stipulation stipul +stipulations stipul +stir stir +stirred stir +stirring stir +stirrup stirrup +stirrups stirrup +stirs stir +stitch stitch +stitched stitch +stitches stitch +stitching stitch +stock stock +stockade stockad +stockbroker stockbrok +stocked stock +stocking stock +stockingless stockingless +stockings stock +stocks stock +stokes stoke +stolbuns stolbun +stole stole +stolen stolen +stolid stolid +stolidity stolid +stolidly stolid +stomach stomach +stomached stomach +stomacher stomach +stomachic stomach +stomachs stomach +stond stond +stone stone +stoned stone +stones stone +stony stoni +stood stood +stool stool +stools stool +stoop stoop +stooped stoop +stooping stoop +stoops stoop +stop stop +stoppage stoppag +stoppages stoppag +stopped stop +stopper stopper +stopping stop +stops stop +store store +stored store +storehouse storehous +storehouses storehous +stores store +storey storey +storeys storey +storied stori +stories stori +storing store +stork stork +storks stork +storm storm +stormed storm +storming storm +storms storm +stormy stormi +storr storr +story stori +storybook storybook +stout stout +stouter stouter +stoutest stoutest +stoutish stoutish +stoutly stout +stove stove +stoves stove +stow stow +stowed stow +strack strack +straggle straggl +straggled straggl +straggler straggler +stragglers straggler +straggling straggl +straight straight +straightening straighten +straightforward straightforward +straightly straight +straightway straightway +strain strain +strained strain +straining strain +strains strain +strait strait +straitened straiten +straits strait +strand strand +stranded strand +stranding strand +strange strang +strangely strang +strangeness strang +stranger stranger +strangers stranger +strangest strangest +strangle strangl +strangled strangl +strangling strangl +strangulation strangul +strap strap +strapped strap +straps strap +strata strata +stratagem stratagem +strategy strategi +stratford stratford +stratification stratif +stratified stratifi +stratum stratum +straw straw +strawberries strawberri +straws straw +stray stray +strayed stray +straying stray +streak streak +streaked streak +streaks streak +stream stream +streamed stream +streamer streamer +streaming stream +streamlet streamlet +streamlets streamlet +streams stream +street street +streetdoor streetdoor +streets street +strength strength +strengthen strengthen +strengthened strengthen +strengthening strengthen +strenuously strenuous +stress stress +stretch stretch +stretched stretch +stretches stretch +stretching stretch +stretchings stretch +strew strew +strewed strew +strewn strewn +stricken stricken +strickland strickland +strict strict +stricter stricter +strictest strictest +strictly strict +strictness strict +stride stride +strides stride +striding stride +strife strife +strike strike +strikes strike +striking strike +strikingly strike +string string +strings string +strip strip +striped stripe +stripes stripe +stripling stripl +stripped strip +stripping strip +strips strip +stritched stritch +strive strive +striven striven +striving strive +strix strix +strode strode +stroke stroke +stroked stroke +strokes stroke +stroking stroke +strokings stroke +stroll stroll +strolled stroll +strolling stroll +strolls stroll +strong strong +stronger stronger +strongest strongest +strongholds stronghold +strongly strong +strongylus strongylus +strop strop +strove strove +struck struck +structure structur +structures structur +struggle struggl +struggled struggl +struggler struggler +strugglers struggler +struggles struggl +struggling struggl +strum strum +strung strung +struthio struthio +strzelecki strzelecki +stuart stuart +stubb stubb +stubble stubbl +stubbly stubbl +stubborn stubborn +stubbornly stubborn +stubbornness stubborn +stubbs stubb +stuck stuck +stud stud +studded stud +student student +students student +studied studi +studies studi +studio studio +studious studious +studiously studious +studiousness studious +study studi +studying studi +stuff stuff +stuffed stuf +stuffing stuf +stuffs stuff +stuffy stuffi +stumble stumbl +stumbled stumbl +stumbles stumbl +stumbling stumbl +stump stump +stumps stump +stung stung +stunned stun +stunning stun +stunted stunt +stupefaction stupefact +stupefied stupefi +stupendous stupend +stupid stupid +stupider stupid +stupidity stupid +stupidly stupid +stupids stupid +stupor stupor +sturdiest sturdiest +sturdily sturdili +sturdy sturdi +sturt sturt +stuttered stutter +style style +styles style +stylifer stylif +stylish stylish +suadiva suadiva +suavity suaviti +sub sub +subacid subacid +subaqueous subaqu +subcostal subcost +subdue subdu +subdued subdu +subduer subduer +subdues subdu +subduing subdu +subgroup subgroup +subgroups subgroup +subject subject +subjected subject +subjecting subject +subjection subject +subjects subject +subjugating subjug +sublime sublim +sublimity sublim +submarine submarin +submerged submerg +submergence submerg +submission submiss +submissive submiss +submissively submiss +submissiveness submiss +submit submit +submits submit +submitted submit +submitting submit +subordinate subordin +subordinates subordin +subordination subordin +suborned suborn +suborning suborn +subscribe subscrib +subscribed subscrib +subscribing subscrib +subscription subscript +subscriptions subscript +subsequent subsequ +subsequently subsequ +subservience subservi +subserviences subservi +subservient subservi +subside subsid +subsided subsid +subsidence subsid +subsides subsid +subsidiary subsidiari +subsiding subsid +subsidized subsid +subsist subsist +subsisted subsist +subsistence subsist +subsoil subsoil +substance substanc +substances substanc +substantial substanti +substantially substanti +substantials substanti +substantiate substanti +substantive substant +substitute substitut +substituted substitut +substitutes substitut +substituting substitut +substracted substract +substratum substratum +subterfuge subterfug +subterfuges subterfug +subterranean subterranean +subtile subtil +subtle subtl +subtlety subtleti +subtracted subtract +subtracting subtract +suburb suburb +suburban suburban +suburbs suburb +subversive subvers +subverted subvert +suc suc +succeed succeed +succeeded succeed +succeeding succeed +succeeds succeed +success success +successes success +successful success +successfully success +succession success +successions success +successive success +successively success +successor successor +successors successor +succinea succinea +succour succour +succulent succul +succumbed succumb +succumbing succumb +such such +suck suck +sucked suck +sucker sucker +suckers sucker +sucking suck +suckle suckl +suckling suckl +suction suction +sudden sudden +suddenl suddenl +suddenly sudden +suddenness sudden +suds sud +sued su +suffer suffer +sufferance suffer +suffered suffer +sufferer suffer +sufferers suffer +suffering suffer +sufferings suffer +suffers suffer +suffice suffic +sufficed suffic +sufficiency suffici +sufficient suffici +sufficiently suffici +sufficing suffic +sufflciently sufflcient +suffocated suffoc +suffocating suffoc +suffocation suffoc +suffolk suffolk +suffrage suffrag +suffrages suffrag +suffused suffus +sugar sugar +sugarscaps sugarscap +sugarscraps sugarscrap +suggest suggest +suggested suggest +suggesting suggest +suggestion suggest +suggestions suggest +suggestive suggest +suggests suggest +suicidal suicid +suicide suicid +suicides suicid +suing su +suit suit +suitability suitabl +suitable suitabl +suitably suitabl +suite suit +suited suit +suites suit +suiting suit +suitor suitor +suitors suitor +suits suit +sulivan sulivan +sulk sulk +sulked sulk +sulkily sulkili +sulkiness sulki +sulks sulk +sulky sulki +sullen sullen +sullenly sullen +sullenness sullen +sully sulli +sulphate sulphat +sulphates sulphat +sulphur sulphur +sulphuratus sulphuratus +sulphureous sulphur +sulphuric sulphur +sultan sultan +sultry sultri +sum sum +sumatra sumatra +sumhoo sumhoo +summarily summarili +summary summari +summat summat +summer summer +summers summer +summerson summerson +summertime summertim +summing sum +summit summit +summits summit +summon summon +summoned summon +summoning summon +summons summon +summonses summons +summonsizzing summonsizz +sumptuous sumptuous +sumptuously sumptuous +sums sum +sun sun +sunbeam sunbeam +sunburnt sunburnt +sunday sunday +sundays sunday +sundries sundri +sundry sundri +sunflowers sunflow +sung sung +sunk sunk +sunken sunken +sunlight sunlight +sunning sun +sunny sunni +sunrise sunris +suns sun +sunset sunset +sunsets sunset +sunshine sunshin +sunshiny sunshini +sup sup +superabundant superabund +superadded superad +superadding superad +superannuated superannu +superannuating superannu +superb superb +superbly superbl +supercilious supercili +superciliously supercili +superciliousness supercili +superficial superfici +superficially superfici +superfluities superflu +superfluity superflu +superfluous superflu +superhuman superhuman +superincumbent superincumb +superinduced superinduc +superintend superintend +superintended superintend +superintendence superintend +superintendent superintend +superintending superintend +superintends superintend +superior superior +superiority superior +superiors superior +superlative superl +superlatives superl +superlativest superlativest +supernatural supernatur +supernumeraries supernumerari +superscription superscript +supersede supersed +superseded supersed +superstition superstit +superstitious superstiti +superstitiously superstiti +supervene superven +supervision supervis +supped sup +supper supper +suppers supper +supplanted supplant +supple suppl +supplementary supplementari +suppleness suppl +suppliant suppliant +supplication supplic +supplications supplic +supplied suppli +supplies suppli +supply suppli +supplying suppli +suppor suppor +support support +supported support +supporter support +supporters support +supporting support +supports support +suppose suppos +supposed suppos +supposes suppos +supposing suppos +supposition supposit +suppositions supposit +supposititious supposititi +suppress suppress +suppressed suppress +suppressing suppress +suppression suppress +suppurated suppur +supremacy supremaci +supreme suprem +supremely suprem +supremest supremest +sups sup +sur sur +surcingle surcingl +sure sure +surely sure +surest surest +surf surf +surfac surfac +surface surfac +surfaces surfac +surge surg +surged surg +surgeon surgeon +surgeons surgeon +surgery surgeri +surging surg +surly sur +surmise surmis +surmised surmis +surmises surmis +surmising surmis +surmount surmount +surmounted surmount +surmounting surmount +surname surnam +surnames surnam +surpass surpass +surpassed surpass +surpasses surpass +surpassing surpass +surplus surplus +surprise surpris +surprised surpris +surprises surpris +surprising surpris +surprisingly surpris +surrender surrend +surrendered surrend +surrendering surrend +surreptitiously surreptiti +surrey surrey +surround surround +surrounded surround +surrounding surround +surroundings surround +surry surri +surveillance surveil +survey survey +surveyed survey +surveying survey +surveyor surveyor +surveyors surveyor +surveys survey +survive surviv +survived surviv +surviving surviv +survivor survivor +survivors survivor +surweys surwey +susan susan +susceptibility suscept +susceptible suscept +suspect suspect +suspected suspect +suspecting suspect +suspects suspect +suspended suspend +suspending suspend +suspense suspens +suspension suspens +suspicion suspicion +suspicions suspicion +suspicious suspici +suspiciously suspici +suspiciousness suspici +sustain sustain +sustained sustain +sustaining sustain +sustenance susten +svidrigailov svidrigailov +svidrigailovs svidrigailov +svidrigrailovs svidrigrailov +svirbey svirbey +swab swab +swaddling swaddl +swagger swagger +swaggered swagger +swaggering swagger +swaggerings swagger +swain swain +swains swain +swainson swainson +swaller swaller +swallering swaller +swallow swallow +swallowed swallow +swallower swallow +swallowing swallow +swallows swallow +swam swam +swamp swamp +swamps swamp +swampy swampi +swan swan +swans swan +swansea swansea +sward sward +swarm swarm +swarmed swarm +swarming swarm +swarms swarm +swart swart +swarthy swarthi +sway sway +swayed sway +swaying sway +swear swear +swearing swear +swears swear +sweat sweat +sweden sweden +sweep sweep +sweeper sweeper +sweepers sweeper +sweeping sweep +sweeps sweep +sweet sweet +sweetbread sweetbread +sweetbrier sweetbrier +sweeten sweeten +sweetened sweeten +sweetener sweeten +sweeter sweeter +sweetest sweetest +sweetheart sweetheart +sweethearts sweetheart +sweetie sweeti +sweetly sweet +sweetmeat sweetmeat +sweetness sweet +sweets sweet +swell swell +swelled swell +swelling swell +swellings swell +swells swell +sweltering swelter +swept swept +swerve swerv +swerved swerv +swift swift +swifter swifter +swiftest swiftest +swiftly swift +swiftness swift +swig swig +swillenhausen swillenhausen +swillenhausens swillenhausen +swills swill +swim swim +swimming swim +swims swim +swindle swindl +swindled swindl +swindler swindler +swindlers swindler +swindling swindl +swine swine +swing swing +swinging swing +swings swing +swinishness swinish +swipes swipe +swirling swirl +switch switch +switches switch +switzerland switzerland +swollen swollen +swoln swoln +swoon swoon +swooned swoon +swooning swoon +swoop swoop +swooped swoop +sword sword +swords sword +swordsman swordsman +swordsmanship swordsmanship +swordsmen swordsmen +swore swore +sworn sworn +swosser swosser +swung swung +sycophancy sycoph +sydney sydney +syenite syenit +syenitic syenit +syllable syllabl +syllogism syllog +sylph sylph +symbol symbol +symbolic symbol +symbolism symbol +symbols symbol +symes syme +symmetrical symmetr +symmetrically symmetr +symmetry symmetri +symond symond +symonds symond +sympathetic sympathet +sympathetically sympathet +sympathies sympathi +sympathise sympathis +sympathised sympathis +sympathising sympathis +sympathize sympath +sympathized sympath +sympathizers sympath +sympathizing sympath +sympathy sympathi +symptom symptom +symptomatic symptomat +symptoms symptom +synetheres synether +synod synod +synonymous synonym +syria syria +syriac syriac +syrphus syrphus +system system +systematic systemat +systems system +t t +ta ta +tabanus tabanus +tabby tabbi +table tabl +tableau tableau +tablecloth tablecloth +tablecloths tablecloth +tables tabl +tabooed taboo +tabor tabor +tacit tacit +tacitly tacit +taciturn taciturn +taciturnity taciturn +tack tack +tacking tack +tackle tackl +tacks tack +tacna tacna +tact tact +tactics tactic +tags tag +tagua tagua +tahiti tahiti +tahitian tahitian +tahitians tahitian +tail tail +tailed tail +tailor tailor +tailors tailor +tails tail +tain tain +taint taint +tainted taint +tainting taint +taints taint +tak tak +take take +taken taken +taker taker +takes take +taketh taketh +taking take +takken takken +takkin takkin +talbot talbot +talcahuano talcahuano +tale tale +talent talent +talented talent +talents talent +tales tale +talguen talguen +talisman talisman +talk talk +talkative talkat +talked talk +talker talker +talkers talker +talkin talkin +talking talk +talks talk +tall tall +taller taller +tallest tallest +tallied talli +tallow tallow +tally talli +talus talus +tam tam +tambillos tambillo +tambour tambour +tambourine tambourin +tame tame +tamed tame +tamely tame +tameness tame +tamer tamer +taming tame +tamper tamper +tampered tamper +tampering tamper +tampers tamper +tan tan +tandeel tandeel +tangible tangibl +tangle tangl +tangled tangl +tankard tankard +tanks tank +tanned tan +tanqui tanqui +tantalisation tantalis +tantalised tantalis +tantalising tantalis +tantalizing tantal +tantamount tantamount +tantrums tantrum +tap tap +tapacolo tapacolo +tapalguen tapalguen +tape tape +taper taper +tapering taper +tapers taper +tapes tape +tapir tapir +tapirs tapir +tapis tapi +tapn tapn +tapped tap +tapping tap +taps tap +tapster tapster +taradiddle taradiddl +tardily tardili +tardiness tardi +tardy tardi +tares tare +target target +targets target +tarn tarn +tarnii tarnii +tarnish tarnish +tarnished tarnish +tarpaulins tarpaulin +tarradiddles tarradiddl +tarred tar +tarry tarri +tart tart +tartan tartan +tartar tartar +tartary tartari +tartly tart +tarts tart +task task +tasking task +tasks task +tasman tasman +tasmania tasmania +tassel tassel +tasselled tassel +tassels tassel +tasso tasso +taste tast +tasted tast +tasteful tast +tastefully tast +tasteless tasteless +tastes tast +tasting tast +tat tat +tata tata +tattered tatter +tatters tatter +tattoo tattoo +tattooed tattoo +tattooing tattoo +taught taught +taunt taunt +taunted taunt +taunting taunt +taunto taunto +taunton taunton +taunts taunt +tavern tavern +taverns tavern +tawdry tawdri +tawny tawni +tax tax +taxation taxat +taxed tax +taxes tax +taylor taylor +tbe tbe +tchebarov tchebarov +te te +tea tea +teach teach +teacher teacher +teachers teacher +teaches teach +teaching teach +teachings teach +teacups teacup +teak teak +team team +teapot teapot +tear tear +teardrop teardrop +tearful tear +tearfully tear +tearing tear +tearless tearless +tears tear +tease teas +teased teas +teasing teas +teaspoon teaspoon +teaspoons teaspoon +teatime teatim +technicalities technic +tedious tedious +tediousness tedious +tedium tedium +tee tee +teel teel +teeming teem +teems teem +teens teen +teeth teeth +tehuelches tehuelch +tekenika tekenika +telegram telegram +telegrams telegram +telegraph telegraph +telegraphed telegraph +telegraphic telegraph +telegraphing telegraph +telemachus telemachus +telephoridae telephorida +telescope telescop +telescopes telescop +telescopic telescop +tell tell +tellee telle +teller teller +telling tell +tells tell +temminckii temminckii +temp temp +temper temper +temperament tempera +temperaments tempera +temperance temper +temperate temper +temperature temperatur +tempered temper +tempers temper +tempest tempest +tempestuous tempestu +temple templ +temples templ +temporal tempor +temporary temporari +tempt tempt +temptation temptat +temptations temptat +tempted tempt +tempter tempter +tempting tempt +tempts tempt +ten ten +tenacious tenaci +tenaciously tenaci +tenacity tenac +tenant tenant +tenanted tenant +tenantry tenantri +tenants tenant +tend tend +tended tend +tendencies tendenc +tendency tendenc +tender tender +tendered tender +tenderer tender +tenderest tenderest +tendering tender +tenderly tender +tenderness tender +tending tend +tendinous tendin +tendon tendon +tends tend +tenement tenement +tenements tenement +teneriffe teneriff +tenez tenez +tenfold tenfold +tennyson tennyson +tenor tenor +tens ten +tense tens +tension tension +tensions tension +tent tent +tentacula tentacula +tentative tentat +tentatively tentat +tenth tenth +tenths tenth +tents tent +tenure tenur +tenway tenway +ter ter +tercero tercero +terebra terebra +terebyeva terebyeva +terewth terewth +term term +termagant termag +termed term +terminal termin +terminate termin +terminated termin +terminates termin +terminating termin +termination termin +terms term +tern tern +terns tern +tero tero +terra terra +terrace terrac +terraces terrac +terres terr +terrestrial terrestri +terrible terribl +terribly terribl +terrier terrier +terriers terrier +terrific terrif +terrified terrifi +terrify terrifi +terrifying terrifi +territorial territori +territories territori +territory territori +terror terror +terrors terror +terse ters +terseness ters +tertiary tertiari +teru teru +tesselated tessel +test test +testacea testacea +testament testament +testamentary testamentari +testator testat +tested test +testified testifi +testifies testifi +testifled testifl +testify testifi +testifying testifi +testily testili +testimonial testimoni +testimony testimoni +testiness testi +tests test +testudo testudo +testy testi +tete tete +tetes tete +teutons teuton +tew tew +text text +texture textur +tfoo tfoo +th th +tha tha +thames thame +than than +thank thank +thanked thank +thankee thanke +thankful thank +thankfully thank +thankfulness thank +thanking thank +thankless thankless +thanks thank +thanksgiving thanksgiv +thanksgivings thanksgiv +thanyou thanyou +that that +thatch thatch +thatched thatch +thavies thavi +thaw thaw +thawed thaw +thawing thaw +the the +theatre theatr +theatres theatr +theatrical theatric +theatrically theatric +theatricals theatric +theayter theayter +thee thee +theer theer +theeself theeself +theft theft +thei thei +theils theil +their their +theirs their +theirselves theirselv +them them +theme theme +themes theme +themselves themselv +then then +thence thenc +thenceforth thenceforth +theodolite theodolit +theodora theodora +theodoras theodora +theodore theodor +theoretical theoret +theoretically theoret +theorie theori +theories theori +theorize theoriz +theory theori +ther ther +there there +thereabout thereabout +thereabouts thereabout +thereafter thereaft +thereby therebi +therefore therefor +therefrom therefrom +therein therein +thereof thereof +thereon thereon +theresa theresa +thereto thereto +thereunto thereunto +thereupon thereupon +therewith therewith +theridion theridion +theristicus theristicus +thermometer thermomet +thes thes +these these +they they +thi thi +thick thick +thicken thicken +thickened thicken +thickening thicken +thicker thicker +thickest thickest +thicket thicket +thickets thicket +thickly thick +thickness thick +thief thief +thier thier +thieved thiev +thieves thiev +thigh thigh +thighs thigh +thimble thimbl +thin thin +thine thine +thing thing +things thing +think think +thinkable thinkabl +thinker thinker +thinkin thinkin +thinking think +thinks think +thinly thin +thinned thin +thinner thinner +thinness thin +thinning thin +thins thin +third third +thirdly third +thirds third +thirst thirst +thirstier thirstier +thirsting thirst +thirsty thirsti +thirteen thirteen +thirteenth thirteenth +thirtieth thirtieth +thirty thirti +this this +thistle thistl +thistles thistl +thither thither +tho tho +thomas thoma +thong thong +thongs thong +thorax thorax +thorn thorn +thorns thorn +thorny thorni +thorough thorough +thoroughbred thoroughbr +thoroughfare thoroughfar +thoroughfares thoroughfar +thoroughgoing thoroughgo +thoroughly thorough +those those +thot thot +thou thou +though though +thought thought +thoughtful thought +thoughtfully thought +thoughtfulness thought +thoughtless thoughtless +thoughtlessness thoughtless +thoughts thought +thoughy thoughi +thousand thousand +thousandfold thousandfold +thousands thousand +thousandth thousandth +thousandths thousandth +thousing thous +thout thout +thraldom thraldom +thrash thrash +thrashed thrash +thrashing thrash +thre thre +thread thread +threadbare threadbar +threaded thread +threading thread +threadneedle threadneedl +threads thread +threat threat +threaten threaten +threatened threaten +threatening threaten +threatenings threaten +threatens threaten +threats threat +three three +threepence threepenc +threes three +threescore threescor +threshed thresh +threshold threshold +threw threw +thrice thrice +thried thri +thrift thrift +thriftless thriftless +thrill thrill +thrilled thrill +thrilling thrill +thrills thrill +thrive thrive +thriven thriven +thrives thrive +thriving thrive +throat throat +throats throat +throb throb +throbbed throb +throbbing throb +throne throne +throng throng +thronged throng +thronging throng +throngs throng +throttled throttl +throug throug +through through +throughout throughout +throve throve +throw throw +throwed throw +throwing throw +thrown thrown +throws throw +thrush thrush +thrushes thrush +thrust thrust +thrusting thrust +thrusts thrust +thrveydrop thrveydrop +thu thu +thud thud +thuds thud +thumb thumb +thumbed thumb +thumbs thumb +thump thump +thumped thump +thumping thump +thumps thump +thunder thunder +thunderbolt thunderbolt +thunderclap thunderclap +thundered thunder +thundering thunder +thunderings thunder +thunderstorm thunderstorm +thunderstorms thunderstorm +thunderstruck thunderstruck +thundery thunderi +thursday thursday +thursdays thursday +thus thus +thwart thwart +thwarted thwart +thwarting thwart +thy thi +thyself thyself +ti ti +tiaauru tiaauru +tial tial +tibby tibbi +tibiae tibia +tick tick +ticked tick +ticket ticket +ticketed ticket +tickets ticket +ticking tick +tickings tick +tickle tickl +tickled tickl +tickles tickl +tickling tickl +ticklish ticklish +ticks tick +tidal tidal +tiddler tiddler +tide tide +tides tide +tidied tidi +tidily tidili +tidings tide +tidy tidi +tie tie +tied tie +tierra tierra +tiers tier +ties tie +tiff tiff +tiger tiger +tigerish tigerish +tigers tiger +tight tight +tighten tighten +tightened tighten +tighter tighter +tightly tight +tightness tight +tights tight +tigre tigr +tigress tigress +til til +tilda tilda +tile tile +tiles tile +tiliareus tiliareus +till till +tillage tillag +tilled till +tilly tilli +tilted tilt +tilting tilt +tilts tilt +tim tim +timber timber +timberry timberri +timbers timber +timbrel timbrel +time time +timed time +timely time +times time +timid timid +timidity timid +timidly timid +timorous timor +timorously timor +timothy timothi +timour timour +tin tin +tinae tina +tinamus tinamus +tinder tinder +tinderidica tinderidica +tinge ting +tinged ting +tingle tingl +tingled tingl +tingling tingl +tiniest tiniest +tinker tinker +tinkers tinker +tinkle tinkl +tinkled tinkl +tinkling tinkl +tinochorus tinochorus +tint tint +tinted tint +tinting tint +tints tint +tiny tini +tion tion +tip tip +tipped tip +tipperary tipperari +tippets tippet +tippy tippi +tips tip +tipsily tipsili +tipslark tipslark +tipsy tipsi +tiptoe tipto +tiptop tiptop +tirade tirad +tire tire +tired tire +tires tire +tiresome tiresom +tiring tire +tis tis +tissue tissu +tit tit +tithe tith +titian titian +titlark titlark +title titl +titled titl +titles titl +titmouse titmous +tittered titter +tittering titter +titular titular +tiv tiv +tix tix +tle tle +to to +toad toad +toads toad +toast toast +toasted toast +toasting toast +tobacco tobacco +tobacconist tobacconist +tockahoopo tockahoopo +today today +toddy toddi +toe toe +toes toe +together togeth +togezzer togezz +toight toight +toil toil +toiled toil +toiler toiler +toilet toilet +toilette toilett +toiling toil +toils toil +toilsome toilsom +toity toiti +token token +tokens token +tol tol +told told +toldos toldo +tolerable toler +tolerably toler +tolerate toler +tolerated toler +toleration toler +toll toll +tolled toll +tolling toll +tolstyakov tolstyakov +tom tom +tomahawk tomahawk +tomahawked tomahawk +tomb tomb +tombs tomb +tombstone tombston +tombstones tombston +tomkins tomkin +tommy tommi +tomorrow tomorrow +ton ton +tone tone +toned tone +tones tone +tongs tong +tongue tongu +tongued tongu +tongues tongu +tonight tonight +tons ton +tony toni +too too +toogather toogath +took took +tool tool +tools tool +toomultuous toomultu +toon toon +tooth tooth +toothed tooth +toothful tooth +toothpick toothpick +toothpicks toothpick +tooting toot +top top +topic topic +topics topic +topped top +topping top +toppling toppl +tops top +topsail topsail +topsel topsel +topsy topsi +tor tor +torches torch +torchlight torchlight +tore tore +torment torment +tormented torment +tormenting torment +tormentor tormentor +tormentors tormentor +torments torment +torn torn +torpid torpid +torpor torpor +torrent torrent +torrents torrent +torrid torrid +tortershell tortershel +tortoise tortois +tortoises tortois +tortuous tortuous +torture tortur +tortured tortur +torturer tortur +tortures tortur +torturing tortur +tory tori +toryism toryism +toss toss +tossed toss +tosses toss +tossing toss +tossings toss +total total +totally total +totanus totanus +tottenham tottenham +tottered totter +tottering totter +totum totum +toucans toucan +touch touch +touched touch +toucher toucher +touches touch +touching touch +touchingly touch +touchstone touchston +touchwood touchwood +tough tough +tougher tougher +toughey toughey +toughness tough +toughy toughi +toulon toulon +tour tour +tourists tourist +tours tour +tout tout +toutes tout +touts tout +toward toward +towards toward +towed tow +towel towel +towelling towel +towels towel +tower tower +towered tower +towering tower +towers tower +town town +towns town +township township +townsman townsman +townsmen townsmen +townspeople townspeopl +toxodon toxodon +toy toy +toyed toy +toying toy +toys toy +trace trace +traceable traceabl +traced trace +tracery traceri +traces trace +tracing trace +track track +tracked track +tracking track +trackless trackless +tracks track +tract tract +tractable tractabl +tracts tract +trade trade +trader trader +traders trader +trades trade +tradesfolk tradesfolk +tradesman tradesman +tradesmen tradesmen +tradespeople tradespeopl +trading trade +tradition tradit +traditional tradit +traditionally tradit +traditions tradit +traducer traduc +traducers traduc +trafalgar trafalgar +traffic traffic +tragedian tragedian +tragedies tragedi +tragedy tragedi +tragic tragic +tragical tragic +trail trail +trailed trail +trailing trail +trails trail +train train +trained train +trainer trainer +training train +trains train +trait trait +traitent traitent +traitor traitor +traitorous traitor +traitors traitor +traits trait +trammels trammel +tramp tramp +tramped tramp +tramping tramp +trample trampl +trampled trampl +trampling trampl +tramps tramp +trance tranc +tranquil tranquil +tranquillity tranquil +tranquillize tranquil +tranquillized tranquil +tranquilly tranquilli +trans tran +transact transact +transacted transact +transaction transact +transactions transact +transcendent transcend +transfer transfer +transferred transfer +transferring transfer +transfers transfer +transfigured transfigur +transfixed transfix +transform transform +transformation transform +transformed transform +transgress transgress +transgressed transgress +transgressing transgress +transgression transgress +transient transient +transit transit +transition transit +transitory transitori +translate translat +translated translat +translating translat +translation translat +translator translat +translucency transluc +transmission transmiss +transmits transmit +transmitted transmit +transmutes transmut +transparency transpar +transparenfly transparenfli +transparent transpar +transpire transpir +transpired transpir +transplant transplant +transplanted transplant +transplanting transplant +transport transport +transportable transport +transportal transport +transportation transport +transported transport +transporting transport +transports transport +transposing transpos +transverse transvers +transversely transvers +trap trap +trappe trapp +trapped trap +trappings trap +traps trap +trash trash +trashy trashi +travel travel +travelers travel +travelled travel +traveller travel +travellers travel +travelling travel +travels travel +traverse travers +traversed travers +traversia traversia +traversing travers +travertin travertin +tray tray +trays tray +treaces treac +treacherous treacher +treachery treacheri +treacle treacl +treacled treacl +tread tread +treadin treadin +treading tread +treadmills treadmil +treads tread +treason treason +treasur treasur +treasure treasur +treasured treasur +treasures treasur +treasuring treasur +treasury treasuri +treat treat +treated treat +treating treat +treatise treatis +treatises treatis +treatment treatment +treats treat +treaty treati +treble trebl +trebled trebl +tree tree +trees tree +trellis trelli +trellised trellis +tremble trembl +trembled trembl +trembles trembl +trembling trembl +tremblingly trembl +tremblings trembl +tremendous tremend +tremendously tremend +tremenjous tremenj +tremor tremor +tremors tremor +tremulous tremul +tremulously tremul +trenchant trenchant +trenched trench +trenches trench +trenching trench +trenham trenham +trepanned trepan +trepidation trepid +tres tres +trespass trespass +tress tress +tresses tress +trial trial +trials trial +triangle triangl +triangular triangular +triangularity triangular +tribe tribe +tribes tribe +tribulation tribul +tributaries tributari +tributary tributari +tribute tribut +trice trice +trichodactylus trichodactylus +trichodesmium trichodesmium +trichomanes trichoman +trick trick +tricked trick +trickery trickeri +trickled trickl +trickles trickl +trickling trickl +tricks trick +tricksters trickster +tried tri +triermain triermain +tries tri +trifasciatus trifasciatus +trifle trifl +trifled trifl +trifles trifl +trifling trifl +trigger trigger +trigonocephalus trigonocephalus +trigonometry trigonometri +trigonomical trigonom +trigonomics trigonom +trilled trill +trilling trill +trim trim +trimly trim +trimmed trim +trimmers trimmer +trimming trim +trimmings trim +trinity triniti +trinket trinket +trinkets trinket +trio trio +trip trip +tripod tripod +tripods tripod +tripped trip +tripping trip +trippingly trip +tristan tristan +tristram tristram +triturated tritur +triumph triumph +triumphal triumphal +triumphant triumphant +triumphantly triumphant +triumphed triumph +triumphing triumph +triumphs triumph +triumvirate triumvir +trivets trivet +trivial trivial +trivialities trivial +trochi trochi +trochilus trochilus +trochus trochus +trod trod +trodden trodden +troifling troifl +trois troi +trolling troll +trollope trollop +troop troop +trooped troop +trooper trooper +troops troop +trophies trophi +trophy trophi +tropic tropic +tropical tropic +tropics tropic +tropillas tropilla +trot trot +trotted trot +trotting trot +trotty trotti +trouble troubl +troubled troubl +troubles troubl +troublesome troublesom +troubling troubl +troublous troublous +troughs trough +trouser trouser +trousers trouser +trousseau trousseau +trout trout +trouve trouv +trowel trowel +trowels trowel +truant truant +trudged trudg +trudges trudg +trudging trudg +true true +truer truer +truest truest +truly truli +trump trump +trumpery trumperi +trumpet trumpet +trumpeters trumpet +trumpets trumpet +trumps trump +truncate truncat +truncated truncat +truncheon truncheon +truncheons truncheon +trunk trunk +trunks trunk +trusses truss +trust trust +trusted trust +trustees truste +trustful trust +trustiest trustiest +trusting trust +trusts trust +trustworthy trustworthi +trusty trusti +truth truth +truthful truth +truthlike truthlik +truths truth +try tri +trying tri +tryst tryst +tsar tsar +tschudi tschudi +tsetup tsetup +tsubmit tsubmit +tub tub +tube tube +tubercles tubercl +tuberculata tuberculata +tubers tuber +tubes tube +tubs tub +tuck tuck +tucked tuck +tucker tucker +tuckered tucker +tucking tuck +tucks tuck +tucuman tucuman +tucutuco tucutuco +tucutucos tucutuco +tuesday tuesday +tufaceous tufac +tuff tuff +tuft tuft +tufted tuft +tufts tuft +tugged tug +tugging tug +tuition tuition +tul tul +tulip tulip +tulkinghorn tulkinghorn +tumble tumbl +tumbled tumbl +tumbler tumbler +tumblers tumbler +tumbles tumbl +tumbling tumbl +tumblings tumbl +tumbrils tumbril +tuming tume +tumley tumley +tumult tumult +tumultuous tumultu +tumultuously tumultu +tunbridge tunbridg +tune tune +tunes tune +tunic tunic +tuning tune +tunnel tunnel +tunnels tunnel +tupinieri tupinieri +tupungato tupungato +turban turban +turbans turban +turbid turbid +turbo turbo +turbulence turbul +turbulent turbul +turco turco +tureen tureen +turf turf +turgenev turgenev +turgid turgid +turing ture +turk turk +turkey turkey +turkish turkish +turks turk +turmoil turmoil +turmoils turmoil +turn turn +turnbull turnbul +turned turn +turner turner +turning turn +turnings turn +turnip turnip +turnips turnip +turnout turnout +turnpike turnpik +turns turn +turnstile turnstil +turpentining turpentin +turpin turpin +turret turret +turreted turret +turrets turret +turtle turtl +turtledoves turtledov +turtles turtl +turveydrop turveydrop +turveydrops turveydrop +turvy turvi +tusks tusk +tussocks tussock +tut tut +tutbury tutburi +tutor tutor +tw tw +twain twain +twang twang +twas twas +tweak tweak +tweaking tweak +twelfth twelfth +twelve twelv +twelvemonth twelvemonth +twelvemonths twelvemonth +twenties twenti +twentieth twentieth +twenty twenti +twice twice +twickenham twickenham +twig twig +twigs twig +twilight twilight +twin twin +twine twine +twined twine +twinge twing +twining twine +twinkle twinkl +twinkled twinkl +twinkling twinkl +twinklings twinkl +twins twin +twirl twirl +twirled twirl +twirling twirl +twirls twirl +twist twist +twisted twist +twisting twist +twistings twist +twists twist +twitch twitch +twitched twitch +twitching twitch +twitchings twitch +twitted twit +twitter twitter +twittering twitter +twixt twixt +two two +twofold twofold +twolve twolv +twonty twonti +twopence twopenc +twopenn twopenn +twopenny twopenni +twos twos +twould twould +ty ty +tybalt tybalt +tyerman tyerman +tying tie +tyler tyler +tylerish tylerish +type type +types type +typhus typhus +typical typic +tyrannical tyrann +tyrannized tyrann +tyrannus tyrannus +tyranny tyranni +tyrant tyrant +tyrants tyrant +tyrolese tyroles +tyrone tyron +u u +ud ud +ugh ugh +uglier uglier +ugliness ugli +ugly ugli +uji uji +ulloa ulloa +ulterior ulterior +ultimate ultim +ultimately ultim +ultra ultra +ulvae ulva +um um +umb umb +umbilical umbil +umbrageous umbrag +umbrella umbrella +umbrellas umbrella +umsonst umsonst +un un +unabashed unabash +unabated unab +unable unabl +unaccompanied unaccompani +unaccountable unaccount +unaccountably unaccount +unaccustomed unaccustom +unacknowledged unacknowledg +unacquainted unacquaint +unadorned unadorn +unaffected unaffect +unaffectedly unaffect +unaided unaid +unallowable unallow +unalloyed unalloy +unalluring unallur +unaltered unalt +unambitious unambiti +unanimous unanim +unanimously unanim +unanswerable unanswer +unanswered unansw +unanue unanu +unappeasable unappeas +unappeased unappeas +unapproachable unapproach +unasked unask +unassailable unassail +unassisted unassist +unassuming unassum +unattached unattach +unattainable unattain +unattempted unattempt +unavailing unavail +unavailingly unavail +unavoidable unavoid +unavoidably unavoid +unaware unawar +unawares unawar +unbear unbear +unbearable unbear +unbearably unbear +unbecoming unbecom +unbelieving unbeliev +unbending unbend +unbent unbent +unbiassed unbiass +unbidden unbidden +unblemished unblemish +unblotted unblot +unblushing unblush +unblushingly unblush +unbolted unbolt +unbonneted unbonnet +unborn unborn +unbound unbound +unbounded unbound +unbroken unbroken +unbrushed unbrush +unburdening unburden +unburied unburi +unbusiness unbusi +unbuttoned unbutton +uncalculating uncalcul +uncalled uncal +uncandid uncandid +uncanny uncanni +uncared uncar +uncarried uncarri +unceasing unceas +unceasingly unceas +uncensorious uncensori +unceremonious unceremoni +unceremoniously unceremoni +uncertain uncertain +uncertainly uncertain +uncertainties uncertainti +uncertainty uncertainti +unchain unchain +unchallengeable unchalleng +unchangeable unchang +unchangeably unchang +unchanged unchang +unchanging unchang +uncharitable uncharit +unchastened unchasten +unchecked uncheck +uncherished uncherish +unchild unchild +unchildish unchildish +unchildlike unchildlik +uncivil uncivil +uncivilized uncivil +unclaimed unclaim +unclasp unclasp +unclasped unclasp +unclasping unclasp +unclassified unclassifi +uncle uncl +unclean unclean +uncleanliness uncleanli +uncleanness unclean +uncleared unclear +uncles uncl +unclose unclos +unclouded uncloud +uncoile uncoil +uncoils uncoil +uncomfortable uncomfort +uncomfortably uncomfort +uncommon uncommon +uncommonly uncommon +uncommunicative uncommun +uncompanionable uncompanion +uncomplaining uncomplain +uncompleted uncomplet +uncomplimentary uncomplimentari +uncomprehended uncomprehend +uncompressed uncompress +uncompromising uncompromis +unconcealed unconc +unconcern unconcern +unconcerned unconcern +unconcernedly unconcern +unconfinable unconfin +unconfined unconfin +uncongenial uncongeni +unconnected unconnect +unconquerable unconquer +unconscious unconsci +unconsciously unconsci +unconsciousness unconsci +unconsidered unconsid +unconstitutional unconstitut +unconstitutionally unconstitut +unconstrained unconstrain +uncontaminated uncontamin +uncontradicted uncontradict +uncontrollable uncontrol +uncontrollably uncontrol +uncontrolled uncontrol +unconvinced unconvinc +uncorked uncork +uncourteous uncourt +uncouth uncouth +uncover uncov +uncovered uncov +uncritically uncrit +uncrossed uncross +uncrossing uncross +unction unction +uncultivated uncultiv +uncut uncut +und und +undaunted undaunt +undeceive undec +undeceived undeceiv +undeceiving undeceiv +undecided undecid +undefaced undefac +undefinable undefin +undefined undefin +undeniable undeni +under under +underbred underbr +undercliff undercliff +underclothes undercloth +underdone underdon +underfoot underfoot +undergo undergo +undergoes undergo +undergoing undergo +undergone undergon +undergraduate undergradu +underground underground +underhand underhand +underhanded underhand +underling underl +underlip underlip +underlying under +undermine undermin +undermined undermin +undermining undermin +underneath underneath +underrated underr +underscored underscor +undersecretary undersecretari +underserving underserv +undersoil undersoil +understand understand +understanding understand +understands understand +understood understood +understrapper understrapp +understrappers understrapp +undertake undertak +undertaken undertaken +undertaker undertak +undertakers undertak +undertakes undertak +undertaking undertak +undertakings undertak +undertone underton +undertook undertook +undervalue undervalu +underwent underw +underwood underwood +undescribed undescrib +undeserved undeserv +undeservedly undeserv +undesigning undesign +undesirable undesir +undetermined undetermin +undeviating undevi +undid undid +undignified undignifi +undiminished undiminish +undimmed undim +undisfigured undisfigur +undisguisable undisguis +undisguised undisguis +undisguisedly undisguis +undismayed undismay +undisposed undispos +undistinguishable undistinguish +undisturbed undisturb +undivided undivid +undivulged undivulg +undo undo +undoing undo +undone undon +undoubted undoubt +undoubtedly undoubt +undrained undrain +undraws undraw +undress undress +undressed undress +undressing undress +undue undu +undulating undul +undulation undul +undulations undul +undulatory undulatori +undutiful unduti +undying undi +une une +unearthed unearth +unearthly unearth +uneasily uneasili +uneasiness uneasi +uneasy uneasi +uneatable uneat +uneducated uneduc +unembarrassed unembarrass +unemployed unemploy +unencumbered unencumb +unendurable unendur +unenviable unenvi +unequal unequ +unequalled unequal +unequally unequ +unequivocal unequivoc +unequivocally unequivoc +unerring uner +unes une +uneven uneven +uneventful unev +unexamined unexamin +unexampled unexampl +unexceptionable unexception +unexciting unexcit +unexpected unexpect +unexpectedly unexpect +unexplained unexplain +unexplored unexplor +unexpressed unexpress +unfailing unfail +unfair unfair +unfairly unfair +unfaithfulness unfaith +unfamiliar unfamiliar +unfamiliarity unfamiliar +unfashionable unfashion +unfastened unfasten +unfathomable unfathom +unfavourable unfavour +unfeeling unfeel +unfeelingly unfeel +unfeigned unfeign +unfeignedly unfeign +unfeminine unfeminin +unfilled unfil +unfinished unfinish +unfit unfit +unfitness unfit +unfitted unfit +unfitting unfit +unflinching unflinch +unflinchingly unflinch +unfold unfold +unfolded unfold +unfolding unfold +unfolds unfold +unforeseen unforeseen +unforgiving unforgiv +unformed unform +unfort unfort +unfortnet unfortnet +unfortunate unfortun +unfortunately unfortun +unfortunates unfortun +unfounded unfound +unfrequent unfrequ +unfrequented unfrequ +unfrequently unfrequ +unfresh unfresh +unfriended unfriend +unfriendly unfriend +unfulfilled unfulfil +unfurled unfurl +ungainly ungain +ungallant ungal +ungenerous ungener +ungenial ungeni +ungenteel ungenteel +ungentlemanly ungentleman +ungirdles ungirdl +ungovernable ungovern +ungracious ungraci +ungraciously ungraci +ungraciousness ungraci +ungrateful ungrat +ungratefully ungrat +ungratified ungratifi +ungrown ungrown +unguarded unguard +unhand unhand +unhandsome unhandsom +unhappier unhappi +unhappily unhappili +unhappiness unhappi +unhappy unhappi +unharnessing unhar +unhealed unheal +unhealthy unhealthi +unheard unheard +unheeded unheed +unheeding unheed +unhesitatingly unhesit +unhewn unhewn +unhinged unhing +unholy unholi +unhonoured unhonour +unhooking unhook +unhorsed unhors +unhurried unhurri +unhurt unhurt +unifor unifor +uniform uniform +uniformity uniform +uniformly uniform +uniforms uniform +unimaginable unimagin +unimagined unimagin +unimpaired unimpair +unimpeachable unimpeach +unimpeached unimpeach +unimportant unimport +unimprovable unimprov +unimproved unimprov +uninfluenced uninfluenc +uninhabited uninhabit +uninitiated uniniti +uninjured uninjur +unintellectual unintellectu +unintelligible unintellig +unintentional unintent +unintentionally unintent +uninterested uninterest +uninteresting uninterest +uninterrupted uninterrupt +uninterruptedly uninterrupt +uninvited uninvit +uninviting uninvit +union union +unions union +unique uniqu +unison unison +unit unit +unite unit +united unit +unites unit +unities uniti +uniting unit +units unit +unity uniti +universal univers +universally univers +universe univers +university univers +unjoyous unjoy +unjust unjust +unjustifiable unjustifi +unjustly unjust +unkempt unkempt +unkind unkind +unkindly unkind +unkindness unkind +unkiver unkiv +unknowing unknow +unknowingly unknow +unknown unknown +unladylike unladylik +unlatched unlatch +unlawful unlaw +unlawfully unlaw +unlearn unlearn +unlearnt unlearnt +unless unless +unlicensed unlicens +unlike unlik +unlikely unlik +unlimited unlimit +unliquidated unliquid +unload unload +unloaded unload +unloading unload +unlock unlock +unlocked unlock +unlocking unlock +unlocks unlock +unlooked unlook +unloosed unloos +unloosened unloosen +unlovable unlov +unloved unlov +unlovely unlov +unloving unlov +unluckily unluckili +unlucky unlucki +unmade unmad +unmake unmak +unmanageable unmanag +unmanly unman +unmanned unman +unmans unman +unmarked unmark +unmarried unmarri +unmasked unmask +unmatched unmatch +unmeaning unmean +unmentionable unmention +unmerciful unmerci +unmercifully unmerci +unmerited unmerit +unmindful unmind +unmistakable unmistak +unmistakably unmistak +unmitigated unmitig +unmixed unmix +unmolested unmolest +unmoved unmov +unnamed unnam +unnat unnat +unnatural unnatur +unnaturally unnatur +unnecessarily unnecessarili +unnecessary unnecessari +unnerved unnerv +unnoticed unnot +unobjectionable unobjection +unobservant unobserv +unobserved unobserv +unobtrusive unobtrus +unoccupied unoccupi +unoffending unoffend +unopenable unopen +unopened unopen +unowned unown +unpack unpack +unpacked unpack +unpacking unpack +unpaid unpaid +unpainted unpaint +unpalatable unpalat +unparalleled unparallel +unpardonable unpardon +unpardonably unpardon +unpaved unpav +unpensioning unpens +unperformed unperform +unpersuadable unpersuad +unperturbable unperturb +unpicturesque unpicturesqu +unpitying unpiti +unplaced unplac +unpleasant unpleas +unpleasantly unpleas +unpleasantness unpleas +unpleasantnesses unpleas +unpleasing unpleas +unpleasingly unpleas +unpolite unpolit +unpolitely unpolit +unpoliteness unpolit +unpopular unpopular +unpractical unpract +unpractised unpractis +unprecedented unpreced +unpremeditated unpremedit +unprepared unprepar +unpretending unpretend +unpretendingly unpretend +unprevaricating unprevar +unprincipled unprincipl +unproducible unproduc +unproductive unproduct +unprofitable unprofit +unpromising unpromis +unprosperous unprosper +unprotected unprotect +unprovided unprovid +unpublished unpublish +unpunctual unpunctu +unpunished unpunish +unqualified unqualifi +unquestionable unquestion +unquestionably unquestion +unquiet unquiet +unravel unravel +unravelling unravel +unravelment unravel +unread unread +unreal unreal +unreason unreason +unreasonable unreason +unreasonableness unreason +unreasonably unreason +unreasoning unreason +unreclaimed unreclaim +unrecognised unrecognis +unredeemed unredeem +unrelenting unrel +unrelieved unreliev +unremitting unremit +unrepining unrepin +unrequited unrequit +unreserved unreserv +unresisting unresist +unrest unrest +unrestrained unrestrain +unrestrainedly unrestrain +unriddling unriddl +unripe unrip +unrivalled unrival +unroofed unroof +unruly unruli +unsaddle unsaddl +unsaddled unsaddl +unsafe unsaf +unsatisfactory unsatisfactori +unsatisfied unsatisfi +unsavoury unsavouri +unsay unsay +unschooled unschool +unscratched unscratch +unscrews unscrew +unscrupulous unscrupul +unscrupulously unscrupul +unseasonable unseason +unseemly unseem +unseen unseen +unselfish unselfish +unselfishly unselfish +unselfishness unselfish +unsettle unsettl +unsettled unsettl +unsettles unsettl +unsettling unsettl +unshackled unshackl +unshadowed unshadow +unshaken unshaken +unshaved unshav +unshaven unshaven +unsheltered unshelt +unshod unshod +unsightly unsight +unskilful unskil +unsoftened unsoften +unsolicited unsolicit +unsolved unsolv +unsophisticated unsophist +unsparing unspar +unspeakable unspeak +unspeakably unspeak +unspoilt unspoilt +unspoken unspoken +unstable unstabl +unsteadier unsteadi +unsteadily unsteadili +unsteadiness unsteadi +unsteady unsteadi +unstratified unstratifi +unstrung unstrung +unstudied unstudi +unsubstantial unsubstanti +unsuccessful unsuccess +unsuccessfully unsuccess +unsuitable unsuit +unsuited unsuit +unsullied unsulli +unsupportable unsupport +unsupported unsupport +unsuspecting unsuspect +unsuspicious unsuspici +unsustainable unsustain +unsymmetrical unsymmetr +unsympathetic unsympathet +untainted untaint +untamed untam +untarnished untarnish +untasted untast +untaxed untax +untenable unten +untenanted unten +untended untend +unthankful unthank +unthankfulness unthank +unthinkable unthink +unthought unthought +unthrifty unthrifti +untidily untidili +untidy untidi +untie unti +untied unti +unties unti +until until +untimely untim +untiring untir +unto unto +untold untold +untouched untouch +untoward untoward +untrammelled untrammel +untranslatable untranslat +untried untri +untrimmed untrim +untroubled untroubl +untrue untru +untrustworthy untrustworthi +unturned unturn +untwisting untwist +untying unti +unused unus +unusual unusu +unusually unusu +unutterable unutter +unuttered unutt +unvaried unvari +unvarying unvari +unveil unveil +unveiling unveil +unventilated unventil +unverified unverifi +unwarily unwarili +unwary unwari +unwashed unwash +unwearied unweari +unwearying unweari +unwelcome unwelcom +unwell unwel +unwhitewashed unwhitewash +unwholesome unwholesom +unwieldy unwieldi +unwilling unwil +unwillingly unwil +unwillingness unwilling +unwinding unwind +unwise unwis +unwisely unwis +unwittingly unwit +unwonted unwont +unworldly unworld +unworthily unworthili +unworthiness unworthi +unworthy unworthi +unwound unwound +unwritten unwritten +unwrung unwrung +unyielding unyield +up up +upas upa +upbearing upbear +upbraid upbraid +upbraiding upbraid +upheaval upheav +upheavals upheav +upheaved upheav +upheaving upheav +upheld upheld +uphill uphil +uphold uphold +upholding uphold +upholstered upholst +upholsterer upholster +upholsterers upholster +upholstery upholsteri +upjohn upjohn +uplan uplan +upland upland +uplift uplift +uplifted uplift +uplifting uplift +upliftings uplift +upon upon +upper upper +uppermost uppermost +upraised uprais +upright upright +uprightness upright +uprising upris +uprisings upris +uproar uproar +uproarious uproari +uproariously uproari +uproot uproot +uprooting uproot +uprose upros +ups up +upsallata upsallata +upset upset +upsets upset +upsetting upset +upshot upshot +upside upsid +upstairs upstair +upstart upstart +upstarts upstart +upturned upturn +upward upward +upwards upward +urbane urban +urbanity urban +urchin urchin +urge urg +urged urg +urgency urgenc +urgent urgent +urgently urgent +urges urg +urging urg +urinary urinari +urn urn +ursula ursula +uruguay uruguay +us us +usage usag +usborne usborn +use use +used use +useful use +usefully use +usefulness use +useless useless +uselessly useless +uselessness useless +uses use +usher usher +ushered usher +ushering usher +ushers usher +using use +usnera usnera +uspallata uspallata +usual usual +usually usual +usurer usur +usurers usur +usurp usurp +utamme utamm +utensils utensil +utilitarianism utilitarian +utility util +utilize util +utilized util +utmost utmost +utter utter +utterance utter +uttered utter +uttering utter +utterly utter +utters utter +v v +va va +vacancies vacanc +vacancy vacanc +vacant vacant +vacantly vacant +vacas vaca +vacate vacat +vacated vacat +vacation vacat +vacations vacat +vacillated vacil +vacillating vacil +vacillations vacil +vacillatory vacillatori +vade vade +vagabond vagabond +vagabondizing vagabond +vagabonds vagabond +vagaries vagari +vagary vagari +vagrant vagrant +vagrants vagrant +vague vagu +vaguely vagu +vagueness vagu +vahrushin vahrushin +vain vain +vainer vainer +vainest vainest +vainglory vainglori +vainly vain +vaiuly vaiuli +valdes vald +valdivia valdivia +vale vale +valet valet +valets valet +valiantly valiant +valid valid +validity valid +valise valis +valle vall +valley valley +valleys valley +valour valour +valparaiso valparaiso +valuable valuabl +valuables valuabl +valuation valuat +value valu +valued valu +valueless valueless +valve valv +vamp vamp +vampire vampir +van van +vancouver vancouv +vane vane +vanellus vanellus +vanes vane +vanessa vanessa +vanikoro vanikoro +vanish vanish +vanished vanish +vanishes vanish +vanishing vanish +vanities vaniti +vanity vaniti +vans van +vapid vapid +vapidity vapid +vaporous vapor +vapour vapour +vapouring vapour +vapourings vapour +vapours vapour +vapoury vapouri +vara vara +varents varent +variable variabl +variance varianc +variation variat +variations variat +varie vari +varied vari +variegated varieg +varies vari +varieties varieti +variety varieti +various various +variously various +varnish varnish +varnished varnish +vary vari +varying vari +vase vase +vases vase +vassal vassal +vassalage vassalag +vassilitch vassilitch +vassily vassili +vassilyevsky vassilyevski +vast vast +vastly vast +vastness vast +vasya vasya +vater vater +vaughans vaughan +vault vault +vaulted vault +vaulting vault +vaults vault +vaunt vaunt +vauxhall vauxhal +vayli vayli +ve ve +veal veal +veals veal +veer veer +veered veer +veering veer +vegetabl vegetabl +vegetable veget +vegetables veget +vegetate veget +vegetation veget +vehemence vehem +vehement vehement +vehemently vehement +vehicle vehicl +vehicles vehicl +veil veil +veiled veil +veils veil +vein vein +veined vein +veinous veinous +veins vein +vellum vellum +velocity veloc +velvet velvet +velvets velvet +venda venda +vendome vendom +vendor vendor +vendors vendor +venerable vener +veneration vener +venetian venetian +vengeance vengeanc +venice venic +veniso veniso +venom venom +venomous venom +vent vent +ventana ventana +vented vent +ventilated ventil +ventilation ventil +ventilator ventil +venting vent +ventnor ventnor +ventriloquists ventriloquist +vents vent +venture ventur +ventured ventur +ventures ventur +venturesome venturesom +venturing ventur +venus venus +veo veo +ver ver +vera vera +veracious veraci +veracity verac +veranda veranda +verandah verandah +verandahs verandah +verb verb +verbal verbal +verbally verbal +verbena verbena +verbenas verbena +verbose verbos +verd verd +verdant verdant +verdict verdict +verdigris verdigri +verds verd +verdure verdur +vere vere +verge verg +verging verg +verified verifi +verify verifi +verily verili +verisopht verisopht +veritably verit +verite verit +vermiform vermiform +vermilion vermilion +vermin vermin +verona verona +versailles versaill +versatile versatil +verse vers +versed vers +verses vers +versification versif +version version +versions version +versts verst +vertebrae vertebra +vertical vertic +vertically vertic +vertu vertu +verulam verulam +very veri +vesicles vesicl +vessel vessel +vessels vessel +vestal vestal +vestige vestig +vestiges vestig +vestigia vestigia +vestry vestri +vesuvius vesuvius +veteran veteran +veterinary veterinari +veto veto +vex vex +vexation vexat +vexations vexat +vexatious vexati +vexed vex +vexes vex +vexing vex +vholes vhole +vholeses vholes +vi vi +via via +viands viand +viazemsky viazemski +vibrate vibrat +vibrated vibrat +vibrates vibrat +vibrating vibrat +vibration vibrat +vibrations vibrat +vibratory vibratori +vicar vicar +vicarage vicarag +vicarious vicari +vicariously vicari +vice vice +vicencio vicencio +viceroys viceroy +vices vice +vicinity vicin +vicious vicious +viciously vicious +viciousness vicious +vicissitudes vicissitud +victim victim +victimized victim +victims victim +victoria victoria +victories victori +victorious victori +victory victori +victualled victual +victuals victual +vicuna vicuna +vide vide +video video +vie vie +vied vie +vienna vienna +view view +viewed view +viewing view +views view +vigil vigil +vigilance vigil +vigilant vigil +vigilantly vigil +vigorous vigor +vigorously vigor +vigour vigour +vii vii +viii viii +vil vil +vile vile +vilely vile +vileness vile +viler viler +vilest vilest +vilified vilifi +vilinco vilinco +vilipilli vilipilli +villa villa +village villag +villagers villag +villages villag +villain villain +villainous villain +villains villain +villainy villaini +villarica villarica +villas villa +villechardouin villechardouin +villosus villosus +vilna vilna +vin vin +vincent vincent +vindicate vindic +vindicated vindic +vindication vindic +vindictive vindict +vindictively vindict +vindictiveness vindict +vine vine +vinegar vinegar +vines vine +vineyards vineyard +vino vino +vinoque vinoqu +vintems vintem +viola viola +violate violat +violated violat +violates violat +violation violat +violence violenc +violent violent +violently violent +violet violet +violets violet +violin violin +violins violin +violoncello violoncello +violoncellos violoncello +viper viper +vire vire +virgin virgin +virginian virginian +virgularia virgularia +virtually virtual +virtue virtu +virtues virtu +virtuous virtuous +virtuously virtuous +virulence virul +vis vis +visage visag +visaged visag +viscid viscid +vise vise +vish vish +vishera vishera +visible visibl +visibly visibl +vision vision +visionary visionari +visions vision +visit visit +visitation visit +visitations visit +visited visit +visiting visit +visitor visitor +visitors visitor +visits visit +vista vista +vitae vita +vital vital +vitality vital +vitally vital +vitals vital +vith vith +vithout vithout +vitiated vitiat +vitrified vitrifi +vittles vittl +vituperation vituper +vituperative vitup +vivacious vivaci +vivacity vivac +vive vive +vivid vivid +vividly vivid +vividness vivid +vivisecting vivisect +vivoras vivora +vixen vixen +vixenish vixenish +viz viz +vizier vizier +vm vm +vocabulary vocabulari +vocal vocal +vocalist vocalist +vocalists vocalist +vocation vocat +voce voce +vociferates vocifer +vociferous vocifer +vodka vodka +vogue vogu +voice voic +voiced voic +voices voic +void void +voir voir +vol vol +volatile volatil +volatilized volatil +volcanic volcan +volcano volcano +volcanoes volcano +volcanos volcano +volley volley +volleys volley +volney volney +volte volt +volubility volubl +voluble volubl +volubly volubl +volume volum +volumes volum +voluminous volumin +volumnia volumnia +volumnias volumnia +voluntarily voluntarili +voluntary voluntari +volunteer volunt +volunteered volunt +volunteering volunt +voluptuous voluptu +voluta voluta +volutas voluta +volute volut +vom vom +vomit vomit +von von +voraciously voraci +vortex vortex +vorticose vorticos +voskresensky voskresenski +votaries votari +vote vote +voted vote +voter voter +voters voter +votes vote +voting vote +vouch vouch +vouches vouch +vouchsafe vouchsaf +vouchsafed vouchsaf +vouchsafing vouchsaf +vous vous +vow vow +vowed vow +vowing vow +vows vow +voyage voyag +voyager voyag +voyagers voyag +voyages voyag +voznesensky voznesenski +vrazumihin vrazumihin +vremya vremya +vrow vrow +vue vue +vulgar vulgar +vulgarest vulgarest +vulgarise vulgaris +vulgarity vulgar +vultur vultur +vulture vultur +vultures vultur +w w +wa wa +waa waa +waants waant +waat waat +wackford wackford +wackfords wackford +wadded wad +wadding wad +waddling waddl +wade wade +waded wade +waders wader +wading wade +wafer wafer +wafered wafer +wafers wafer +waft waft +wafted waft +wage wage +waged wage +wager wager +wagers wager +wages wage +wagged wag +wagging wag +waggish waggish +waggishly waggish +waggon waggon +waggoner waggon +waggons waggon +wagner wagner +wagon wagon +wai wai +wail wail +wailed wail +wailing wail +wailings wail +wails wail +waimate waimat +wainscot wainscot +wainscotting wainscot +waiomio waiomio +waist waist +waistcoat waistcoat +waistcoats waistcoat +waisted waist +waists waist +wait wait +waited wait +waiter waiter +waiters waiter +waither waither +waiting wait +waitress waitress +waits wait +wake wake +waked wake +wakeful wake +wakefulness wake +wakened waken +wakening waken +wakes wake +waking wake +wakken wakken +walckanaer walckana +walcot walcot +wale wale +walerawang walerawang +wales wale +walk walk +walked walk +walker walker +walketh walketh +walking walk +walks walk +wall wall +walled wall +walleechu walleechu +wallenstein wallenstein +wallflower wallflow +wallflowers wallflow +wallow wallow +wallowing wallow +walls wall +walnut walnut +walpole walpol +walter walter +walting walt +waltz waltz +waltzed waltz +waltzes waltz +waltzing waltz +wan wan +wand wand +wander wander +wandered wander +wanderer wander +wanderers wander +wandering wander +wanderings wander +wanders wander +wands wand +wane wane +waned wane +wanness wan +wanst wanst +want want +wanted want +wanting want +wanton wanton +wantonly wanton +wantonness wanton +wants want +war war +warbler warbler +warbling warbl +warburton warburton +ward ward +warded ward +warder warder +warding ward +wardrobe wardrob +wardrobes wardrob +wards ward +ware ware +warehouse warehous +warehousemen warehousemen +warehouses warehous +wares ware +warfare warfar +warhorse warhors +warily warili +warking wark +warlike warlik +warm warm +warmed warm +warmer warmer +warmest warmest +warmhearted warmheart +warming warm +warmly warm +warms warm +warmth warmth +warn warn +warned warn +warning warn +warnings warn +warped warp +warrant warrant +warranted warrant +warrants warrant +warrens warren +warring war +warrior warrior +warriors warrior +warrn warrn +wars war +wart wart +warted wart +warts wart +warwick warwick +wary wari +was was +wasche wasch +wash wash +washed wash +washerwoman washerwoman +washery washeri +washes wash +washin washin +washing wash +washings wash +wasn wasn +wasp wasp +waste wast +wasted wast +wasteful wast +wastefulness wast +wastes wast +wasting wast +wat wat +watch watch +watched watch +watcher watcher +watchers watcher +watches watch +watchful watch +watchfully watch +watchfulness watch +watching watch +watchings watch +watchmaker watchmak +watchman watchman +watchmen watchmen +water water +watercourse watercours +watered water +waterfall waterfal +waterfalls waterfal +waterfloods waterflood +waterfowl waterfowl +waterhouse waterhous +watering water +waterloo waterloo +waterproof waterproof +waters water +watershed watersh +waterside watersid +waterwheel waterwheel +waterworn waterworn +watery wateri +wather wather +watkins watkin +watt watt +watts watt +wave wave +waved wave +wavered waver +wavering waver +waves wave +waving wave +wavy wavi +wax wax +waxed wax +waxen waxen +waxing wax +waxy waxi +way way +wayfarer wayfar +wayfarers wayfar +waylaid waylaid +waylay waylay +ways way +wayside waysid +wayward wayward +waywardness wayward +we we +weak weak +weaken weaken +weakened weaken +weakening weaken +weaker weaker +weakest weakest +weakly weak +weakness weak +weaknesses weak +weals weal +wealth wealth +wealthy wealthi +wean wean +weaning wean +weapon weapon +weapons weapon +wear wear +wearer wearer +wearers wearer +wearied weari +wearily wearili +weariness weari +wearing wear +wearisome wearisom +wears wear +weary weari +wearying weari +weasen weasen +weather weather +weatherboard weatherboard +weathercock weathercock +weathered weather +weathers weather +weave weav +weavers weaver +weaving weav +weazen weazen +weazened weazen +web web +webb webb +webbed web +webs web +webster webster +wed wed +wedded wed +weddin weddin +wedding wed +weddings wed +wedge wedg +wedged wedg +wedges wedg +wedlock wedlock +wednesday wednesday +wednesdays wednesday +weed weed +weeding weed +weeds weed +weedur weedur +weedy weedi +week week +weekly week +weeks week +weel weel +weep weep +weepers weeper +weeping weep +weeps weep +weevle weevl +wehr wehr +weigh weigh +weighed weigh +weighing weigh +weighs weigh +weight weight +weightily weightili +weights weight +weighty weighti +weir weir +weird weird +weirs weir +weise weis +welcome welcom +welcomed welcom +welcomer welcom +welcomes welcom +welcoming welcom +welfare welfar +well well +wellington wellington +wells well +welsh welsh +weltering welter +welveteen welveteen +wen wen +wench wench +wenches wench +wend wend +wended wend +wending wend +wengeance wengeanc +went went +weobly weobli +wepping wep +wept wept +wer wer +were were +weren weren +werry werri +wery weri +wessel wessel +west west +westerly wester +western western +westminster westminst +westmoreland westmoreland +westward westward +westwood westwood +wet wet +wets wet +wetted wet +wettest wettest +wetting wet +wexed wex +wha wha +whale whale +whalebones whalebon +whaler whaler +whalers whaler +whalery whaleri +whales whale +whaling whale +wharf wharf +wharton wharton +whartons wharton +wharves wharv +what what +whate whate +whatever whatev +whatsername whatsernam +whatsoever whatsoev +whe whe +wheat wheat +wheedled wheedl +wheedlin wheedlin +wheel wheel +wheelbarrow wheelbarrow +wheelbarrowful wheelbarrow +wheeled wheel +wheeling wheel +wheels wheel +wheelwright wheelwright +wheeze wheez +wheezing wheez +when when +whence whenc +whenever whenev +whensoever whensoev +wher wher +where where +whereabout whereabout +whereabouts whereabout +whereas wherea +whereat whereat +whereby wherebi +wherefore wherefor +wherein wherein +whereof whereof +whereon whereon +wheresoever wheresoev +whereupon whereupon +whereve wherev +wherever wherev +wherewith wherewith +whet whet +whethe wheth +whether whether +whew whew +whey whey +whic whic +which which +whichever whichev +whichsoever whichsoev +whiff whiff +whig whig +whigs whig +while while +whiles while +whilst whilst +whim whim +whimper whimper +whimpered whimper +whimpering whimper +whimpers whimper +whims whim +whimsical whimsic +whimsically whimsic +whined whine +whines whine +whining whine +whinstone whinston +whip whip +whipcord whipcord +whipped whip +whipper whipper +whipping whip +whips whip +whipster whipster +whipt whipt +whirl whirl +whirled whirl +whirling whirl +whirlpool whirlpool +whirls whirl +whirlwind whirlwind +whirr whirr +whish whish +whisk whisk +whisked whisk +whisker whisker +whiskered whisker +whiskers whisker +whisking whisk +whisky whiski +whisper whisper +whispered whisper +whisperers whisper +whispering whisper +whisperings whisper +whisperirig whisperirig +whispers whisper +whist whist +whistle whistl +whistled whistl +whistles whistl +whistling whistl +whit whit +white white +whitechapel whitechapel +whiteford whiteford +whitefriars whitefriar +whitened whiten +whiteness white +whitening whiten +whiter whiter +whites white +whitest whitest +whitewash whitewash +whitewashed whitewash +whitewashing whitewash +whitey whitey +whitford whitford +whither whither +whitish whitish +whitsunday whitsunday +whitsuntide whitsuntid +whittington whittington +whity whiti +who who +whoam whoam +whoever whoever +whol whol +whole whole +wholesale wholesal +wholesome wholesom +wholesomely wholesom +wholesomer wholesom +wholly wholli +whom whom +whomsoever whomsoev +whoo whoo +whooping whoop +whoosh whoosh +whose whose +whosoever whosoev +why whi +whytorseller whytorsel +wi wi +wice wice +wicious wicious +wick wick +wicked wick +wickedest wickedest +wickedly wick +wickedness wicked +wicker wicker +wicket wicket +wickham wickham +widder widder +wide wide +widely wide +widened widen +wider wider +widespread widespread +widest widest +widow widow +widowed widow +widower widow +widowhood widowhood +widows widow +width width +widths width +wield wield +wielded wield +wife wife +wig wig +wight wight +wiglomeration wiglomer +wigmaker wigmak +wigmore wigmor +wigs wig +wigwam wigwam +wigwams wigwam +wil wil +wild wild +wilder wilder +wilderness wilder +wildest wildest +wildly wild +wildness wild +wile wile +wiled wile +wiles wile +wilful wil +wilfully wil +wilfulness wil +wilheim wilheim +will will +willage willag +willed will +william william +williams william +willin willin +willing will +willingiy willingiy +willingly will +willingness willing +willinwodd willinwodd +willl willl +willow willow +willows willow +wills will +willst willst +willy willi +wilmot wilmot +wilson wilson +wilt wilt +wily wili +win win +winced winc +winchester winchest +wincing winc +wind wind +winded wind +winder winder +winders winder +winding wind +windings wind +windlass windlass +windmill windmil +windmills windmil +window window +windowed window +windows window +windpipe windpip +winds wind +windsor windsor +windward windward +windy windi +wine wine +wineglassful wineglass +wines wine +wing wing +winged wing +wingfield wingfield +wingless wingless +wings wing +wink wink +winked wink +winking wink +winkles winkl +winks wink +winner winner +winning win +winnings win +winnowing winnow +wins win +winter winter +winters winter +wintry wintri +wiolinceller wiolincel +wiolincellers wiolincel +wipe wipe +wiped wipe +wipes wipe +wiping wipe +wire wire +wires wire +wiry wiri +wis wis +wisdom wisdom +wise wise +wisely wise +wiser wiser +wisest wisest +wish wish +wished wish +wisher wisher +wishermaydie wishermaydi +wishes wish +wishful wish +wishing wish +wisit wisit +wisitation wisit +wisitations wisit +wisitin wisitin +wisiting wisit +wisk wisk +wisp wisp +wiss wiss +wissen wissen +wistful wist +wistfully wist +wit wit +witch witch +witchcraft witchcraft +witchery witcheri +witches witch +with with +withal withal +withdraw withdraw +withdrawal withdraw +withdrawed withdraw +withdrawing withdraw +withdrawn withdrawn +withdraws withdraw +withdrew withdrew +wither wither +withered wither +withering wither +withers wither +withheld withheld +withhold withhold +withi withi +within within +withou withou +without without +withstand withstand +withstood withstood +wititterly wititt +wititterlys wititt +witness wit +witnessed wit +witnesses wit +witnessing wit +wits wit +witted wit +witticism wittic +witticisms wittic +wittier wittier +wittily wittili +wittles wittl +witty witti +wives wive +wizard wizard +wizened wizen +wlll wlll +wo wo +woa woa +woe woe +woebegone woebegon +woeful woeful +woes woe +woful woful +wofully wofulli +woice woic +woices woic +woke woke +wold wold +wolds wold +wolf wolf +wolgan wolgan +wollaston wollaston +wolsey wolsey +wolves wolv +woman woman +womanhood womanhood +womanish womanish +womankind womankind +womanly woman +women women +won won +wonder wonder +wondered wonder +wonderful wonder +wonderfully wonder +wondering wonder +wonderingly wonder +wonderment wonder +wonders wonder +wondrous wondrous +wonld wonld +wont wont +wonted wont +woo woo +wood wood +woodbine woodbin +woodchips woodchip +woodcot woodcot +woodcourt woodcourt +woodcut woodcut +wooded wood +wooden wooden +woodland woodland +woodlouse woodlous +woodman woodman +woodpecker woodpeck +woods wood +woodwork woodwork +woody woodi +wooed woo +wool wool +woolen woolen +woollen woollen +woolly woolli +woollya woollya +woolsack woolsack +woolwich woolwich +wooman wooman +wor wor +word word +worded word +wording word +words word +wordsworth wordsworth +wordy wordi +wore wore +worid worid +work work +workaday workaday +workbox workbox +worked work +worker worker +workers worker +workhouse workhous +working work +workings work +workman workman +workmanlike workmanlik +workmanship workmanship +workmen workmen +workroom workroom +works work +workshop workshop +workshops workshop +world world +worldliness worldli +worldlings worldl +worldly world +worlds world +worm worm +worming worm +worms worm +wormwood wormwood +worn worn +worried worri +worries worri +worrit worrit +worrited worrit +worritted worrit +worry worri +worrying worri +worse wors +worship worship +worshipped worship +worshippers worshipp +worships worship +worst worst +worsted worst +worsteds worst +worth worth +worthbourne worthbourn +worthier worthier +worthies worthi +worthily worthili +worthless worthless +worthlessness worthless +worthwhile worthwhil +worthy worthi +wos wos +wot wot +woul woul +would would +wouldest wouldest +wouldn wouldn +wound wound +wounded wound +wounding wound +wounds wound +woven woven +wow wow +wows wow +wrangerton wrangerton +wrangle wrangl +wrangling wrangl +wrap wrap +wrapped wrap +wrapper wrapper +wrappers wrapper +wrapping wrap +wrappings wrap +wrapt wrapt +wrath wrath +wrathful wrath +wrathfully wrath +wreaked wreak +wreaking wreak +wreath wreath +wreathed wreath +wreathes wreath +wreathing wreath +wreaths wreath +wreck wreck +wrecked wreck +wren wren +wrench wrench +wrenched wrench +wrenching wrench +wrens wren +wrested wrest +wresting wrest +wrestle wrestl +wrestling wrestl +wretch wretch +wretched wretch +wretchedest wretchedest +wretchedly wretch +wretchedness wretched +wretches wretch +wriggling wriggl +wring wring +wringing wring +wrings wring +wrinkle wrinkl +wrinkled wrinkl +wrinkles wrinkl +wrinkling wrinkl +wrist wrist +wristbands wristband +wrists wrist +writ writ +write write +writer writer +writers writer +writes write +writhe writh +writhed writh +writhing writh +writhings writh +writin writin +writing write +writings write +written written +wrong wrong +wrongdoing wrongdo +wronged wrong +wrongfully wrong +wronging wrong +wrongly wrong +wrongs wrong +wrote wrote +wroth wroth +wrought wrought +wrung wrung +wry wri +wrymug wrymug +wull wull +wuns wun +wunst wunst +wur wur +wurd wurd +wye wye +wyelands wyeland +wyndham wyndham +x x +xi xi +xii xii +xiii xiii +xiv xiv +xix xix +xl xl +xli xli +xlii xlii +xliii xliii +xliv xliv +xlix xlix +xlv xlv +xlvi xlvi +xlvii xlvii +xlviii xlviii +xv xv +xvi xvi +xvii xvii +xviii xviii +xx xx +xxi xxi +xxii xxii +xxiii xxiii +xxiv xxiv +xxix xxix +xxv xxv +xxvi xxvi +xxvii xxvii +xxviii xxviii +xxx xxx +xxxi xxxi +xxxii xxxii +xxxiii xxxiii +xxxiv xxxiv +xxxix xxxix +xxxv xxxv +xxxvi xxxvi +xxxvii xxxvii +xxxviii xxxviii +y y +ya ya +yacht yacht +yachting yacht +yagouaroundi yagouaroundi +yam yam +yammerschooner yammerschoon +yammerschoonering yammerschoon +yams yam +yan yan +yankee yanke +yaquil yaquil +yard yard +yards yard +yarn yarn +yataghan yataghan +yawl yawl +yawn yawn +yawned yawn +yawning yawn +yawns yawn +ye ye +yea yea +year year +yearly year +yearned yearn +yearning yearn +yearnings yearn +years year +yegorovna yegorovna +yell yell +yelled yell +yelling yell +yellow yellow +yellowed yellow +yellower yellow +yellowish yellowish +yells yell +yelping yelp +yeoman yeoman +yerba yerba +yes yes +yesday yesday +yeso yeso +yesterday yesterday +yet yet +yew yew +yield yield +yielded yield +yielding yield +yields yield +yinder yinder +yit yit +yo yo +yoke yoke +yokes yoke +yolk yolk +yon yon +yonder yonder +yonge yong +yoong yoong +yoongster yoongster +yore yore +yorick yorick +york york +yorkshire yorkshir +yorkshireman yorkshireman +you you +youn youn +young young +younger younger +youngest youngest +youngster youngster +youngsters youngster +your your +yours your +yourself yourself +yourselves yourselv +youth youth +youthful youth +youthfully youth +youthfulness youth +youths youth +yquem yquem +yseulte yseult +yucca yucca +yushin yushin +yusupov yusupov +z z +zag zag +zaharovitch zaharovitch +zametov zametov +zample zampl +zaraisk zaraisk +zaraisky zaraiski +zarnitsyn zarnitsyn +zeal zeal +zealand zealand +zealander zealand +zealanders zealand +zealous zealous +zebras zebra +zelandiae zelandia +zelinda zelinda +zenaida zenaida +zenith zenith +zest zest +zeus zeus +zig zig +zigzag zigzag +zigzags zigzag +zimmerman zimmerman +zone zone +zones zone +zonotrichia zonotrichia +zoo zoo +zoodle zoodl +zooks zook +zoolog zoolog +zoological zoolog +zoologically zoolog +zoology zoolog +zoophyt zoophyt +zoophyte zoophyt +zoophytes zoophyt +zorillo zorillo +zorillos zorillo +zossimov zossimov +zu zu +zu! zu diff --git a/main.cpp b/main.cpp index bc8f460..ac5b5bb 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,173 @@ -#include -int main() { - std::cout << "Hello, World!" << std::endl; +#include +#include "parsingData.h" +#include +#include + + +int main(int argc, char* const args[]) { + string searchWord = args[2]; + string DataSet = args[1]; + Directory newDirec; + searchWord = newDirec.stemWord(searchWord); + + word myWord; + myWord.id = searchWord; + + newDirec.createStopMap(); + newDirec.open_dir_using_filesystem(DataSet); + + vector allWords = newDirec.index.toVector(); + vector> wordFreq; + for(int i = 0; i < allWords.size(); i++) { + wordFreq.push_back(make_pair(allWords.at(i).count,allWords.at(i).id)); + } + cout << "most common words" << endl; + sort(wordFreq.begin(), wordFreq.end()); + for(int i = 1; i < 26; i++ ) { + cout << i << ": " << wordFreq.at(wordFreq.size()-i).second << "count: " << wordFreq.at(wordFreq.size()-i).first << endl; + } + + + + string usrInput; + cout << "please enter search query, or 'q' to quit." << endl; + getline(cin, usrInput); + bool andQuery = true; + bool orQuery = false; + bool notQuery = false; + + bool word = true; + bool person = false; + bool org = false; + std::string stringvalues = "125 320 512 750 333"; + vector inputVector; + string tmp; + + vector wordVector; + vector personVector; + vector orgVector; + vector notWordVector; + vector notPersonVector; + vector notOrgVector; + + + //TODO at the end just use the function you made in parsingData with all 6 vectors pretty close to done. then loop + // around until first input is q. remember to add some extra check so that it doesnt auto exit if the first letter is + // q for a longer query. + + while(usrInput.size() > 1 && usrInput[0] != 'q') { + std::istringstream iss (usrInput); + while (!iss.eof()) { + iss >> tmp; + inputVector.push_back(tmp); + } + for (int i = 0; i < inputVector.size(); i++) { + //cout << inputVector.at(i) << endl; + } + + for (int i = 0; i < inputVector.size(); i++) { + if (inputVector.at(i) == "AND") { + + } else if (inputVector.at(i) == "OR") { + andQuery = false; + orQuery = true; + } else if (inputVector.at(i) == "PERSON") { + word = false; + person = true; + org = false; + } else if (inputVector.at(i) == "ORG") { + word = false; + person = false; + org = true; + } else if (inputVector.at(i) == "NOT") { + notQuery = true; + word = true; + person = false; + org = false; + } else {//push to respective lists here. not that much work maybe 15 minutes + if (!notQuery) { + if (word) { + wordVector.push_back(inputVector.at(i)); + } else if (person) { + personVector.push_back(inputVector.at(i)); + } else if (org) { + orgVector.push_back(inputVector.at(i)); + } + + } else { + if (word) { + notWordVector.push_back(inputVector.at(i)); + } else if (person) { + notPersonVector.push_back(inputVector.at(i)); + } else if (org) { + notOrgVector.push_back(inputVector.at(i)); + } + } + } + } + vector searchVector; + if(orQuery) { + searchVector = newDirec.searchOr(wordVector, personVector, orgVector, notWordVector, + notPersonVector, notOrgVector); + } + else { + searchVector = newDirec.searchAnd(wordVector, personVector, orgVector, notWordVector, + notPersonVector, notOrgVector); + } + vector rankedIDs = newDirec.Ranking(searchVector, wordVector); + string docText; + for (int i = 0; i < rankedIDs.size(); i++) { + docText = newDirec.getText(rankedIDs.at(i)); + cout << i+1 << ": "; + for(int j = 0; j < 60 & j < docText.size(); j++) { + cout << docText[j]; + } + cout << endl; + for(int j = 61; j < 120 & j < docText.size(); j++) { + cout << docText[j]; + } + cout << "..." << endl << endl; + + } + cout << endl << "please enter the document number which you want to read" << endl; + int docNum; + cin >> docNum; + docNum--; + if(docNum < rankedIDs.size() && docNum >= 0) { + cout << newDirec.getText(rankedIDs.at(docNum)) << endl; + } + cin.get(); + + cout << endl << "please enter search query, or 'q' to quit." << endl; + getline(cin, usrInput); + + andQuery = true; + orQuery = false; + notQuery = false; + + word = true; + person = false; + org = false; + + //iss.str (usrInput); + + + inputVector.clear(); + wordVector.clear(); + personVector.clear(); + orgVector.clear(); + notWordVector.clear(); + notPersonVector.clear(); + notOrgVector.clear(); + + + } + + + + + return 0; -} + +} \ No newline at end of file diff --git a/parsingData.cpp b/parsingData.cpp new file mode 100644 index 0000000..3c03f96 --- /dev/null +++ b/parsingData.cpp @@ -0,0 +1,408 @@ +// +// Created by Michael Castle on 4/10/22. +// +#include "parsingData.h" +#include "vectorHelper.h" +#include +#include +#include +#include "fstream" +#include "sstream" +#include "stemmerGiveUp.h" +#include + + +using namespace std; +namespace fs = std::filesystem; + + +void Directory::open_dir_using_dirent(const string& directory) { + string filepath; + DIR *dp; + struct dirent *dirp; // the directory file + struct stat filestat; + dp = opendir(directory.c_str()); // open the directory + if (dp == nullptr) // check and see if there was an error opening a given directory + { + cout << "Error(" << errno << ") opening " << directory << endl; + } + + int i = 0; + while ((dirp = readdir(dp)) != nullptr) // while files exist in the directory + { + if(i == 1 || i == 0) { // this is necessary because the first 2 lines that it tries to read are /. and /.. + i++; + continue; + } + + filepath = directory + "/" + dirp->d_name; + + // If the file is a directory (or is in some way invalid) we'll skip it + if (stat(filepath.c_str(), &filestat)) continue; + if (S_ISDIR(filestat.st_mode)) { //If the file is a directory, recursive call to this function + open_dir_using_dirent(filepath); + } else { + //cout << filepath <> str){ + stopWords[str] = true; + } +} + + +void Directory::ParseData(const string& filename) { + + ifstream file(filename); + rapidjson::IStreamWrapper wrapper(file); + rapidjson::Document d; + d.ParseStream(wrapper); + + rapidjson::Value &text = d["text"]; + rapidjson::Value &persons = d["entities"]["persons"]; + rapidjson::Value &organizations = d["entities"]["organizations"]; + rapidjson::Value &uuid = d["uuid"]; + + idString = uuid.GetString(); + vector personsString; + vector orgString; + for(int i = 0; i < persons.Size(); i++) { + personsString.push_back(persons[i]["name"].GetString()); + } + for(int i = 0; i < organizations.Size(); i++) { + orgString.push_back(organizations[i]["name"].GetString()); + } + for (int i = 0; i < personsString.size(); i++) { + vector* vectorPoint = personHash.findPoint(personsString.at(i)); + if(vectorPoint == nullptr) { + vector tmpV; + tmpV.push_back(idString); + //cout << personsString.at(i) << endl; + personHash.insertElement(personsString.at(i), tmpV); + vectorPoint = personHash.findPoint(personsString.at(i)); + } + else { + //cout << idString << endl; + personHash.appendID(personsString.at(i), idString); + } + + //personsString.push_back(persons[i]["name"].GetString()); + } + for (int i = 0; i < orgString.size(); i++) { + vector* vectorPoint = orgHash.findPoint(orgString.at(i)); + if(vectorPoint == nullptr) { + vector tmpV; + tmpV.push_back(idString); + orgHash.insertElement(orgString.at(i), tmpV); + } + else { + orgHash.appendID(orgString.at(i), idString); + } + } + textString = text.GetString(); + istringstream textStream(textString); + + DSDocument tmpDocument; + tmpDocument.ID = idString; + tmpDocument.text = textString; + documentTree.insert(tmpDocument); + + + while (textStream >> tmpWord) { + if (stopWords[tmpWord]) { +// || tmpWord.size() < 3 + } else { + i = tmpWord.size() - 1; + for (int j = 0; j < i + 1; j++) { + tmpWord[j] = tolower(tmpWord[j]); + if (!isalpha(tmpWord[j])) { + tmpWord.resize(j); + break; + } + } + i = tmpWord.size() - 1; + tmps = tmpWord; + + strcpy(s, tmps.c_str()); + i = stem(s, 0, i); + tmpWord.resize(i + 1); + + wordObj.id = tmpWord; + DSNode *location; + index.insert(wordObj); + location = index.findValue(wordObj); + + if (tmpWord != "" && tmpWord != "iraqi") { + location->data.documents.push_back(idString); + location->data.count++; + } + //cout << tmpWord << endl; + } + + } + for(string wholeName : orgString) { + istringstream orgStream(wholeName); + while (orgStream >> tmpWord) { + if (stopWords[tmpWord]) { +// || tmpWord.size() < 3 + } else { + i = tmpWord.size() - 1; + for (int j = 0; j < i + 1; j++) { + tmpWord[j] = tolower(tmpWord[j]); + if (!isalpha(tmpWord[j])) { + tmpWord.resize(j); + break; + } + } + wordObj.id = tmpWord; + DSNode *location; + org_index.insert(wordObj); + location = org_index.findValue(wordObj); + + if (tmpWord != "") { + location->data.documents.push_back(idString); + } + //cout << tmpWord << endl; + } + + } + } + + + for(string wholeName : personsString) { + istringstream personStream(wholeName); + while (personStream >> tmpWord) { + if (stopWords[tmpWord]) { +// || tmpWord.size() < 3 + } else { + i = tmpWord.size() - 1; + for (int j = 0; j < i + 1; j++) { + tmpWord[j] = tolower(tmpWord[j]); + if (!isalpha(tmpWord[j])) { + tmpWord.resize(j); + break; + } + } + wordObj.id = tmpWord; + DSNode *location; + person_index.insert(wordObj); + location = person_index.findValue(wordObj); + + if (tmpWord != "") { + location->data.documents.push_back(idString); + } + //cout << tmpWord << endl; + } + + } + } + + file.close(); + +} + +vector Directory::SearchWord(const word searchword) { + vectorHelper myHelp; + vector returnVector; + cout << searchword.id << endl; + DSNode* tmpWord = index.findValue(searchword); + if(tmpWord != nullptr) { + vector locations = tmpWord->data.documents; + for (int i = 0; i < locations.size(); i++) { + returnVector.push_back(locations[i]); + } + myHelp.pruneVector(&returnVector); + } + return returnVector; + +} + vector Directory::SearchPerson(const word searchword) { + string tmp = searchword.id; + for(int i = 0; i < tmp.size(); i++) { + tmp[i] = tolower(tmp[i]); + } + return personHash.find(tmp); +} + +vector Directory::SearchOrg(const word searchword) { + string tmp = searchword.id; + for(int i = 0; i < tmp.size(); i++) { + tmp[i] = tolower(tmp[i]); + } + return orgHash.find(tmp); +} + +string Directory::stemWord(string searchWord) { + int i = 0; + string tmps; + char s[50]; + + i = searchWord.size()-1; + for(int j = 0; j < i+1; j++) { + searchWord[j] = tolower(searchWord[j]); + if(!isalpha(searchWord[j])) { + searchWord.resize(j); + break; + } + } + i = searchWord.size()-1; + tmps = searchWord; + + strcpy(s,tmps.c_str()); + i = stem(s, 0, i); + searchWord.resize(i+1); + return searchWord; +} + +vector +Directory::searchAnd(vector words, vector persons, vector orgs, vector notWords, + vector notPersons, vector notOrgs) { + + vector returnVector; + vector tmpVector; + vectorHelper myHelp; + word tmpWord; + tmpWord.id = words.at(0); + returnVector = SearchWord(tmpWord); + for(int i = 1; i < words.size(); i++) { + tmpWord.id = words.at(i); + tmpVector = SearchWord(tmpWord); + returnVector = myHelp.combineAnd(&returnVector, &tmpVector); + } + for(int i = 0; i < persons.size(); i++) { + tmpVector = SearchPerson(persons.at(i)); + returnVector = myHelp.combineAnd(&returnVector, &tmpVector); + } + for(int i = 0; i < orgs.size(); i++) { + tmpVector = SearchOrg(orgs.at(i)); + returnVector = myHelp.combineAnd(&returnVector, &tmpVector); + } + + for(string notWord : notWords) { + tmpWord.id = notWord; + tmpVector = SearchWord(tmpWord); + returnVector = myHelp.combineNot(&returnVector, &tmpVector); + } + + for(string notOrg : notOrgs) { + tmpWord.id = notOrg; + tmpVector = SearchOrg(tmpWord); + returnVector = myHelp.combineNot(&returnVector, &tmpVector); + } + + for(string notWord : notPersons) { + tmpWord.id = notWord; + tmpVector = SearchPerson(tmpWord); + returnVector = myHelp.combineNot(&returnVector, &tmpVector); + } + + return returnVector; +} + + +vector +Directory::searchOr(vector words, vector persons, vector orgs, vector notWords, + vector notPersons, vector notOrgs) { + + vector returnVector; + vector tmpVector; + vectorHelper myHelp; + word tmpWord; + tmpWord.id = words.at(0); + returnVector = SearchWord(tmpWord); + for(int i = 1; i < words.size(); i++) { + tmpWord.id = words.at(i); + tmpVector = SearchWord(tmpWord); + returnVector = myHelp.combineOr(&returnVector, &tmpVector); + } + for(int i = 0; i < persons.size(); i++) { + tmpVector = SearchPerson(persons.at(i)); + returnVector = myHelp.combineOr(&returnVector, &tmpVector); + } + for(int i = 0; i < orgs.size(); i++) { + tmpVector = SearchOrg(orgs.at(i)); + returnVector = myHelp.combineOr(&returnVector, &tmpVector); + } + + for(string notWord : notWords) { + tmpWord.id = notWord; + tmpVector = SearchWord(tmpWord); + returnVector = myHelp.combineNot(&returnVector, &tmpVector); + } + + for(string notWord : notOrgs) { + tmpWord.id = notWord; + tmpVector = SearchOrg(tmpWord); + returnVector = myHelp.combineNot(&returnVector, &tmpVector); + } + + for(string notWord : notPersons) { + tmpWord.id = notWord; + tmpVector = SearchPerson(tmpWord); + returnVector = myHelp.combineNot(&returnVector, &tmpVector); + } + return returnVector; +} + + + + +vector Directory::Ranking(vector DocIds, vector words) { + vector> uuidWithRankings; + DSDocument tmp; + vector tempVec; + vector finalVec; + vector integerVec; + string temp; + double counter = 0; + for(int i = 0; i < DocIds.size(); i++){ + temp = getText(DocIds.at(i)); + tempVec = tmp.putWordsInVec(temp); + + for (int j = 0; j < words.size(); j++) { + for (int n = 0; n < tempVec.size(); n++) { + tempVec.at(n) = stemWord(tempVec.at(n)); + if (tempVec.at(n) == words.at(j)){ + counter++; + } + } + } + counter = counter/tempVec.size(); + uuidWithRankings.push_back(make_pair(counter, (DocIds.at(i)))); + counter = 0; + } + sort(uuidWithRankings.begin(), uuidWithRankings.end()); + + for(int v = 0; v < 10 && v < uuidWithRankings.size(); v++){ + finalVec.push_back(uuidWithRankings.at(uuidWithRankings.size()-v-1).second); + } + + return finalVec; +} + + + +string Directory::getText(const string ID) { + DSDocument tmp; + tmp.ID = ID; + return documentTree.findValue(tmp)->data.text; +} + diff --git a/parsingData.h b/parsingData.h new file mode 100644 index 0000000..d8acdf2 --- /dev/null +++ b/parsingData.h @@ -0,0 +1,57 @@ +// +// Created by Michael Ramenofsky on 4/10/22. +// + +#ifndef INC_22S_FINAL_PROJ_PARSINGDATA_H +#define INC_22S_FINAL_PROJ_PARSINGDATA_H +#include "unordered_map" +#include "wordObject.h" +#include "iostream" +#include "DSAvlTree.h" +#include "hashtable.h" +#include "rapidjson/document.h" +#include "rapidjson/istreamwrapper.h" +#include "DSDocument.h" + +class Directory { +public: + unordered_map documentWords; + string tmpWord; + string tmps; + word wordObj; + int i; + char s[100]; + string idString; + string textString; + unordered_map stopWords; + DSTree index; + DSTree org_index; + DSTree person_index; + HashTable orgHash; + HashTable personHash; + DSTree documentTree; + void createStopMap(); + + void open_dir_using_filesystem(const std::string &directory); + + void open_dir_using_dirent(const std::string &directory); + + void ParseData(const std::string &filename); + + vector SearchWord(const word searchword); + + vector SearchPerson(const word searchword); + + vector SearchOrg(const word searchword); + + string getText(string uuid); + + string stemWord(const string unstemedWord); + + vector searchAnd(vector words, vector persons, vector orgs, vector notWords, vector notPersons, vector notOrgs); + vector searchOr(vector words, vector persons, vector orgs, vector notWords, vector notPersons, vector notOrgs); + + vector Ranking(vector DocIds, vector words); + +}; +#endif //INC_22S_FINAL_PROJ_PARSINGDATA_H diff --git a/rapidjson/allocators.h b/rapidjson/allocators.h new file mode 100644 index 0000000..3ec83c1 --- /dev/null +++ b/rapidjson/allocators.h @@ -0,0 +1,692 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ALLOCATORS_H_ +#define RAPIDJSON_ALLOCATORS_H_ + +#include "rapidjson.h" +#include "internal/meta.h" + +#include + +#if RAPIDJSON_HAS_CXX11 +#include +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + + +/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User-defined kDefaultChunkCapacity definition. + + User can define this as any \c size that is a power of 2. +*/ + +#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY +#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024) +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \note implements Allocator concept +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return RAPIDJSON_MALLOC(size); + else + return NULL; // standardize to returning NULL. + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + RAPIDJSON_FREE(originalPtr); + return NULL; + } + return RAPIDJSON_REALLOC(originalPtr, newSize); + } + static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); } + + bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { + return true; + } + bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { + return false; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \note implements Allocator concept +*/ +template +class MemoryPoolAllocator { + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + struct SharedData { + ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + BaseAllocator* ownBaseAllocator; //!< base allocator created by this object. + size_t refcount; + bool ownBuffer; + }; + + static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData)); + static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader)); + + static inline ChunkHeader *GetChunkHead(SharedData *shared) + { + return reinterpret_cast(reinterpret_cast(shared) + SIZEOF_SHARED_DATA); + } + static inline uint8_t *GetChunkBuffer(SharedData *shared) + { + return reinterpret_cast(shared->chunkHead) + SIZEOF_CHUNK_HEADER; + } + + static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity. + +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + explicit + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunk_capacity_(chunkSize), + baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()), + shared_(static_cast(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0)) + { + RAPIDJSON_ASSERT(baseAllocator_ != 0); + RAPIDJSON_ASSERT(shared_ != 0); + if (baseAllocator) { + shared_->ownBaseAllocator = 0; + } + else { + shared_->ownBaseAllocator = baseAllocator_; + } + shared_->chunkHead = GetChunkHead(shared_); + shared_->chunkHead->capacity = 0; + shared_->chunkHead->size = 0; + shared_->chunkHead->next = 0; + shared_->ownBuffer = true; + shared_->refcount = 1; + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunk_capacity_(chunkSize), + baseAllocator_(baseAllocator), + shared_(static_cast(AlignBuffer(buffer, size))) + { + RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER); + shared_->chunkHead = GetChunkHead(shared_); + shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER; + shared_->chunkHead->size = 0; + shared_->chunkHead->next = 0; + shared_->ownBaseAllocator = 0; + shared_->ownBuffer = false; + shared_->refcount = 1; + } + + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(rhs.baseAllocator_), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + ++shared_->refcount; + } + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + ++rhs.shared_->refcount; + this->~MemoryPoolAllocator(); + baseAllocator_ = rhs.baseAllocator_; + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(rhs.baseAllocator_), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + rhs.shared_ = 0; + } + MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + this->~MemoryPoolAllocator(); + baseAllocator_ = rhs.baseAllocator_; + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + rhs.shared_ = 0; + return *this; + } +#endif + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT { + if (!shared_) { + // do nothing if moved + return; + } + if (shared_->refcount > 1) { + --shared_->refcount; + return; + } + Clear(); + BaseAllocator *a = shared_->ownBaseAllocator; + if (shared_->ownBuffer) { + baseAllocator_->Free(shared_); + } + RAPIDJSON_DELETE(a); + } + + //! Deallocates all memory chunks, excluding the first/user one. + void Clear() RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + for (;;) { + ChunkHeader* c = shared_->chunkHead; + if (!c->next) { + break; + } + shared_->chunkHead = c->next; + baseAllocator_->Free(c); + } + shared_->chunkHead->size = 0; + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + size_t capacity = 0; + for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + size_t size = 0; + for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Whether the allocator is shared. + /*! \return true or false. + */ + bool Shared() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + return shared_->refcount > 1; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); + if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity)) + if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) + return NULL; + + void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size; + shared_->chunkHead->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + if (newSize == 0) + return NULL; + + originalSize = RAPIDJSON_ALIGN(originalSize); + newSize = RAPIDJSON_ALIGN(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) { + size_t increment = static_cast(newSize - originalSize); + if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) { + shared_->chunkHead->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + if (void* newBuffer = Malloc(newSize)) { + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + else + return NULL; + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing + + //! Compare (equality) with another MemoryPoolAllocator + bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + return shared_ == rhs.shared_; + } + //! Compare (inequality) with another MemoryPoolAllocator + bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { + return !operator==(rhs); + } + +private: + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + \return true if success. + */ + bool AddChunk(size_t capacity) { + if (!baseAllocator_) + shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); + if (ChunkHeader* chunk = static_cast(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) { + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = shared_->chunkHead; + shared_->chunkHead = chunk; + return true; + } + else + return false; + } + + static inline void* AlignBuffer(void* buf, size_t &size) + { + RAPIDJSON_NOEXCEPT_ASSERT(buf != 0); + const uintptr_t mask = sizeof(void*) - 1; + const uintptr_t ubuf = reinterpret_cast(buf); + if (RAPIDJSON_UNLIKELY(ubuf & mask)) { + const uintptr_t abuf = (ubuf + mask) & ~mask; + RAPIDJSON_ASSERT(size >= abuf - ubuf); + buf = reinterpret_cast(abuf); + size -= abuf - ubuf; + } + return buf; + } + + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + SharedData *shared_; //!< The shared data of the allocator +}; + +namespace internal { + template + struct IsRefCounted : + public FalseType + { }; + template + struct IsRefCounted::Type> : + public TrueType + { }; +} + +template +inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) +{ + RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T)); + return static_cast(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); +} + +template +inline T *Malloc(A& a, size_t n = 1) +{ + return Realloc(a, NULL, 0, n); +} + +template +inline void Free(A& a, T *p, size_t n = 1) +{ + static_cast(Realloc(a, p, n, 0)); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited +#endif + +template +class StdAllocator : + public std::allocator +{ + typedef std::allocator allocator_type; +#if RAPIDJSON_HAS_CXX11 + typedef std::allocator_traits traits_type; +#else + typedef allocator_type traits_type; +#endif + +public: + typedef BaseAllocator BaseAllocatorType; + + StdAllocator() RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_() + { } + + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + template + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(std::move(rhs)), + baseAllocator_(std::move(rhs.baseAllocator_)) + { } +#endif +#if RAPIDJSON_HAS_CXX11 + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; +#endif + + /* implicit */ + StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(allocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template + struct rebind { + typedef StdAllocator other; + }; + + typedef typename traits_type::size_type size_type; + typedef typename traits_type::difference_type difference_type; + + typedef typename traits_type::value_type value_type; + typedef typename traits_type::pointer pointer; + typedef typename traits_type::const_pointer const_pointer; + +#if RAPIDJSON_HAS_CXX11 + + typedef typename std::add_lvalue_reference::type &reference; + typedef typename std::add_lvalue_reference::type>::type &const_reference; + + pointer address(reference r) const RAPIDJSON_NOEXCEPT + { + return std::addressof(r); + } + const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT + { + return std::addressof(r); + } + + size_type max_size() const RAPIDJSON_NOEXCEPT + { + return traits_type::max_size(*this); + } + + template + void construct(pointer p, Args&&... args) + { + traits_type::construct(*this, p, std::forward(args)...); + } + void destroy(pointer p) + { + traits_type::destroy(*this, p); + } + +#else // !RAPIDJSON_HAS_CXX11 + + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + + pointer address(reference r) const RAPIDJSON_NOEXCEPT + { + return allocator_type::address(r); + } + const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT + { + return allocator_type::address(r); + } + + size_type max_size() const RAPIDJSON_NOEXCEPT + { + return allocator_type::max_size(); + } + + void construct(pointer p, const_reference r) + { + allocator_type::construct(p, r); + } + void destroy(pointer p) + { + allocator_type::destroy(p); + } + +#endif // !RAPIDJSON_HAS_CXX11 + + template + U* allocate(size_type n = 1, const void* = 0) + { + return RAPIDJSON_NAMESPACE::Malloc(baseAllocator_, n); + } + template + void deallocate(U* p, size_type n = 1) + { + RAPIDJSON_NAMESPACE::Free(baseAllocator_, p, n); + } + + pointer allocate(size_type n = 1, const void* = 0) + { + return allocate(n); + } + void deallocate(pointer p, size_type n = 1) + { + deallocate(p, n); + } + +#if RAPIDJSON_HAS_CXX11 + using is_always_equal = std::is_empty; +#endif + + template + bool operator==(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT + { + return baseAllocator_ == rhs.baseAllocator_; + } + template + bool operator!=(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT + { + return !operator==(rhs); + } + + //! rapidjson Allocator concept + static const bool kNeedFree = BaseAllocator::kNeedFree; + static const bool kRefCounted = internal::IsRefCounted::Value; + void* Malloc(size_t size) + { + return baseAllocator_.Malloc(size); + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) + { + return baseAllocator_.Realloc(originalPtr, originalSize, newSize); + } + static void Free(void *ptr) RAPIDJSON_NOEXCEPT + { + BaseAllocator::Free(ptr); + } + +private: + template + friend class StdAllocator; // access to StdAllocator.* + + BaseAllocator baseAllocator_; +}; + +#if !RAPIDJSON_HAS_CXX17 // std::allocator deprecated in C++17 +template +class StdAllocator : + public std::allocator +{ + typedef std::allocator allocator_type; + +public: + typedef BaseAllocator BaseAllocatorType; + + StdAllocator() RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_() + { } + + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + template + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + /* implicit */ + StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(allocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template + struct rebind { + typedef StdAllocator other; + }; + + typedef typename allocator_type::value_type value_type; + +private: + template + friend class StdAllocator; // access to StdAllocator.* + + BaseAllocator baseAllocator_; +}; +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/rapidjson/cursorstreamwrapper.h b/rapidjson/cursorstreamwrapper.h new file mode 100644 index 0000000..fd6513d --- /dev/null +++ b/rapidjson/cursorstreamwrapper.h @@ -0,0 +1,78 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_ +#define RAPIDJSON_CURSORSTREAMWRAPPER_H_ + +#include "stream.h" + +#if defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4702) // unreachable code +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + + +//! Cursor stream wrapper for counting line and column number if error exists. +/*! + \tparam InputStream Any stream that implements Stream Concept +*/ +template > +class CursorStreamWrapper : public GenericStreamWrapper { +public: + typedef typename Encoding::Ch Ch; + + CursorStreamWrapper(InputStream& is): + GenericStreamWrapper(is), line_(1), col_(0) {} + + // counting line and column number + Ch Take() { + Ch ch = this->is_.Take(); + if(ch == '\n') { + line_ ++; + col_ = 0; + } else { + col_ ++; + } + return ch; + } + + //! Get the error line number, if error exists. + size_t GetLine() const { return line_; } + //! Get the error column number, if error exists. + size_t GetColumn() const { return col_; } + +private: + size_t line_; //!< Current Line + size_t col_; //!< Current Column +}; + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_POP +#endif + +#if defined(__GNUC__) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_ diff --git a/rapidjson/document.h b/rapidjson/document.h new file mode 100644 index 0000000..54e2936 --- /dev/null +++ b/rapidjson/document.h @@ -0,0 +1,3011 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +/*! \file document.h */ + +#include "reader.h" +#include "internal/meta.h" +#include "internal/strfunc.h" +#include "memorystream.h" +#include "encodedstream.h" +#include // placement new +#include +#ifdef __cpp_lib_three_way_comparison +#include +#endif + +RAPIDJSON_DIAG_PUSH +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_OFF(effc++) +#endif // __GNUC__ + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include // std::random_access_iterator_tag +#endif + +#if RAPIDJSON_USE_MEMBERSMAP +#include // std::multimap +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template +class GenericValue; + +template +class GenericDocument; + +/*! \def RAPIDJSON_DEFAULT_ALLOCATOR + \ingroup RAPIDJSON_CONFIG + \brief Allows to choose default allocator. + + User can define this to use CrtAllocator or MemoryPoolAllocator. +*/ +#ifndef RAPIDJSON_DEFAULT_ALLOCATOR +#define RAPIDJSON_DEFAULT_ALLOCATOR MemoryPoolAllocator +#endif + +/*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR + \ingroup RAPIDJSON_CONFIG + \brief Allows to choose default stack allocator for Document. + + User can define this to use CrtAllocator or MemoryPoolAllocator. +*/ +#ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR +#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR CrtAllocator +#endif + +/*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User defined kDefaultObjectCapacity value. + + User can define this as any natural number. +*/ +#ifndef RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY +// number of objects that rapidjson::Value allocates memory for by default +#define RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY 16 +#endif + +/*! \def RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User defined kDefaultArrayCapacity value. + + User can define this as any natural number. +*/ +#ifndef RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY +// number of array elements that rapidjson::Value allocates memory for by default +#define RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY 16 +#endif + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template +class GenericMember { +public: + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT + : name(std::move(rhs.name)), + value(std::move(rhs.value)) + { + } + + //! Move assignment in C++11 + GenericMember& operator=(GenericMember&& rhs) RAPIDJSON_NOEXCEPT { + return *this = static_cast(rhs); + } +#endif + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. Its name and value will become a null value after assignment. + */ + GenericMember& operator=(GenericMember& rhs) RAPIDJSON_NOEXCEPT { + if (RAPIDJSON_LIKELY(this != &rhs)) { + name = rhs.name; + value = rhs.value; + } + return *this; + } + + // swap() for std::sort() and other potential use in STL. + friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT { + a.name.Swap(b.name); + a.value.Swap(b.value); + } + +private: + //! Copy constructor is not permitted. + GenericMember(const GenericMember& rhs); +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template +class GenericMemberIterator { + + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator NonConstIterator; + + /** \name std::iterator_traits support */ + //@{ + typedef ValueType value_type; + typedef ValueType * pointer; + typedef ValueType & reference; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + //@} + + //! Pointer to (const) GenericMember + typedef pointer Pointer; + //! Reference to (const) GenericMember + typedef reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + template bool operator==(const GenericMemberIterator& that) const { return ptr_ == that.ptr_; } + template bool operator!=(const GenericMemberIterator& that) const { return ptr_ != that.ptr_; } + template bool operator<=(const GenericMemberIterator& that) const { return ptr_ <= that.ptr_; } + template bool operator>=(const GenericMemberIterator& that) const { return ptr_ >= that.ptr_; } + template bool operator< (const GenericMemberIterator& that) const { return ptr_ < that.ptr_; } + template bool operator> (const GenericMemberIterator& that) const { return ptr_ > that.ptr_; } + +#ifdef __cpp_lib_three_way_comparison + template std::strong_ordering operator<=>(const GenericMemberIterator& that) const { return ptr_ <=> that.ptr_; } +#endif + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template +class GenericMemberIterator; + +//! non-const GenericMemberIterator +template +class GenericMemberIterator { +public: + //! use plain pointer as iterator type + typedef GenericMember* Iterator; +}; +//! const GenericMemberIterator +template +class GenericMemberIterator { +public: + //! use plain const pointer as iterator type + typedef const GenericMember* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array +#ifndef __clang__ // -Wdocumentation + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + template + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer +#ifndef __clang__ // -Wdocumentation + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + explicit GenericStringRef(const CharType* str) + : s(str), length(NotNullStrLen(str)) {} + + //! Create constant string reference from pointer and length +#ifndef __clang__ // -Wdocumentation + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ +#endif + GenericStringRef(const CharType* str, SizeType len) + : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); } + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + SizeType NotNullStrLen(const CharType* str) { + RAPIDJSON_ASSERT(str != 0); + return internal::StrLen(str); + } + + /// Empty string - used when passing in a NULL pointer + static const Ch emptyString[]; + + //! Disallow construction from non-const array + template + GenericStringRef(CharType (&str)[N]) /* = delete */; + //! Copy assignment operator not permitted - immutable type + GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */; +}; + +template +const CharType GenericStringRef::emptyString[] = { CharType() }; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template +inline GenericStringRef StringRef(const CharType* str) { + return GenericStringRef(str); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template +inline GenericStringRef StringRef(const CharType* str, size_t length) { + return GenericStringRef(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template +inline GenericStringRef StringRef(const std::basic_string& str) { + return GenericStringRef(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template struct IsGenericValueImpl::Type, typename Void::Type> + : IsBaseOf, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template struct IsGenericValue : IsGenericValueImpl::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// TypeHelper + +namespace internal { + +template +struct TypeHelper {}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsBool(); } + static bool Get(const ValueType& v) { return v.GetBool(); } + static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } + static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt(); } + static int Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; + +#ifdef _MSC_VER +RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int)); +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt(); } + static long Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned)); +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned long Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; +#endif + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt64(); } + static int64_t Get(const ValueType& v) { return v.GetInt64(); } + static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } + static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint64(); } + static uint64_t Get(const ValueType& v) { return v.GetUint64(); } + static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } + static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsDouble(); } + static double Get(const ValueType& v) { return v.GetDouble(); } + static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } + static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsFloat(); } + static float Get(const ValueType& v) { return v.GetFloat(); } + static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } + static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } +}; + +template +struct TypeHelper { + typedef const typename ValueType::Ch* StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return v.GetString(); } + static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } + static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; + +#if RAPIDJSON_HAS_STDSTRING +template +struct TypeHelper > { + typedef std::basic_string StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } + static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; +#endif + +template +struct TypeHelper { + typedef typename ValueType::Array ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(ValueType& v) { return v.GetArray(); } + static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } + static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(const ValueType& v) { return v.GetArray(); } +}; + +template +struct TypeHelper { + typedef typename ValueType::Object ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(ValueType& v) { return v.GetObject(); } + static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } + static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstObject ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(const ValueType& v) { return v.GetObject(); } +}; + +} // namespace internal + +// Forward declarations +template class GenericArray; +template class GenericObject; + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +template +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. + typedef GenericArray Array; + typedef GenericArray ConstArray; + typedef GenericObject Object; + typedef GenericObject ConstObject; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { + rhs.data_.f.flags = kNullFlag; // give up contents + } +#endif + +private: + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template + GenericValue(GenericDocument&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template + GenericValue& operator=(GenericDocument&& rhs); +#endif + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { + static const uint16_t defaultFlags[] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType); + data_.f.flags = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) + \see CopyFrom() + */ + template + GenericValue(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + switch (rhs.GetType()) { + case kObjectType: + DoCopyMembers(rhs, allocator, copyConstStrings); + break; + case kArrayType: { + SizeType count = rhs.data_.a.size; + GenericValue* le = reinterpret_cast(allocator.Malloc(count * sizeof(GenericValue))); + const GenericValue* re = rhs.GetElementsPointer(); + for (SizeType i = 0; i < count; i++) + new (&le[i]) GenericValue(re[i], allocator, copyConstStrings); + data_.f.flags = kArrayFlag; + data_.a.size = data_.a.capacity = count; + SetElementsPointer(le); + } + break; + case kStringType: + if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) { + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + } + else + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + break; + } + } + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT // See #472 +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_() { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); + data_.f.flags = b ? kTrueFlag : kFalseFlag; + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i; + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u; + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i64; + data_.f.flags = kNumberInt64Flag; + if (i64 >= 0) { + data_.f.flags |= kNumberUint64Flag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + else if (i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u64; + data_.f.flags = kNumberUint64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + data_.f.flags |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for float value. + explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast(f); data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Constructor for Array. + /*! + \param a An array obtained by \c GetArray(). + \note \c Array is always pass-by-value. + \note the source array is moved into this value and the sourec array becomes empty. + */ + GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { + a.value_.data_ = Data(); + a.value_.data_.f.flags = kArrayFlag; + } + + //! Constructor for Object. + /*! + \param o An object obtained by \c GetObject(). + \note \c Object is always pass-by-value. + \note the source object is moved into this value and the sourec object becomes empty. + */ + GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { + o.value_.data_ = Data(); + o.value_.data_.f.flags = kObjectFlag; + } + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + // With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release + // their Allocator if it's refcounted (e.g. MemoryPoolAllocator). + if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 && + internal::IsRefCounted::Value)) { + switch(data_.f.flags) { + case kArrayFlag: + { + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Allocator::Free(e); + } + } + break; + + case kObjectFlag: + DoFreeMembers(); + break; + + case kCopyStringFlag: + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Allocator::Free(const_cast(GetStringPointer())); + } + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + if (RAPIDJSON_LIKELY(this != &rhs)) { + // Can't destroy "this" before assigning "rhs", otherwise "rhs" + // could be used after free if it's an sub-Value of "this", + // hence the temporary danse. + GenericValue temp; + temp.RawAssign(rhs); + this->~GenericValue(); + RawAssign(temp); + } + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) + */ + template + GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator, copyConstStrings); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Complexity is quadratic in Object's member number and linear for the rest (number of all values in the subtree and total lengths of all strings). + */ + template + bool operator==(const GenericValue& rhs) const { + typedef GenericValue RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + return false; + for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + return data_.n.u64 == rhs.data_.n.u64; + + default: + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template + bool operator!=(const GenericValue& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + +#ifndef __cpp_lib_three_way_comparison + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} +#endif + + //!@name Type + //@{ + + Type GetType() const { return static_cast(data_.f.flags & kTypeMask); } + bool IsNull() const { return data_.f.flags == kNullFlag; } + bool IsFalse() const { return data_.f.flags == kFalseFlag; } + bool IsTrue() const { return data_.f.flags == kTrueFlag; } + bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } + bool IsObject() const { return data_.f.flags == kObjectFlag; } + bool IsArray() const { return data_.f.flags == kArrayFlag; } + bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } + bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } + bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } + bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } + bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } + bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } + bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } + + // Checks whether a number can be losslessly converted to a double. + bool IsLosslessDouble() const { + if (!IsNumber()) return false; + if (IsUint64()) { + uint64_t u = GetUint64(); + volatile double d = static_cast(u); + return (d >= 0.0) + && (d < static_cast((std::numeric_limits::max)())) + && (u == static_cast(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast(i); + return (d >= static_cast((std::numeric_limits::min)())) + && (d < static_cast((std::numeric_limits::max)())) + && (i == static_cast(d)); + } + return true; // double, int, uint are always lossless + } + + // Checks whether a number is a float (possible lossy). + bool IsFloat() const { + if ((data_.f.flags & kDoubleFlag) == 0) + return false; + double d = GetDouble(); + return d >= -3.4028234e38 && d <= 3.4028234e38; + } + // Checks whether a number can be losslessly converted to a float. + bool IsLosslessFloat() const { + if (!IsNumber()) return false; + double a = GetDouble(); + if (a < static_cast(-(std::numeric_limits::max)()) + || a > static_cast((std::numeric_limits::max)())) + return false; + double b = static_cast(static_cast(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal + } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Get the capacity of object. + SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template + GenericValue& operator[](const GenericValue& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + + // This will generate -Wexit-time-destructors in clang + // static GenericValue NullValue; + // return NullValue; + + // Use static buffer and placement-new to prevent destruction + static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); + } + } + template + const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } + + //! Request the object to have enough capacity to store members. + /*! \param newCapacity The capacity that the object at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsObject()); + DoReserveMembers(newCapacity, allocator); + return *this; + } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string& name) const { return FindMember(name) != MemberEnd(); } +#endif + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template + bool HasMember(const GenericValue& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template + MemberIterator FindMember(const GenericValue& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + return DoFindMember(name); + } + template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } + +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string& name) { return FindMember(GenericValue(StringRef(name))); } + ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(GenericValue(StringRef(name))); } +#endif + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + DoAddMember(name, value, allocator); + return *this; + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(GenericValue& name, T value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + DoClearMembers(); + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template + bool RemoveMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + return DoRemoveMember(m); + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); + return DoEraseMembers(first, last); + } + + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template + bool EraseMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return GetElementsPointer()[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + SetElementsPointer(reinterpret_cast(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + GetElementsPointer()[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + GetElementsPointer()[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(GetElementsPointer() != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(static_cast(pos), last, static_cast(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast(last - first); + return pos; + } + + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } + + //! Get the value as double type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. + */ + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((data_.f.flags & kInt64Flag) != 0) return static_cast(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast(data_.n.u64); // uint64_t -> double (may lose precision) + } + + //! Get the value as float type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. + */ + float GetFloat() const { + return static_cast(GetDouble()); + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast(f)); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); } + + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); } + + //! Set this value as a string by copying from source string. + /*! \param s source string reference + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(StringRef(s), allocator); } +#endif + + //@} + + //!@name Array + //@{ + + //! Templated version for checking whether this value is type T. + /*! + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string + */ + template + bool Is() const { return internal::TypeHelper::Is(*this); } + + template + T Get() const { return internal::TypeHelper::Get(*this); } + + template + T Get() { return internal::TypeHelper::Get(*this); } + + template + ValueType& Set(const T& data) { return internal::TypeHelper::Set(*this, data); } + + template + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper::Set(*this, data, allocator); } + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) + return false; + if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + return false; + for (const GenericValue* v = Begin(); v != End(); ++v) + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if (IsDouble()) return handler.Double(data_.n.d); + else if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else return handler.Uint64(data_.n.u64); + } + } + +private: + template friend class GenericValue; + template friend class GenericDocument; + + enum { + kBoolFlag = 0x0008, + kNumberFlag = 0x0010, + kIntFlag = 0x0020, + kUintFlag = 0x0040, + kInt64Flag = 0x0080, + kUint64Flag = 0x0100, + kDoubleFlag = 0x0200, + kStringFlag = 0x0400, + kCopyFlag = 0x0800, + kInlineStrFlag = 0x1000, + + // Initial flags of different types. + kNullFlag = kNullType, + // These casts are added to suppress the warning on MSVC about bitwise operations between enums of different types. + kTrueFlag = static_cast(kTrueType) | static_cast(kBoolFlag), + kFalseFlag = static_cast(kFalseType) | static_cast(kBoolFlag), + kNumberIntFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kIntFlag | kInt64Flag), + kNumberUintFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag), + kNumberInt64Flag = static_cast(kNumberType) | static_cast(kNumberFlag | kInt64Flag), + kNumberUint64Flag = static_cast(kNumberType) | static_cast(kNumberFlag | kUint64Flag), + kNumberDoubleFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kDoubleFlag), + kNumberAnyFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag), + kConstStringFlag = static_cast(kStringType) | static_cast(kStringFlag), + kCopyStringFlag = static_cast(kStringType) | static_cast(kStringFlag | kCopyFlag), + kShortStringFlag = static_cast(kStringType) | static_cast(kStringFlag | kCopyFlag | kInlineStrFlag), + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0x07 + }; + + static const SizeType kDefaultArrayCapacity = RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY; + static const SizeType kDefaultObjectCapacity = RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY; + + struct Flag { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer +#elif RAPIDJSON_64BIT + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes +#else + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes +#endif + uint16_t flags; + }; + + struct String { + SizeType length; + SizeType hashcode; //!< reserved + const Ch* str; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(static_cast(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = static_cast(MaxSize - len); } + inline SizeType GetLength() const { return static_cast(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; +#else + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct ObjectData { + SizeType size; + SizeType capacity; + Member* members; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct ArrayData { + SizeType size; + SizeType capacity; + GenericValue* elements; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + ObjectData o; + ArrayData a; + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + + static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) { + return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str); + } + static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) { + return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length; + } + + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } + +#if RAPIDJSON_USE_MEMBERSMAP + + struct MapTraits { + struct Less { + bool operator()(const Data& s1, const Data& s2) const { + SizeType n1 = DataStringLength(s1), n2 = DataStringLength(s2); + int cmp = std::memcmp(DataString(s1), DataString(s2), sizeof(Ch) * (n1 < n2 ? n1 : n2)); + return cmp < 0 || (cmp == 0 && n1 < n2); + } + }; + typedef std::pair Pair; + typedef std::multimap > Map; + typedef typename Map::iterator Iterator; + }; + typedef typename MapTraits::Map Map; + typedef typename MapTraits::Less MapLess; + typedef typename MapTraits::Pair MapPair; + typedef typename MapTraits::Iterator MapIterator; + + // + // Layout of the members' map/array, re(al)located according to the needed capacity: + // + // {Map*}<>{capacity}<>{Member[capacity]}<>{MapIterator[capacity]} + // + // (where <> stands for the RAPIDJSON_ALIGN-ment, if needed) + // + + static RAPIDJSON_FORCEINLINE size_t GetMapLayoutSize(SizeType capacity) { + return RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType)) + + RAPIDJSON_ALIGN(capacity * sizeof(Member)) + + capacity * sizeof(MapIterator); + } + + static RAPIDJSON_FORCEINLINE SizeType &GetMapCapacity(Map* &map) { + return *reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) { + return reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType))); + } + + static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) { + return reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType)) + + RAPIDJSON_ALIGN(GetMapCapacity(map) * sizeof(Member))); + } + + static RAPIDJSON_FORCEINLINE Map* &GetMap(Member* members) { + RAPIDJSON_ASSERT(members != 0); + return *reinterpret_cast(reinterpret_cast(members) - + RAPIDJSON_ALIGN(sizeof(SizeType)) - + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + // Some compilers' debug mechanisms want all iterators to be destroyed, for their accounting.. + RAPIDJSON_FORCEINLINE MapIterator DropMapIterator(MapIterator& rhs) { +#if RAPIDJSON_HAS_CXX11 + MapIterator ret = std::move(rhs); +#else + MapIterator ret = rhs; +#endif + rhs.~MapIterator(); + return ret; + } + + Map* &DoReallocMap(Map** oldMap, SizeType newCapacity, Allocator& allocator) { + Map **newMap = static_cast(allocator.Malloc(GetMapLayoutSize(newCapacity))); + GetMapCapacity(*newMap) = newCapacity; + if (!oldMap) { + *newMap = new (allocator.Malloc(sizeof(Map))) Map(MapLess(), allocator); + } + else { + *newMap = *oldMap; + size_t count = (*oldMap)->size(); + std::memcpy(static_cast(GetMapMembers(*newMap)), + static_cast(GetMapMembers(*oldMap)), + count * sizeof(Member)); + MapIterator *oldIt = GetMapIterators(*oldMap), + *newIt = GetMapIterators(*newMap); + while (count--) { + new (&newIt[count]) MapIterator(DropMapIterator(oldIt[count])); + } + Allocator::Free(oldMap); + } + return *newMap; + } + + RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { + return GetMapMembers(DoReallocMap(0, capacity, allocator)); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* oldMembers = GetMembersPointer(); + Map **oldMap = oldMembers ? &GetMap(oldMembers) : 0, + *&newMap = DoReallocMap(oldMap, newCapacity, allocator); + RAPIDJSON_SETPOINTER(Member, o.members, GetMapMembers(newMap)); + o.capacity = newCapacity; + } + } + + template + MemberIterator DoFindMember(const GenericValue& name) { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator mit = map->find(reinterpret_cast(name.data_)); + if (mit != map->end()) { + return MemberIterator(&members[mit->second]); + } + } + return MemberEnd(); + } + + void DoClearMembers() { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + for (SizeType i = 0; i < data_.o.size; i++) { + map->erase(DropMapIterator(mit[i])); + members[i].~Member(); + } + data_.o.size = 0; + } + } + + void DoFreeMembers() { + if (Member* members = GetMembersPointer()) { + GetMap(members)->~Map(); + for (SizeType i = 0; i < data_.o.size; i++) { + members[i].~Member(); + } + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Map** map = &GetMap(members); + Allocator::Free(*map); + Allocator::Free(map); + } + } + } + +#else // !RAPIDJSON_USE_MEMBERSMAP + + RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { + return Malloc(allocator, capacity); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* newMembers = Realloc(allocator, GetMembersPointer(), o.capacity, newCapacity); + RAPIDJSON_SETPOINTER(Member, o.members, newMembers); + o.capacity = newCapacity; + } + } + + template + MemberIterator DoFindMember(const GenericValue& name) { + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + + void DoClearMembers() { + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + void DoFreeMembers() { + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(GetMembersPointer()); + } + +#endif // !RAPIDJSON_USE_MEMBERSMAP + + void DoAddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + ObjectData& o = data_.o; + if (o.size >= o.capacity) + DoReserveMembers(o.capacity ? (o.capacity + (o.capacity + 1) / 2) : kDefaultObjectCapacity, allocator); + Member* members = GetMembersPointer(); + Member* m = members + o.size; + m->name.RawAssign(name); + m->value.RawAssign(value); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + new (&mit[o.size]) MapIterator(map->insert(MapPair(m->name.data_, o.size))); +#endif + ++o.size; + } + + MemberIterator DoRemoveMember(MemberIterator m) { + ObjectData& o = data_.o; + Member* members = GetMembersPointer(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + SizeType mpos = static_cast(&*m - members); + map->erase(DropMapIterator(mit[mpos])); +#endif + MemberIterator last(members + (o.size - 1)); + if (o.size > 1 && m != last) { +#if RAPIDJSON_USE_MEMBERSMAP + new (&mit[mpos]) MapIterator(DropMapIterator(mit[&*last - members])); + mit[mpos]->second = mpos; +#endif + *m = *last; // Move the last one to this place + } + else { + m->~Member(); // Only one left, just destroy + } + --o.size; + return m; + } + + MemberIterator DoEraseMembers(ConstMemberIterator first, ConstMemberIterator last) { + ObjectData& o = data_.o; + MemberIterator beg = MemberBegin(), + pos = beg + (first - beg), + end = MemberEnd(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(GetMembersPointer()); + MapIterator* mit = GetMapIterators(map); +#endif + for (MemberIterator itr = pos; itr != last; ++itr) { +#if RAPIDJSON_USE_MEMBERSMAP + map->erase(DropMapIterator(mit[itr - beg])); +#endif + itr->~Member(); + } +#if RAPIDJSON_USE_MEMBERSMAP + if (first != last) { + // Move remaining members/iterators + MemberIterator next = pos + (last - first); + for (MemberIterator itr = pos; next != end; ++itr, ++next) { + std::memcpy(static_cast(&*itr), &*next, sizeof(Member)); + SizeType mpos = static_cast(itr - beg); + new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg])); + mit[mpos]->second = mpos; + } + } +#else + std::memmove(static_cast(&*pos), &*last, + static_cast(end - last) * sizeof(Member)); +#endif + o.size -= static_cast(last - first); + return pos; + } + + template + void DoCopyMembers(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings) { + RAPIDJSON_ASSERT(rhs.GetType() == kObjectType); + + data_.f.flags = kObjectFlag; + SizeType count = rhs.data_.o.size; + Member* lm = DoAllocMembers(count, allocator); + const typename GenericValue::Member* rm = rhs.GetMembersPointer(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(lm); + MapIterator* mit = GetMapIterators(map); +#endif + for (SizeType i = 0; i < count; i++) { + new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings); + new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings); +#if RAPIDJSON_USE_MEMBERSMAP + new (&mit[i]) MapIterator(map->insert(MapPair(lm[i].name.data_, i))); +#endif + } + data_.o.size = data_.o.capacity = count; + SetMembersPointer(lm); + } + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + data_.f.flags = kArrayFlag; + if (count) { + GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(static_cast(e), values, count * sizeof(GenericValue)); + } + else + SetElementsPointer(0); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + data_.f.flags = kObjectFlag; + if (count) { + Member* m = DoAllocMembers(count, allocator); + SetMembersPointer(m); + std::memcpy(static_cast(m), members, count * sizeof(Member)); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(m); + MapIterator* mit = GetMapIterators(map); + for (SizeType i = 0; i < count; i++) { + new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i))); + } +#endif + } + else + SetMembersPointer(0); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + data_.f.flags = kConstStringFlag; + SetStringPointer(s); + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = 0; + if (ShortString::Usable(s.length)) { + data_.f.flags = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + data_.f.flags = kCopyStringFlag; + data_.s.length = s.length; + str = static_cast(allocator.Malloc((s.length + 1) * sizeof(Ch))); + SetStringPointer(str); + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + // data_.f.flags = rhs.data_.f.flags; + rhs.data_.f.flags = kNullFlag; + } + + template + bool StringEqual(const GenericValue& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; +}; + +//! GenericValue with UTF8 encoding +typedef GenericValue > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \tparam StackAllocator Allocator for allocating memory for stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. +*/ +template +class GenericDocument : public GenericValue { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + // Clear the ::ValueType before ownAllocator is destroyed, ~ValueType() + // runs last and may access its elements or members which would be freed + // with an allocator like MemoryPoolAllocator (CrtAllocator does not + // free its data when destroyed, but MemoryPoolAllocator does). + if (ownAllocator_) { + ValueType::SetNull(); + } + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //! Exchange the contents of this document with those of another. + /*! + \param rhs Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } + + // Allow Swap with ValueType. + // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names. + using ValueType::Swap; + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Populate this document by a generator which produces SAX events. + /*! \tparam Generator A functor with bool f(Handler) prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template + GenericDocument& Populate(Generator& g) { + ClearStackOnExit scope(*this); + if (g(*this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + GenericReader reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(reinterpret_cast(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream is(ms); + ParseStream(is); + return *this; + } + + template + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + template + GenericDocument& Parse(const std::basic_string& str) { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse(str.c_str()); + } + + template + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str.c_str()); + } + + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str); + } +#endif // RAPIDJSON_HAS_STDSTRING + + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occurred in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //! Implicit conversion to get the last parse result +#ifndef __clang // -Wdocumentation + /*! \return \ref ParseResult of the last parse operation + + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ +#endif + operator ParseResult() const { return parseResult_; } + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + // template friend class GenericReader; // for parsing + template friend class GenericValue; // for deep copying + +public: + // Implementation of Handler + bool Null() { new (stack_.template Push()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } + + bool RawNumber(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } + +private: + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument > Document; + + +//! Helper class for accessing Value of array type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetArray(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericArray { +public: + typedef GenericArray ConstArray; + typedef GenericArray Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef ValueType* ValueIterator; // This may be const or non-const iterator + typedef const ValueT* ConstValueIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + + template + friend class GenericValue; + + GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } + ~GenericArray() {} + + operator ValueType&() const { return value_; } + SizeType Size() const { return value_.Size(); } + SizeType Capacity() const { return value_.Capacity(); } + bool Empty() const { return value_.Empty(); } + void Clear() const { value_.Clear(); } + ValueType& operator[](SizeType index) const { return value_[index]; } + ValueIterator Begin() const { return value_.Begin(); } + ValueIterator End() const { return value_.End(); } + GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } + GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + GenericArray PopBack() const { value_.PopBack(); return *this; } + ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + ValueIterator begin() const { return value_.Begin(); } + ValueIterator end() const { return value_.End(); } +#endif + +private: + GenericArray(); + GenericArray(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +//! Helper class for accessing Value of object type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetObject(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericObject { +public: + typedef GenericObject ConstObject; + typedef GenericObject Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef GenericMemberIterator MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; + + template + friend class GenericValue; + + GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } + ~GenericObject() {} + + operator ValueType&() const { return value_; } + SizeType MemberCount() const { return value_.MemberCount(); } + SizeType MemberCapacity() const { return value_.MemberCapacity(); } + bool ObjectEmpty() const { return value_.ObjectEmpty(); } + template ValueType& operator[](T* name) const { return value_[name]; } + template ValueType& operator[](const GenericValue& name) const { return value_[name]; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& operator[](const std::basic_string& name) const { return value_[name]; } +#endif + MemberIterator MemberBegin() const { return value_.MemberBegin(); } + MemberIterator MemberEnd() const { return value_.MemberEnd(); } + GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; } + bool HasMember(const Ch* name) const { return value_.HasMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool HasMember(const std::basic_string& name) const { return value_.HasMember(name); } +#endif + template bool HasMember(const GenericValue& name) const { return value_.HasMember(name); } + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } + template MemberIterator FindMember(const GenericValue& name) const { return value_.FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + MemberIterator FindMember(const std::basic_string& name) const { return value_.FindMember(name); } +#endif + GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_STDSTRING + GenericObject AddMember(ValueType& name, std::basic_string& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + void RemoveAllMembers() { value_.RemoveAllMembers(); } + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) const { return value_.RemoveMember(name); } +#endif + template bool RemoveMember(const GenericValue& name) const { return value_.RemoveMember(name); } + MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } + MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } + bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) const { return EraseMember(ValueType(StringRef(name))); } +#endif + template bool EraseMember(const GenericValue& name) const { return value_.EraseMember(name); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + MemberIterator begin() const { return value_.MemberBegin(); } + MemberIterator end() const { return value_.MemberEnd(); } +#endif + +private: + GenericObject(); + GenericObject(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/rapidjson/encodedstream.h b/rapidjson/encodedstream.h new file mode 100644 index 0000000..cf046b8 --- /dev/null +++ b/rapidjson/encodedstream.h @@ -0,0 +1,299 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODEDSTREAM_H_ +#define RAPIDJSON_ENCODEDSTREAM_H_ + +#include "stream.h" +#include "memorystream.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Input byte stream wrapper with a statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. +*/ +template +class EncodedInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); + + InputByteStream& is_; + Ch current_; +}; + +//! Specialized for UTF8 MemoryStream. +template <> +class EncodedInputStream, MemoryStream> { +public: + typedef UTF8<>::Ch Ch; + + EncodedInputStream(MemoryStream& is) : is_(is) { + if (static_cast(is_.Peek()) == 0xEFu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBBu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBFu) is_.Take(); + } + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) {} + void Flush() {} + Ch* PutBegin() { return 0; } + size_t PutEnd(Ch*) { return 0; } + + MemoryStream& is_; + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); +}; + +//! Output byte stream wrapper with statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream. +*/ +template +class EncodedOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } + + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); + + OutputByteStream& os_; +}; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + +//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. +*/ +template +class AutoUTFInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = reinterpret_cast(is_->Peek4()); + if (!c) + return; + + unsigned bom = static_cast(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; +}; + +//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for writing. + \tparam OutputByteStream type of output byte stream to be wrapped. +*/ +template +class AutoUTFOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } + + typedef void (*PutFunc)(OutputByteStream&, Ch); + + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; +}; + +#undef RAPIDJSON_ENCODINGS_FUNC + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/rapidjson/encodings.h b/rapidjson/encodings.h new file mode 100644 index 0000000..50ad18b --- /dev/null +++ b/rapidjson/encodings.h @@ -0,0 +1,716 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODINGS_H_ +#define RAPIDJSON_ENCODINGS_H_ + +#include "rapidjson.h" + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(overflow) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template + static void Put(OutputByteStream& os, Ch c); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept +*/ +template +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + PutUnsafe(os, static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + PutUnsafe(os, static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + PutUnsafe(os, static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { +#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) +#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + typename InputStream::Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = static_cast(c); + return true; + } + + unsigned char type = GetRange(static_cast(c)); + if (type >= 32) { + *codepoint = 0; + } else { + *codepoint = (0xFFu >> type) & static_cast(c); + } + bool result = true; + switch (type) { + case 2: RAPIDJSON_TAIL(); return result; + case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; + case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; + case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + default: return false; + } +#undef RAPIDJSON_COPY +#undef RAPIDJSON_TRANS +#undef RAPIDJSON_TAIL + } + + template + static bool Validate(InputStream& is, OutputStream& os) { +#define RAPIDJSON_COPY() os.Put(c = is.Take()) +#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + Ch c; + RAPIDJSON_COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange(static_cast(c))) { + case 2: RAPIDJSON_TAIL(); return result; + case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; + case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; + case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + default: return false; + } +#undef RAPIDJSON_COPY +#undef RAPIDJSON_TRANS +#undef RAPIDJSON_TAIL + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + typename InputByteStream::Ch c = Take(is); + if (static_cast(c) != 0xEFu) return c; + c = is.Take(); + if (static_cast(c) != 0xBBu) return c; + c = is.Take(); + if (static_cast(c) != 0xBFu) return c; + c = is.Take(); + return c; + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xEFu)); + os.Put(static_cast(0xBBu)); + os.Put(static_cast(0xBFu)); + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. +*/ +template +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast((v >> 10) | 0xD800)); + os.Put(static_cast((v & 0x3FF) | 0xDC00)); + } + } + + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + PutUnsafe(os, static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast((v >> 10) | 0xD800)); + PutUnsafe(os, static_cast((v & 0x3FF) | 0xDC00)); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + typename InputStream::Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = static_cast(c); + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (static_cast(c) & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (static_cast(c) & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + typename InputStream::Ch c; + os.Put(static_cast(c = is.Take())); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } +}; + +//! UTF-16 little endian encoding. +template +struct UTF16LE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(static_cast(c) & 0xFFu)); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + } +}; + +//! UTF-16 big endian encoding. +template +struct UTF16BE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + os.Put(static_cast(static_cast(c) & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. +*/ +template +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } +}; + +//! UTF-32 little endian enocoding. +template +struct UTF32LE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 24; + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 24) & 0xFFu)); + } +}; + +//! UTF-32 big endian encoding. +template +struct UTF32BE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 24; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((c >> 24) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast(c & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast(codepoint & 0xFF)); + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast(codepoint & 0xFF)); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + uint8_t c = static_cast(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + uint8_t c = static_cast(is.Take()); + os.Put(static_cast(c)); + return c <= 0x7F; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + uint8_t c = static_cast(Take(is)); + return static_cast(c); + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// AutoUTF + +//! Runtime-specified UTF encoding type of a stream. +enum UTFType { + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. +}; + +//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. +/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). +*/ +template +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + + template + static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; + (*f[os.GetType()])(os, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; + (*f[os.GetType()])(os, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) { + typedef bool (*DecodeFunc)(InputStream&, unsigned*); + static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; + return (*f[is.GetType()])(is, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + typedef bool (*ValidateFunc)(InputStream&, OutputStream&); + static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; + return (*f[is.GetType()])(is, os); + } + +#undef RAPIDJSON_ENCODINGS_FUNC +}; + +/////////////////////////////////////////////////////////////////////////////// +// Transcoder + +//! Encoding conversion. +template +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template + static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::EncodeUnsafe(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +// Forward declaration. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + +//! Specialization of Transcoder with same source and target encoding. +template +struct Transcoder { + template + static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { + os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + return Encoding::Validate(is, os); // source/target encoding are the same + } +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__)) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/rapidjson/error/en.h b/rapidjson/error/en.h new file mode 100644 index 0000000..5d2e57b --- /dev/null +++ b/rapidjson/error/en.h @@ -0,0 +1,122 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_EN_H_ +#define RAPIDJSON_ERROR_EN_H_ + +#include "error.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(covered-switch-default) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Maps error code of parsing into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param parseErrorCode Error code obtained in parsing. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { + switch (parseErrorCode) { + case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); + + case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); + + case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); + case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); + case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); + + case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); + + case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); + case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); + case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); + case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); + case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); + + case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); + case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); + case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); + + case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); + case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +//! Maps error code of validation into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param validateErrorCode Error code obtained from validator. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) { + switch (validateErrorCode) { + case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred"); + case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'."); + case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'."); + case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'."); + case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'."); + case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'."); + + case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'."); + case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'."); + case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression."); + + case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'."); + case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'."); + case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true."); + case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema."); + + case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'."); + case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'."); + case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'."); + case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema."); + case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema."); + case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors."); + + case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values."); + case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'."); + + case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors."); + case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'."); + case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors."); + case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors."); + case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_EN_H_ diff --git a/rapidjson/error/error.h b/rapidjson/error/error.h new file mode 100644 index 0000000..6270da1 --- /dev/null +++ b/rapidjson/error/error.h @@ -0,0 +1,216 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_ERROR_H_ +#define RAPIDJSON_ERROR_ERROR_H_ + +#include "../rapidjson.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +/*! \file error.h */ + +/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_CHARTYPE + +//! Character type of error messages. +/*! \ingroup RAPIDJSON_ERRORS + The default character type is \c char. + On Windows, user can define this macro as \c TCHAR for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_CHARTYPE +#define RAPIDJSON_ERROR_CHARTYPE char +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_STRING + +//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. +/*! \ingroup RAPIDJSON_ERRORS + By default this conversion macro does nothing. + On Windows, user can define this macro as \c _T(x) for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_STRING +#define RAPIDJSON_ERROR_STRING(x) x +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseErrorCode + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericReader::Parse, GenericReader::GetParseErrorCode +*/ +enum ParseErrorCode { + kParseErrorNone = 0, //!< No error. + + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + + kParseErrorValueInvalid, //!< Invalid value. + + kParseErrorObjectMissName, //!< Missing a name for object member. + kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. + kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. + + kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. + + kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. + kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. + kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. + kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. + kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. + + kParseErrorNumberTooBig, //!< Number too big to be stored in double. + kParseErrorNumberMissFraction, //!< Miss fraction part in number. + kParseErrorNumberMissExponent, //!< Miss exponent in number. + + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. +}; + +//! Result of parsing (wraps ParseErrorCode) +/*! + \ingroup RAPIDJSON_ERRORS + \code + Document doc; + ParseResult ok = doc.Parse("[42]"); + if (!ok) { + fprintf(stderr, "JSON parse error: %s (%u)", + GetParseError_En(ok.Code()), ok.Offset()); + exit(EXIT_FAILURE); + } + \endcode + \see GenericReader::Parse, GenericDocument::Parse +*/ +struct ParseResult { + //!! Unspecified boolean type + typedef bool (ParseResult::*BooleanType)() const; +public: + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} + //! Constructor to set an error. + ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} + + //! Get the error code. + ParseErrorCode Code() const { return code_; } + //! Get the error offset, if \ref IsError(), 0 otherwise. + size_t Offset() const { return offset_; } + + //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). + operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + + bool operator==(const ParseResult& that) const { return code_ == that.code_; } + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + + bool operator!=(const ParseResult& that) const { return !(*this == that); } + bool operator!=(ParseErrorCode code) const { return !(*this == code); } + friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; } + + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. + void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + +private: + ParseErrorCode code_; + size_t offset_; +}; + +//! Function pointer type of GetParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetParseErrorFunc GetParseError = GetParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + +/////////////////////////////////////////////////////////////////////////////// +// ValidateErrorCode + +//! Error codes when validating. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericSchemaValidator +*/ +enum ValidateErrorCode { + kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set. + kValidateErrorNone = 0, //!< No error. + + kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value. + kValidateErrorMaximum, //!< Number is greater than the 'maximum' value. + kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value. + kValidateErrorMinimum, //!< Number is less than the 'minimum' value. + kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value. + + kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value. + kValidateErrorMinLength, //!< String is longer than the 'maxLength' value. + kValidateErrorPattern, //!< String does not match the 'pattern' regular expression. + + kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value. + kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value. + kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true. + kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema. + + kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value. + kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value. + kValidateErrorRequired, //!< Object is missing one or more members required by the schema. + kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema. + kValidateErrorPatternProperties, //!< See other errors. + kValidateErrorDependencies, //!< Object has missing property or schema dependencies. + + kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values + kValidateErrorType, //!< Property has a type that is not allowed by the schema.. + + kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'. + kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'. + kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'. + kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'. + kValidateErrorNot //!< Property matched the sub-schema specified by 'not'. +}; + +//! Function pointer type of GetValidateError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetValidateError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode); + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_ERROR_H_ diff --git a/rapidjson/filereadstream.h b/rapidjson/filereadstream.h new file mode 100644 index 0000000..f8bb43c --- /dev/null +++ b/rapidjson/filereadstream.h @@ -0,0 +1,99 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEREADSTREAM_H_ +#define RAPIDJSON_FILEREADSTREAM_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! File byte stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileReadStream { +public: + typedef char Ch; //!< Character type (byte). + + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; + } + +private: + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = std::fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } + + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/rapidjson/filewritestream.h b/rapidjson/filewritestream.h new file mode 100644 index 0000000..5d89588 --- /dev/null +++ b/rapidjson/filewritestream.h @@ -0,0 +1,104 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEWRITESTREAM_H_ +#define RAPIDJSON_FILEWRITESTREAM_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of C file stream for output using fwrite(). +/*! + \note implements Stream concept +*/ +class FileWriteStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + size_t result = std::fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if (result < static_cast(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; +}; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(FileWriteStream& stream, char c, size_t n) { + stream.PutN(c, n); +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/rapidjson/fwd.h b/rapidjson/fwd.h new file mode 100644 index 0000000..d62f77f --- /dev/null +++ b/rapidjson/fwd.h @@ -0,0 +1,151 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FWD_H_ +#define RAPIDJSON_FWD_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +// encodings.h + +template struct UTF8; +template struct UTF16; +template struct UTF16BE; +template struct UTF16LE; +template struct UTF32; +template struct UTF32BE; +template struct UTF32LE; +template struct ASCII; +template struct AutoUTF; + +template +struct Transcoder; + +// allocators.h + +class CrtAllocator; + +template +class MemoryPoolAllocator; + +// stream.h + +template +struct GenericStringStream; + +typedef GenericStringStream > StringStream; + +template +struct GenericInsituStringStream; + +typedef GenericInsituStringStream > InsituStringStream; + +// stringbuffer.h + +template +class GenericStringBuffer; + +typedef GenericStringBuffer, CrtAllocator> StringBuffer; + +// filereadstream.h + +class FileReadStream; + +// filewritestream.h + +class FileWriteStream; + +// memorybuffer.h + +template +struct GenericMemoryBuffer; + +typedef GenericMemoryBuffer MemoryBuffer; + +// memorystream.h + +struct MemoryStream; + +// reader.h + +template +struct BaseReaderHandler; + +template +class GenericReader; + +typedef GenericReader, UTF8, CrtAllocator> Reader; + +// writer.h + +template +class Writer; + +// prettywriter.h + +template +class PrettyWriter; + +// document.h + +template +class GenericMember; + +template +class GenericMemberIterator; + +template +struct GenericStringRef; + +template +class GenericValue; + +typedef GenericValue, MemoryPoolAllocator > Value; + +template +class GenericDocument; + +typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document; + +// pointer.h + +template +class GenericPointer; + +typedef GenericPointer Pointer; + +// schema.h + +template +class IGenericRemoteSchemaDocumentProvider; + +template +class GenericSchemaDocument; + +typedef GenericSchemaDocument SchemaDocument; +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +template < + typename SchemaDocumentType, + typename OutputHandler, + typename StateAllocator> +class GenericSchemaValidator; + +typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSONFWD_H_ diff --git a/rapidjson/internal/biginteger.h b/rapidjson/internal/biginteger.h new file mode 100644 index 0000000..1245578 --- /dev/null +++ b/rapidjson/internal/biginteger.h @@ -0,0 +1,290 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_BIGINTEGER_H_ +#define RAPIDJSON_BIGINTEGER_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64) +#include // for _umul128 +#pragma intrinsic(_umul128) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class BigInteger { +public: + typedef uint64_t Type; + + BigInteger(const BigInteger& rhs) : count_(rhs.count_) { + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + + explicit BigInteger(uint64_t u) : count_(1) { + digits_[0] = u; + } + + BigInteger(const char* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; + const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 + while (length >= kMaxDigitPerIteration) { + AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); + length -= kMaxDigitPerIteration; + i += kMaxDigitPerIteration; + } + + if (length > 0) + AppendDecimal64(decimals + i, decimals + i + length); + } + + BigInteger& operator=(const BigInteger &rhs) + { + if (this != &rhs) { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + return *this; + } + + BigInteger& operator=(uint64_t u) { + digits_[0] = u; + count_ = 1; + return *this; + } + + BigInteger& operator+=(uint64_t u) { + Type backup = digits_[0]; + digits_[0] += u; + for (size_t i = 0; i < count_ - 1; i++) { + if (digits_[i] >= backup) + return *this; // no carry + backup = digits_[i + 1]; + digits_[i + 1] += 1; + } + + // Last carry + if (digits_[count_ - 1] < backup) + PushBack(1); + + return *this; + } + + BigInteger& operator*=(uint64_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator*=(uint32_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + const uint64_t c = digits_[i] >> 32; + const uint64_t d = digits_[i] & 0xFFFFFFFF; + const uint64_t uc = u * c; + const uint64_t ud = u * d; + const uint64_t p0 = ud + k; + const uint64_t p1 = uc + (p0 >> 32); + digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); + k = p1 >> 32; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator<<=(size_t shift) { + if (IsZero() || shift == 0) return *this; + + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { + std::memmove(digits_ + offset, digits_, count_ * sizeof(Type)); + count_ += offset; + } + else { + digits_[count_] = 0; + for (size_t i = count_; i > 0; i--) + digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); + digits_[offset] = digits_[0] << interShift; + count_ += offset; + if (digits_[count_]) + count_++; + } + + std::memset(digits_, 0, offset * sizeof(Type)); + + return *this; + } + + bool operator==(const BigInteger& rhs) const { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } + + bool operator==(const Type rhs) const { + return count_ == 1 && digits_[0] == rhs; + } + + BigInteger& MultiplyPow5(unsigned exp) { + static const uint32_t kPow5[12] = { + 5, + 5 * 5, + 5 * 5 * 5, + 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 + }; + if (exp == 0) return *this; + for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 + for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 + if (exp > 0) *this *= kPow5[exp - 1]; + return *this; + } + + // Compute absolute difference of this and rhs. + // Assume this != rhs + bool Difference(const BigInteger& rhs, BigInteger* out) const { + int cmp = Compare(rhs); + RAPIDJSON_ASSERT(cmp != 0); + const BigInteger *a, *b; // Makes a > b + bool ret; + if (cmp < 0) { a = &rhs; b = this; ret = true; } + else { a = this; b = &rhs; ret = false; } + + Type borrow = 0; + for (size_t i = 0; i < a->count_; i++) { + Type d = a->digits_[i] - borrow; + if (i < b->count_) + d -= b->digits_[i]; + borrow = (d > a->digits_[i]) ? 1 : 0; + out->digits_[i] = d; + if (d != 0) + out->count_ = i + 1; + } + + return ret; + } + + int Compare(const BigInteger& rhs) const { + if (count_ != rhs.count_) + return count_ < rhs.count_ ? -1 : 1; + + for (size_t i = count_; i-- > 0;) + if (digits_[i] != rhs.digits_[i]) + return digits_[i] < rhs.digits_[i] ? -1 : 1; + + return 0; + } + + size_t GetCount() const { return count_; } + Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + +private: + void AppendDecimal64(const char* begin, const char* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + static uint64_t ParseUint64(const char* begin, const char* end) { + uint64_t r = 0; + for (const char* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); + r = r * 10u + static_cast(*p - '0'); + } + return r; + } + + // Assume a * b + k < 2^128 + static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t low = _umul128(a, b, outHigh) + k; + if (low < k) + (*outHigh)++; + return low; +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(a) * static_cast(b); + p += k; + *outHigh = static_cast(p >> 64); + return static_cast(p); +#else + const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; + uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; + x1 += (x0 >> 32); // can't give carry + x1 += x2; + if (x1 < x2) + x3 += (static_cast(1) << 32); + uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); + uint64_t hi = x3 + (x1 >> 32); + + lo += k; + if (lo < k) + hi++; + *outHigh = hi; + return lo; +#endif + } + + static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 + static const size_t kCapacity = kBitCount / sizeof(Type); + static const size_t kTypeBit = sizeof(Type) * 8; + + Type digits_[kCapacity]; + size_t count_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/rapidjson/internal/clzll.h b/rapidjson/internal/clzll.h new file mode 100644 index 0000000..8fc5118 --- /dev/null +++ b/rapidjson/internal/clzll.h @@ -0,0 +1,71 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_CLZLL_H_ +#define RAPIDJSON_CLZLL_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && !defined(UNDER_CE) +#include +#if defined(_WIN64) +#pragma intrinsic(_BitScanReverse64) +#else +#pragma intrinsic(_BitScanReverse) +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline uint32_t clzll(uint64_t x) { + // Passing 0 to __builtin_clzll is UB in GCC and results in an + // infinite loop in the software implementation. + RAPIDJSON_ASSERT(x != 0); + +#if defined(_MSC_VER) && !defined(UNDER_CE) + unsigned long r = 0; +#if defined(_WIN64) + _BitScanReverse64(&r, x); +#else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast(x >> 32))) + return 63 - (r + 32); + + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast(x & 0xFFFFFFFF)); +#endif // _WIN64 + + return 63 - r; +#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll) + // __builtin_clzll wrapper + return static_cast(__builtin_clzll(x)); +#else + // naive version + uint32_t r = 0; + while (!(x & (static_cast(1) << 63))) { + x <<= 1; + ++r; + } + + return r; +#endif // _MSC_VER +} + +#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_CLZLL_H_ diff --git a/rapidjson/internal/diyfp.h b/rapidjson/internal/diyfp.h new file mode 100644 index 0000000..a40797e --- /dev/null +++ b/rapidjson/internal/diyfp.h @@ -0,0 +1,257 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DIYFP_H_ +#define RAPIDJSON_DIYFP_H_ + +#include "../rapidjson.h" +#include "clzll.h" +#include + +#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) +#include +#pragma intrinsic(_umul128) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +struct DiyFp { + DiyFp() : f(), e() {} + + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + + explicit DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(f) * static_cast(rhs.f); + uint64_t h = static_cast(p >> 64); + uint64_t l = static_cast(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { + int s = static_cast(clzll(f)); + return DiyFp(f << s, e - s); + } + + DiyFp NormalizeBoundary() const { + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + double ToDouble() const { + union { + double d; + uint64_t u64; + }u; + RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask); + if (e < kDpDenormalExponent) { + // Underflow. + return 0.0; + } + if (e >= kDpMaxExponent) { + // Overflow. + return std::numeric_limits::infinity(); + } + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMaxExponent = 0x7FF - kDpExponentBias; + static const int kDpMinExponent = -kDpExponentBias; + static const int kDpDenormalExponent = -kDpExponentBias + 1; + static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPowerByIndex(size_t index) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), + RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), + RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), + RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), + RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), + RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), + RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), + RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), + RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), + RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), + RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), + RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), + RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), + RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), + RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), + RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), + RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), + RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), + RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), + RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), + RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), + RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), + RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), + RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), + RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), + RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), + RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), + RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), + RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), + RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), + RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), + RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), + RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), + RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), + RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), + RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), + RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), + RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), + RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), + RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), + RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), + RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + RAPIDJSON_ASSERT(index < 87); + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast(dk); + if (dk - k > 0.0) + k++; + + unsigned index = static_cast((k >> 3) + 1); + *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table + + return GetCachedPowerByIndex(index); +} + +inline DiyFp GetCachedPower10(int exp, int *outExp) { + RAPIDJSON_ASSERT(exp >= -348); + unsigned index = static_cast(exp + 348) / 8u; + *outExp = -348 + static_cast(index) * 8; + return GetCachedPowerByIndex(index); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +RAPIDJSON_DIAG_OFF(padded) +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DIYFP_H_ diff --git a/rapidjson/internal/dtoa.h b/rapidjson/internal/dtoa.h new file mode 100644 index 0000000..621402f --- /dev/null +++ b/rapidjson/internal/dtoa.h @@ -0,0 +1,245 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DTOA_ +#define RAPIDJSON_DTOA_ + +#include "itoa.h" // GetDigitsLut() +#include "diyfp.h" +#include "ieee754.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 +#endif + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline int CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + // Will not reach 10 digits in DigitGen() + //if (n < 1000000000) return 9; + //return 10; + return 9; +} + +inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + *len = 0; + + while (kappa > 0) { + uint32_t d = 0; + switch (kappa) { + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default:; + } + if (d || *len) + buffer[(*len)++] = static_cast('0' + static_cast(d)); + kappa--; + uint64_t tmp = (static_cast(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast('0' + d); + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + int index = -kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline char* WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = static_cast('0' + static_cast(K / 100)); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = static_cast('0' + static_cast(K)); + + return buffer; +} + +inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (0 <= k && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + return &buffer[kk + 2]; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); + buffer[kk] = '.'; + if (0 > k + maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[kk + 2]; // Reserve one zero + } + else + return &buffer[length + 1]; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + std::memmove(&buffer[offset], &buffer[0], static_cast(length)); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + if (length - kk > maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = maxDecimalPlaces + 1; i > 2; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[3]; // Reserve one zero + } + else + return &buffer[length + offset]; + } + else if (kk < -maxDecimalPlaces) { + // Truncate to zero + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + return WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + return WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { + RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); + Double d(value); + if (d.IsZero()) { + if (d.Sign()) + *buffer++ = '-'; // -0.0, Issue #289 + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + return Prettify(buffer, length, K, maxDecimalPlaces); + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DTOA_ diff --git a/rapidjson/internal/ieee754.h b/rapidjson/internal/ieee754.h new file mode 100644 index 0000000..68c9e96 --- /dev/null +++ b/rapidjson/internal/ieee754.h @@ -0,0 +1,78 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_IEEE754_ +#define RAPIDJSON_IEEE754_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class Double { +public: + Double() {} + Double(double d) : d_(d) {} + Double(uint64_t u) : u_(u) {} + + double Value() const { return d_; } + uint64_t Uint64Value() const { return u_; } + + double NextPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + return Double(u_ + 1).Value(); + } + + bool Sign() const { return (u_ & kSignMask) != 0; } + uint64_t Significand() const { return u_ & kSignificandMask; } + int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } + + bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } + bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } + bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } + + uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } + + static int EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else + return order + 1074; + } + +private: + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const int kDenormalExponent = 1 - kExponentBias; + static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + union { + double d_; + uint64_t u_; + }; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_IEEE754_ diff --git a/rapidjson/internal/itoa.h b/rapidjson/internal/itoa.h new file mode 100644 index 0000000..9fe8c93 --- /dev/null +++ b/rapidjson/internal/itoa.h @@ -0,0 +1,308 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ITOA_ +#define RAPIDJSON_ITOA_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', + '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', + '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', + '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', + '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', + '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', + '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', + '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', + '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', + '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' + }; + return cDigitsLut; +} + +inline char* u32toa(uint32_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + + const char* cDigitsLut = GetDigitsLut(); + + if (value < 10000) { + const uint32_t d1 = (value / 100) << 1; + const uint32_t d2 = (value % 100) << 1; + + if (value >= 1000) + *buffer++ = cDigitsLut[d1]; + if (value >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else if (value < 100000000) { + // value = bbbbcccc + const uint32_t b = value / 10000; + const uint32_t c = value % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + else { + // value = aabbbbcccc in decimal + + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; + + if (a >= 10) { + const unsigned i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else + *buffer++ = static_cast('0' + static_cast(a)); + + const uint32_t b = value / 10000; // 0 to 9999 + const uint32_t c = value % 10000; // 0 to 9999 + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + return buffer; +} + +inline char* i32toa(int32_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + uint32_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u32toa(u, buffer); +} + +inline char* u64toa(uint64_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; + const uint64_t kTen10 = kTen8 * 100; + const uint64_t kTen11 = kTen8 * 1000; + const uint64_t kTen12 = kTen8 * 10000; + const uint64_t kTen13 = kTen8 * 100000; + const uint64_t kTen14 = kTen8 * 1000000; + const uint64_t kTen15 = kTen8 * 10000000; + const uint64_t kTen16 = kTen8 * kTen8; + + if (value < kTen8) { + uint32_t v = static_cast(value); + if (v < 10000) { + const uint32_t d1 = (v / 100) << 1; + const uint32_t d2 = (v % 100) << 1; + + if (v >= 1000) + *buffer++ = cDigitsLut[d1]; + if (v >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (v >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else { + // value = bbbbcccc + const uint32_t b = v / 10000; + const uint32_t c = v % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + } + else if (value < kTen16) { + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + if (value >= kTen15) + *buffer++ = cDigitsLut[d1]; + if (value >= kTen14) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= kTen13) + *buffer++ = cDigitsLut[d2]; + if (value >= kTen12) + *buffer++ = cDigitsLut[d2 + 1]; + if (value >= kTen11) + *buffer++ = cDigitsLut[d3]; + if (value >= kTen10) + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; + + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + else { + const uint32_t a = static_cast(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast('0' + static_cast(a)); + else if (a < 100) { + const uint32_t i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else if (a < 1000) { + *buffer++ = static_cast('0' + static_cast(a / 100)); + + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else { + const uint32_t i = (a / 100) << 1; + const uint32_t j = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } + + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + + return buffer; +} + +inline char* i64toa(int64_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + uint64_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u64toa(u, buffer); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ITOA_ diff --git a/rapidjson/internal/meta.h b/rapidjson/internal/meta.h new file mode 100644 index 0000000..27092dc --- /dev/null +++ b/rapidjson/internal/meta.h @@ -0,0 +1,186 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_META_H_ +#define RAPIDJSON_INTERNAL_META_H_ + +#include "../rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(6334) +#endif + +#if RAPIDJSON_HAS_CXX11_TYPETRAITS +#include +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType TrueType; +typedef BoolType FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; +template struct SelectIfCond : SelectIfImpl::template Apply {}; +template struct SelectIf : SelectIfCond {}; + +template struct AndExprCond : FalseType {}; +template <> struct AndExprCond : TrueType {}; +template struct OrExprCond : TrueType {}; +template <> struct OrExprCond : FalseType {}; + +template struct BoolExpr : SelectIf::Type {}; +template struct NotExpr : SelectIf::Type {}; +template struct AndExpr : AndExprCond::Type {}; +template struct OrExpr : OrExprCond::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template struct AddConst { typedef const T Type; }; +template struct MaybeAddConst : SelectIfCond {}; +template struct RemoveConst { typedef T Type; }; +template struct RemoveConst { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template struct IsSame : FalseType {}; +template struct IsSame : TrueType {}; + +template struct IsConst : FalseType {}; +template struct IsConst : TrueType {}; + +template +struct IsMoreConst + : AndExpr::Type, typename RemoveConst::Type>, + BoolType::Value >= IsConst::Value> >::Type {}; + +template struct IsPointer : FalseType {}; +template struct IsPointer : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template struct IsBaseOf + : BoolType< ::std::is_base_of::value> {}; + +#else // simplified version adopted from Boost + +template struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template + static Yes Check(const D*, T); + static No Check(const B*, int); + + struct Host { + operator const B*() const; + operator const D*(); + }; + + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; +}; + +template struct IsBaseOf + : OrExpr, BoolExpr > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template struct EnableIfCond { typedef T Type; }; +template struct EnableIfCond { /* empty */ }; + +template struct DisableIfCond { typedef T Type; }; +template struct DisableIfCond { /* empty */ }; + +template +struct EnableIf : EnableIfCond {}; + +template +struct DisableIf : DisableIfCond {}; + +// SFINAE helpers +struct SfinaeTag {}; +template struct RemoveSfinaeTag; +template struct RemoveSfinaeTag { typedef T Type; }; + +#define RAPIDJSON_REMOVEFPTR_(type) \ + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + +#define RAPIDJSON_ENABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type + +} // namespace internal +RAPIDJSON_NAMESPACE_END +//@endcond + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_META_H_ diff --git a/rapidjson/internal/pow10.h b/rapidjson/internal/pow10.h new file mode 100644 index 0000000..eae1a43 --- /dev/null +++ b/rapidjson/internal/pow10.h @@ -0,0 +1,55 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POW10_ +#define RAPIDJSON_POW10_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n non-negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POW10_ diff --git a/rapidjson/internal/regex.h b/rapidjson/internal/regex.h new file mode 100644 index 0000000..6446c40 --- /dev/null +++ b/rapidjson/internal/regex.h @@ -0,0 +1,739 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_REGEX_H_ +#define RAPIDJSON_INTERNAL_REGEX_H_ + +#include "../allocators.h" +#include "../stream.h" +#include "stack.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifndef RAPIDJSON_REGEX_VERBOSE +#define RAPIDJSON_REGEX_VERBOSE 0 +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// DecodedStream + +template +class DecodedStream { +public: + DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } + unsigned Peek() { return codepoint_; } + unsigned Take() { + unsigned c = codepoint_; + if (c) // No further decoding when '\0' + Decode(); + return c; + } + +private: + void Decode() { + if (!Encoding::Decode(ss_, &codepoint_)) + codepoint_ = 0; + } + + SourceStream& ss_; + unsigned codepoint_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericRegex + +static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 +static const SizeType kRegexInvalidRange = ~SizeType(0); + +template +class GenericRegexSearch; + +//! Regular expression engine with subset of ECMAscript grammar. +/*! + Supported regular expression syntax: + - \c ab Concatenation + - \c a|b Alternation + - \c a? Zero or one + - \c a* Zero or more + - \c a+ One or more + - \c a{3} Exactly 3 times + - \c a{3,} At least 3 times + - \c a{3,5} 3 to 5 times + - \c (ab) Grouping + - \c ^a At the beginning + - \c a$ At the end + - \c . Any character + - \c [abc] Character classes + - \c [a-c] Character class range + - \c [a-z0-9_] Character class combination + - \c [^abc] Negated character classes + - \c [^a-c] Negated character class range + - \c [\b] Backspace (U+0008) + - \c \\| \\\\ ... Escape characters + - \c \\f Form feed (U+000C) + - \c \\n Line feed (U+000A) + - \c \\r Carriage return (U+000D) + - \c \\t Tab (U+0009) + - \c \\v Vertical tab (U+000B) + + \note This is a Thompson NFA engine, implemented with reference to + Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", + https://swtch.com/~rsc/regexp/regexp1.html +*/ +template +class GenericRegex { +public: + typedef Encoding EncodingType; + typedef typename Encoding::Ch Ch; + template friend class GenericRegexSearch; + + GenericRegex(const Ch* source, Allocator* allocator = 0) : + ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), + states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), + anchorBegin_(), anchorEnd_() + { + GenericStringStream ss(source); + DecodedStream, Encoding> ds(ss); + Parse(ds); + } + + ~GenericRegex() + { + RAPIDJSON_DELETE(ownAllocator_); + } + + bool IsValid() const { + return root_ != kRegexInvalidState; + } + +private: + enum Operator { + kZeroOrOne, + kZeroOrMore, + kOneOrMore, + kConcatenation, + kAlternation, + kLeftParenthesis + }; + + static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.' + static const unsigned kRangeCharacterClass = 0xFFFFFFFE; + static const unsigned kRangeNegationFlag = 0x80000000; + + struct Range { + unsigned start; // + unsigned end; + SizeType next; + }; + + struct State { + SizeType out; //!< Equals to kInvalid for matching state + SizeType out1; //!< Equals to non-kInvalid for split + SizeType rangeStart; + unsigned codepoint; + }; + + struct Frag { + Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {} + SizeType start; + SizeType out; //!< link-list of all output states + SizeType minIndex; + }; + + State& GetState(SizeType index) { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + const State& GetState(SizeType index) const { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + Range& GetRange(SizeType index) { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + const Range& GetRange(SizeType index) const { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + template + void Parse(DecodedStream& ds) { + Stack operandStack(allocator_, 256); // Frag + Stack operatorStack(allocator_, 256); // Operator + Stack atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis) + + *atomCountStack.template Push() = 0; + + unsigned codepoint; + while (ds.Peek() != 0) { + switch (codepoint = ds.Take()) { + case '^': + anchorBegin_ = true; + break; + + case '$': + anchorEnd_ = true; + break; + + case '|': + while (!operatorStack.Empty() && *operatorStack.template Top() < kAlternation) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + *operatorStack.template Push() = kAlternation; + *atomCountStack.template Top() = 0; + break; + + case '(': + *operatorStack.template Push() = kLeftParenthesis; + *atomCountStack.template Push() = 0; + break; + + case ')': + while (!operatorStack.Empty() && *operatorStack.template Top() != kLeftParenthesis) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + if (operatorStack.Empty()) + return; + operatorStack.template Pop(1); + atomCountStack.template Pop(1); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '?': + if (!Eval(operandStack, kZeroOrOne)) + return; + break; + + case '*': + if (!Eval(operandStack, kZeroOrMore)) + return; + break; + + case '+': + if (!Eval(operandStack, kOneOrMore)) + return; + break; + + case '{': + { + unsigned n, m; + if (!ParseUnsigned(ds, &n)) + return; + + if (ds.Peek() == ',') { + ds.Take(); + if (ds.Peek() == '}') + m = kInfinityQuantifier; + else if (!ParseUnsigned(ds, &m) || m < n) + return; + } + else + m = n; + + if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') + return; + ds.Take(); + } + break; + + case '.': + PushOperand(operandStack, kAnyCharacterClass); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '[': + { + SizeType range; + if (!ParseRange(ds, &range)) + return; + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass); + GetState(s).rangeStart = range; + *operandStack.template Push() = Frag(s, s, s); + } + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '\\': // Escape character + if (!CharacterEscape(ds, &codepoint)) + return; // Unsupported escape character + // fall through to default + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + default: // Pattern character + PushOperand(operandStack, codepoint); + ImplicitConcatenation(atomCountStack, operatorStack); + } + } + + while (!operatorStack.Empty()) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + + // Link the operand to matching state. + if (operandStack.GetSize() == sizeof(Frag)) { + Frag* e = operandStack.template Pop(1); + Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); + root_ = e->start; + +#if RAPIDJSON_REGEX_VERBOSE + printf("root: %d\n", root_); + for (SizeType i = 0; i < stateCount_ ; i++) { + State& s = GetState(i); + printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); + } + printf("\n"); +#endif + } + } + + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { + State* s = states_.template Push(); + s->out = out; + s->out1 = out1; + s->codepoint = codepoint; + s->rangeStart = kRegexInvalidRange; + return stateCount_++; + } + + void PushOperand(Stack& operandStack, unsigned codepoint) { + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); + *operandStack.template Push() = Frag(s, s, s); + } + + void ImplicitConcatenation(Stack& atomCountStack, Stack& operatorStack) { + if (*atomCountStack.template Top()) + *operatorStack.template Push() = kConcatenation; + (*atomCountStack.template Top())++; + } + + SizeType Append(SizeType l1, SizeType l2) { + SizeType old = l1; + while (GetState(l1).out != kRegexInvalidState) + l1 = GetState(l1).out; + GetState(l1).out = l2; + return old; + } + + void Patch(SizeType l, SizeType s) { + for (SizeType next; l != kRegexInvalidState; l = next) { + next = GetState(l).out; + GetState(l).out = s; + } + } + + bool Eval(Stack& operandStack, Operator op) { + switch (op) { + case kConcatenation: + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); + { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + Patch(e1.out, e2.start); + *operandStack.template Push() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); + } + return true; + + case kAlternation: + if (operandStack.GetSize() >= sizeof(Frag) * 2) { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + SizeType s = NewState(e1.start, e2.start, 0); + *operandStack.template Push() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); + return true; + } + return false; + + case kZeroOrOne: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + *operandStack.template Push() = Frag(s, Append(e.out, s), e.minIndex); + return true; + } + return false; + + case kZeroOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(s, s, e.minIndex); + return true; + } + return false; + + case kOneOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(e.start, s, e.minIndex); + return true; + } + return false; + + default: + // syntax error (e.g. unclosed kLeftParenthesis) + return false; + } + } + + bool EvalQuantifier(Stack& operandStack, unsigned n, unsigned m) { + RAPIDJSON_ASSERT(n <= m); + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag)); + + if (n == 0) { + if (m == 0) // a{0} not support + return false; + else if (m == kInfinityQuantifier) + Eval(operandStack, kZeroOrMore); // a{0,} -> a* + else { + Eval(operandStack, kZeroOrOne); // a{0,5} -> a? + for (unsigned i = 0; i < m - 1; i++) + CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a? + for (unsigned i = 0; i < m - 1; i++) + Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a? + } + return true; + } + + for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a + CloneTopOperand(operandStack); + + if (m == kInfinityQuantifier) + Eval(operandStack, kOneOrMore); // a{3,} -> a a a+ + else if (m > n) { + CloneTopOperand(operandStack); // a{3,5} -> a a a a + Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a? + for (unsigned i = n; i < m - 1; i++) + CloneTopOperand(operandStack); // a{3,5} -> a a a a? a? + for (unsigned i = n; i < m; i++) + Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a? + } + + for (unsigned i = 0; i < n - 1; i++) + Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? + + return true; + } + + static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } + + void CloneTopOperand(Stack& operandStack) { + const Frag src = *operandStack.template Top(); // Copy constructor to prevent invalidation + SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) + State* s = states_.template Push(count); + memcpy(s, &GetState(src.minIndex), count * sizeof(State)); + for (SizeType j = 0; j < count; j++) { + if (s[j].out != kRegexInvalidState) + s[j].out += count; + if (s[j].out1 != kRegexInvalidState) + s[j].out1 += count; + } + *operandStack.template Push() = Frag(src.start + count, src.out + count, src.minIndex + count); + stateCount_ += count; + } + + template + bool ParseUnsigned(DecodedStream& ds, unsigned* u) { + unsigned r = 0; + if (ds.Peek() < '0' || ds.Peek() > '9') + return false; + while (ds.Peek() >= '0' && ds.Peek() <= '9') { + if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295 + return false; // overflow + r = r * 10 + (ds.Take() - '0'); + } + *u = r; + return true; + } + + template + bool ParseRange(DecodedStream& ds, SizeType* range) { + bool isBegin = true; + bool negate = false; + int step = 0; + SizeType start = kRegexInvalidRange; + SizeType current = kRegexInvalidRange; + unsigned codepoint; + while ((codepoint = ds.Take()) != 0) { + if (isBegin) { + isBegin = false; + if (codepoint == '^') { + negate = true; + continue; + } + } + + switch (codepoint) { + case ']': + if (start == kRegexInvalidRange) + return false; // Error: nothing inside [] + if (step == 2) { // Add trailing '-' + SizeType r = NewRange('-'); + RAPIDJSON_ASSERT(current != kRegexInvalidRange); + GetRange(current).next = r; + } + if (negate) + GetRange(start).start |= kRangeNegationFlag; + *range = start; + return true; + + case '\\': + if (ds.Peek() == 'b') { + ds.Take(); + codepoint = 0x0008; // Escape backspace character + } + else if (!CharacterEscape(ds, &codepoint)) + return false; + // fall through to default + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + default: + switch (step) { + case 1: + if (codepoint == '-') { + step++; + break; + } + // fall through to step 0 for other characters + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + case 0: + { + SizeType r = NewRange(codepoint); + if (current != kRegexInvalidRange) + GetRange(current).next = r; + if (start == kRegexInvalidRange) + start = r; + current = r; + } + step = 1; + break; + + default: + RAPIDJSON_ASSERT(step == 2); + GetRange(current).end = codepoint; + step = 0; + } + } + } + return false; + } + + SizeType NewRange(unsigned codepoint) { + Range* r = ranges_.template Push(); + r->start = r->end = codepoint; + r->next = kRegexInvalidRange; + return rangeCount_++; + } + + template + bool CharacterEscape(DecodedStream& ds, unsigned* escapedCodepoint) { + unsigned codepoint; + switch (codepoint = ds.Take()) { + case '^': + case '$': + case '|': + case '(': + case ')': + case '?': + case '*': + case '+': + case '.': + case '[': + case ']': + case '{': + case '}': + case '\\': + *escapedCodepoint = codepoint; return true; + case 'f': *escapedCodepoint = 0x000C; return true; + case 'n': *escapedCodepoint = 0x000A; return true; + case 'r': *escapedCodepoint = 0x000D; return true; + case 't': *escapedCodepoint = 0x0009; return true; + case 'v': *escapedCodepoint = 0x000B; return true; + default: + return false; // Unsupported escape character + } + } + + Allocator* ownAllocator_; + Allocator* allocator_; + Stack states_; + Stack ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; + + static const unsigned kInfinityQuantifier = ~0u; + + // For SearchWithAnchoring() + bool anchorBegin_; + bool anchorEnd_; +}; + +template +class GenericRegexSearch { +public: + typedef typename RegexType::EncodingType Encoding; + typedef typename Encoding::Ch Ch; + + GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : + regex_(regex), allocator_(allocator), ownAllocator_(0), + state0_(allocator, 0), state1_(allocator, 0), stateSet_() + { + RAPIDJSON_ASSERT(regex_.IsValid()); + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); + state0_.template Reserve(regex_.stateCount_); + state1_.template Reserve(regex_.stateCount_); + } + + ~GenericRegexSearch() { + Allocator::Free(stateSet_); + RAPIDJSON_DELETE(ownAllocator_); + } + + template + bool Match(InputStream& is) { + return SearchWithAnchoring(is, true, true); + } + + bool Match(const Ch* s) { + GenericStringStream is(s); + return Match(is); + } + + template + bool Search(InputStream& is) { + return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_); + } + + bool Search(const Ch* s) { + GenericStringStream is(s); + return Search(is); + } + +private: + typedef typename RegexType::State State; + typedef typename RegexType::Range Range; + + template + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) { + DecodedStream ds(is); + + state0_.Clear(); + Stack *current = &state0_, *next = &state1_; + const size_t stateSetSize = GetStateSetSize(); + std::memset(stateSet_, 0, stateSetSize); + + bool matched = AddState(*current, regex_.root_); + unsigned codepoint; + while (!current->Empty() && (codepoint = ds.Take()) != 0) { + std::memset(stateSet_, 0, stateSetSize); + next->Clear(); + matched = false; + for (const SizeType* s = current->template Bottom(); s != current->template End(); ++s) { + const State& sr = regex_.GetState(*s); + if (sr.codepoint == codepoint || + sr.codepoint == RegexType::kAnyCharacterClass || + (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) + { + matched = AddState(*next, sr.out) || matched; + if (!anchorEnd && matched) + return true; + } + if (!anchorBegin) + AddState(*next, regex_.root_); + } + internal::Swap(current, next); + } + + return matched; + } + + size_t GetStateSetSize() const { + return (regex_.stateCount_ + 31) / 32 * 4; + } + + // Return whether the added states is a match state + bool AddState(Stack& l, SizeType index) { + RAPIDJSON_ASSERT(index != kRegexInvalidState); + + const State& s = regex_.GetState(index); + if (s.out1 != kRegexInvalidState) { // Split + bool matched = AddState(l, s.out); + return AddState(l, s.out1) || matched; + } + else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) { + stateSet_[index >> 5] |= (1u << (index & 31)); + *l.template PushUnsafe() = index; + } + return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. + } + + bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { + bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0; + while (rangeIndex != kRegexInvalidRange) { + const Range& r = regex_.GetRange(rangeIndex); + if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end) + return yes; + rangeIndex = r.next; + } + return !yes; + } + + const RegexType& regex_; + Allocator* allocator_; + Allocator* ownAllocator_; + Stack state0_; + Stack state1_; + uint32_t* stateSet_; +}; + +typedef GenericRegex > Regex; +typedef GenericRegexSearch RegexSearch; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_REGEX_H_ diff --git a/rapidjson/internal/stack.h b/rapidjson/internal/stack.h new file mode 100644 index 0000000..73abd70 --- /dev/null +++ b/rapidjson/internal/stack.h @@ -0,0 +1,232 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +#include "../allocators.h" +#include "swap.h" +#include + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template +class Stack { +public: + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); + } + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { + // Expand the stack if needed + if (RAPIDJSON_UNLIKELY(static_cast(sizeof(T) * count) > (stackEnd_ - stackTop_))) + Expand(count); + } + + template + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + Reserve(count); + return PushUnsafe(count); + } + + template + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { + RAPIDJSON_ASSERT(stackTop_); + RAPIDJSON_ASSERT(static_cast(sizeof(T) * count) <= (stackEnd_ - stackTop_)); + T* ret = reinterpret_cast(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast(stackTop_); + } + + template + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + const T* Top() const { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + T* End() { return reinterpret_cast(stackTop_); } + + template + const T* End() const { return reinterpret_cast(stackTop_); } + + template + T* Bottom() { return reinterpret_cast(stack_); } + + template + const T* Bottom() const { return reinterpret_cast(stack_); } + + bool HasAllocator() const { + return allocator_ != 0; + } + + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } + +private: + template + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STACK_H_ diff --git a/rapidjson/internal/strfunc.h b/rapidjson/internal/strfunc.h new file mode 100644 index 0000000..baecb6c --- /dev/null +++ b/rapidjson/internal/strfunc.h @@ -0,0 +1,69 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +#include "../stream.h" +#include + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template +inline SizeType StrLen(const Ch* s) { + RAPIDJSON_ASSERT(s != 0); + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +template <> +inline SizeType StrLen(const char* s) { + return SizeType(std::strlen(s)); +} + +template <> +inline SizeType StrLen(const wchar_t* s) { + return SizeType(std::wcslen(s)); +} + +//! Returns number of code points in a encoded string. +template +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + RAPIDJSON_ASSERT(s != 0); + RAPIDJSON_ASSERT(outCount != 0); + GenericStringStream is(s); + const typename Encoding::Ch* end = s + length; + SizeType count = 0; + while (is.src_ < end) { + unsigned codepoint; + if (!Encoding::Decode(is, &codepoint)) + return false; + count++; + } + *outCount = count; + return true; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/rapidjson/internal/strtod.h b/rapidjson/internal/strtod.h new file mode 100644 index 0000000..d61a67a --- /dev/null +++ b/rapidjson/internal/strtod.h @@ -0,0 +1,290 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRTOD_ +#define RAPIDJSON_STRTOD_ + +#include "ieee754.h" +#include "biginteger.h" +#include "diyfp.h" +#include "pow10.h" +#include +#include + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline double FastPath(double significand, int exp) { + if (exp < -308) + return 0.0; + else if (exp >= 0) + return significand * internal::Pow10(exp); + else + return significand / internal::Pow10(-exp); +} + +inline double StrtodNormalPrecision(double d, int p) { + if (p < -308) { + // Prevent expSum < -308, making Pow10(p) = 0 + d = FastPath(d, -308); + d = FastPath(d, p + 308); + } + else + d = FastPath(d, p); + return d; +} + +template +inline T Min3(T a, T b, T c) { + T m = a; + if (m > b) m = b; + if (m > c) m = c; + return m; +} + +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { + const Double db(b); + const uint64_t bInt = db.IntegerSignificand(); + const int bExp = db.IntegerExponent(); + const int hExp = bExp - 1; + + int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + BigInteger dS = d; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); + + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); + + BigInteger hS(1); + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); + + BigInteger delta(0); + dS.Difference(bS, &delta); + + return delta.Compare(hS); +} + +inline bool StrtodFast(double d, int p, double* result) { + // Use fast path for string-to-double conversion if possible + // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ + if (p > 22 && p < 22 + 16) { + // Fast Path Cases In Disguise + d *= internal::Pow10(p - 22); + p = 22; + } + + if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 + *result = FastPath(d, p); + return true; + } + else + return false; +} + +// Compute an approximation and see if it is within 1/2 ULP +inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) { + uint64_t significand = 0; + int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 + for (; i < dLen; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) + break; + significand = significand * 10u + static_cast(decimals[i] - '0'); + } + + if (i < dLen && decimals[i] >= '5') // Rounding + significand++; + + int remaining = dLen - i; + const int kUlpShift = 3; + const int kUlp = 1 << kUlpShift; + int64_t error = (remaining == 0) ? 0 : kUlp / 2; + + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; + + dExp += remaining; + + int actualExp; + DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); + if (actualExp != dExp) { + static const DiyFp kPow10[] = { + DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1 + DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2 + DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3 + DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4 + DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5 + DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6 + DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7 + }; + int adjustment = dExp - actualExp; + RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8); + v = v * kPow10[adjustment - 1]; + if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + + v = v * cachedPower; + + error += kUlp + (error == 0 ? 0 : 1); + + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; + + const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + int precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { + int scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; + error = (error >> scaleExp) + 1 + kUlp; + precisionSize -= scaleExp; + } + + DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); + const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; + const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; + if (precisionBits >= halfWay + static_cast(error)) { + rounded.f++; + if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) + rounded.f >>= 1; + rounded.e++; + } + } + + *result = rounded.ToDouble(); + + return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); +} + +inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) { + RAPIDJSON_ASSERT(dLen >= 0); + const BigInteger dInt(decimals, static_cast(dLen)); + Double a(approx); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return a.NextPositiveDouble(); + else + return a.Value(); + } + else // adjustment + return a.NextPositiveDouble(); +} + +inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + + double result = 0.0; + if (StrtodFast(d, p, &result)) + return result; + + RAPIDJSON_ASSERT(length <= INT_MAX); + int dLen = static_cast(length); + + RAPIDJSON_ASSERT(length >= decimalPosition); + RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX); + int dExpAdjust = static_cast(length - decimalPosition); + + RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust); + int dExp = exp - dExpAdjust; + + // Make sure length+dExp does not overflow + RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen); + + // Trim leading zeros + while (dLen > 0 && *decimals == '0') { + dLen--; + decimals++; + } + + // Trim trailing zeros + while (dLen > 0 && decimals[dLen - 1] == '0') { + dLen--; + dExp++; + } + + if (dLen == 0) { // Buffer only contains zeros. + return 0.0; + } + + // Trim right-most digits + const int kMaxDecimalDigit = 767 + 1; + if (dLen > kMaxDecimalDigit) { + dExp += dLen - kMaxDecimalDigit; + dLen = kMaxDecimalDigit; + } + + // If too small, underflow to zero. + // Any x <= 10^-324 is interpreted as zero. + if (dLen + dExp <= -324) + return 0.0; + + // If too large, overflow to infinity. + // Any x >= 10^309 is interpreted as +infinity. + if (dLen + dExp > 309) + return std::numeric_limits::infinity(); + + if (StrtodDiyFp(decimals, dLen, dExp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison + return StrtodBigInteger(result, decimals, dLen, dExp); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRTOD_ diff --git a/rapidjson/internal/swap.h b/rapidjson/internal/swap.h new file mode 100644 index 0000000..2cf92f9 --- /dev/null +++ b/rapidjson/internal/swap.h @@ -0,0 +1,46 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_SWAP_H_ +#define RAPIDJSON_INTERNAL_SWAP_H_ + +#include "../rapidjson.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom swap() to avoid dependency on C++ header +/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. + \note This has the same semantics as std::swap(). +*/ +template +inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { + T tmp = a; + a = b; + b = tmp; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/rapidjson/istreamwrapper.h b/rapidjson/istreamwrapper.h new file mode 100644 index 0000000..01437ec --- /dev/null +++ b/rapidjson/istreamwrapper.h @@ -0,0 +1,128 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ISTREAMWRAPPER_H_ +#define RAPIDJSON_ISTREAMWRAPPER_H_ + +#include "stream.h" +#include +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::istringstream + - \c std::stringstream + - \c std::wistringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wifstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_istream. +*/ + +template +class BasicIStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + + //! Constructor. + /*! + \param stream stream opened for read. + */ + BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + Read(); + } + + //! Constructor. + /*! + \param stream stream opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; + } + +private: + BasicIStreamWrapper(); + BasicIStreamWrapper(const BasicIStreamWrapper&); + BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); + + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = bufferSize_; + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (!stream_.read(buffer_, static_cast(bufferSize_))) { + readCount_ = static_cast(stream_.gcount()); + *(bufferLast_ = buffer_ + readCount_) = '\0'; + eof_ = true; + } + } + } + + StreamType &stream_; + Ch peekBuffer_[4], *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +typedef BasicIStreamWrapper IStreamWrapper; +typedef BasicIStreamWrapper WIStreamWrapper; + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ISTREAMWRAPPER_H_ diff --git a/rapidjson/memorybuffer.h b/rapidjson/memorybuffer.h new file mode 100644 index 0000000..ffbc41e --- /dev/null +++ b/rapidjson/memorybuffer.h @@ -0,0 +1,70 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYBUFFER_H_ +#define RAPIDJSON_MEMORYBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output byte stream. +/*! + This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. + + It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. + + Differences between MemoryBuffer and StringBuffer: + 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. + 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. + + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; +}; + +typedef GenericMemoryBuffer<> MemoryBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { + std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/rapidjson/memorystream.h b/rapidjson/memorystream.h new file mode 100644 index 0000000..77af6c9 --- /dev/null +++ b/rapidjson/memorystream.h @@ -0,0 +1,71 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYSTREAM_H_ +#define RAPIDJSON_MEMORYSTREAM_H_ + +#include "stream.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory input byte stream. +/*! + This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. + + It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. + + Differences between MemoryStream and StringStream: + 1. StringStream has encoding but MemoryStream is a byte stream. + 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. + 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). + \note implements Stream concept +*/ +struct MemoryStream { + typedef char Ch; // byte + + MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + + Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } + Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } + size_t Tell() const { return static_cast(src_ - begin_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return Tell() + 4 <= size_ ? src_ : 0; + } + + const Ch* src_; //!< Current read position. + const Ch* begin_; //!< Original head of the string. + const Ch* end_; //!< End of stream. + size_t size_; //!< Size of the stream. +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/rapidjson/msinttypes/inttypes.h b/rapidjson/msinttypes/inttypes.h new file mode 100644 index 0000000..1811128 --- /dev/null +++ b/rapidjson/msinttypes/inttypes.h @@ -0,0 +1,316 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// miloyip: VC supports inttypes.h since VC2013 +#if _MSC_VER >= 1800 +#include +#else + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + +#endif // _MSC_VER >= 1800 + +#endif // _MSC_INTTYPES_H_ ] diff --git a/rapidjson/msinttypes/stdint.h b/rapidjson/msinttypes/stdint.h new file mode 100644 index 0000000..3d4477b --- /dev/null +++ b/rapidjson/msinttypes/stdint.h @@ -0,0 +1,300 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. +#if _MSC_VER >= 1600 // [ +#include + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +#undef INT8_C +#undef INT16_C +#undef INT32_C +#undef INT64_C +#undef UINT8_C +#undef UINT16_C +#undef UINT32_C +#undef UINT64_C + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#else // ] _MSC_VER >= 1700 [ + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we have to wrap include with 'extern "C++" {}' +// or compiler would give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if defined(__cplusplus) && !defined(_M_ARM) +extern "C" { +#endif +# include +#if defined(__cplusplus) && !defined(_M_ARM) +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] diff --git a/rapidjson/ostreamwrapper.h b/rapidjson/ostreamwrapper.h new file mode 100644 index 0000000..11ed4d3 --- /dev/null +++ b/rapidjson/ostreamwrapper.h @@ -0,0 +1,81 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_OSTREAMWRAPPER_H_ +#define RAPIDJSON_OSTREAMWRAPPER_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::ostringstream + - \c std::stringstream + - \c std::wpstringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wofstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_ostream. +*/ + +template +class BasicOStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} + + void Put(Ch c) { + stream_.put(c); + } + + void Flush() { + stream_.flush(); + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + BasicOStreamWrapper(const BasicOStreamWrapper&); + BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); + + StreamType& stream_; +}; + +typedef BasicOStreamWrapper OStreamWrapper; +typedef BasicOStreamWrapper WOStreamWrapper; + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_OSTREAMWRAPPER_H_ diff --git a/rapidjson/pointer.h b/rapidjson/pointer.h new file mode 100644 index 0000000..90e5903 --- /dev/null +++ b/rapidjson/pointer.h @@ -0,0 +1,1415 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POINTER_H_ +#define RAPIDJSON_POINTER_H_ + +#include "document.h" +#include "internal/itoa.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode +*/ +enum PointerParseErrorCode { + kPointerParseErrorNone = 0, //!< The parse is successful + + kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' + kPointerParseErrorInvalidEscape, //!< Invalid escape + kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment + kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericPointer + +//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. +/*! + This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" + (https://tools.ietf.org/html/rfc6901). + + A JSON pointer is for identifying a specific value in a JSON document + (GenericDocument). It can simplify coding of DOM tree manipulation, because it + can access multiple-level depth of DOM tree with single API call. + + After it parses a string representation (e.g. "/foo/0" or URI fragment + representation (e.g. "#/foo/0") into its internal representation (tokens), + it can be used to resolve a specific value in multiple documents, or sub-tree + of documents. + + Contrary to GenericValue, Pointer can be copy constructed and copy assigned. + Apart from assignment, a Pointer cannot be modified after construction. + + Although Pointer is very convenient, please aware that constructing Pointer + involves parsing and dynamic memory allocation. A special constructor with user- + supplied tokens eliminates these. + + GenericPointer depends on GenericDocument and GenericValue. + + \tparam ValueType The value type of the DOM tree. E.g. GenericValue > + \tparam Allocator The allocator type for allocating memory for internal representation. + + \note GenericPointer uses same encoding of ValueType. + However, Allocator of GenericPointer is independent of Allocator of Value. +*/ +template +class GenericPointer { +public: + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value + + //! A token is the basic units of internal representation. + /*! + A JSON pointer string representation "/foo/123" is parsed to two tokens: + "foo" and 123. 123 will be represented in both numeric form and string form. + They are resolved according to the actual value type (object or array). + + For token that are not numbers, or the numeric value is out of bound + (greater than limits of SizeType), they are only treated as string form + (i.e. the token's index will be equal to kPointerInvalidIndex). + + This struct is public so that user can create a Pointer without parsing and + allocation, using a special constructor. + */ + struct Token { + const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. + SizeType length; //!< Length of the name. + SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. + }; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor. + GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A null-terminated, string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + */ + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, internal::StrLen(source)); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source.c_str(), source.size()); + } +#endif + + //! Constructor that parses a string or URI fragment representation, with length of the source string. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param length Length of source. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Slightly faster than the overload without length. + */ + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, length); + } + + //! Constructor with user-supplied tokens. + /*! + This constructor let user supplies const array of tokens. + This prevents the parsing process and eliminates allocation. + This is preferred for memory constrained environments. + + \param tokens An constant array of tokens representing the JSON pointer. + \param tokenCount Number of tokens. + + \b Example + \code + #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } + #define INDEX(i) { #i, sizeof(#i) - 1, i } + + static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; + static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + // Equivalent to static const Pointer p("/foo/123"); + + #undef NAME + #undef INDEX + \endcode + */ + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Copy constructor. + GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Copy constructor. + GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Destructor. + ~GenericPointer() { + if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. + Allocator::Free(tokens_); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator. + GenericPointer& operator=(const GenericPointer& rhs) { + if (this != &rhs) { + // Do not delete ownAllcator + if (nameBuffer_) + Allocator::Free(tokens_); + + tokenCount_ = rhs.tokenCount_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; + + if (rhs.nameBuffer_) + CopyFromRaw(rhs); // Normally parsed tokens. + else { + tokens_ = rhs.tokens_; // User supplied const tokens. + nameBuffer_ = 0; + } + } + return *this; + } + + //! Swap the content of this pointer with an other. + /*! + \param other The pointer to swap with. + \note Constant complexity. + */ + GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, other.allocator_); + internal::Swap(ownAllocator_, other.ownAllocator_); + internal::Swap(nameBuffer_, other.nameBuffer_); + internal::Swap(tokens_, other.tokens_); + internal::Swap(tokenCount_, other.tokenCount_); + internal::Swap(parseErrorOffset_, other.parseErrorOffset_); + internal::Swap(parseErrorCode_, other.parseErrorCode_); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.pointer, b.pointer); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //@} + + //!@name Append token + //@{ + + //! Append a token and return a new Pointer + /*! + \param token Token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Token& token, Allocator* allocator = 0) const { + GenericPointer r; + r.allocator_ = allocator; + Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); + std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); + r.tokens_[tokenCount_].name = p; + r.tokens_[tokenCount_].length = token.length; + r.tokens_[tokenCount_].index = token.index; + return r; + } + + //! Append a name token with length, and return a new Pointer + /*! + \param name Name to be appended. + \param length Length of name. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { + Token token = { name, length, kPointerInvalidIndex }; + return Append(token, allocator); + } + + //! Append a name token without length, and return a new Pointer + /*! + \param name Name (const Ch*) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const { + return Append(name, internal::StrLen(name), allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Append a name token, and return a new Pointer + /*! + \param name Name to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const std::basic_string& name, Allocator* allocator = 0) const { + return Append(name.c_str(), static_cast(name.size()), allocator); + } +#endif + + //! Append a index token, and return a new Pointer + /*! + \param index Index to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(SizeType index, Allocator* allocator = 0) const { + char buffer[21]; + char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); + SizeType length = static_cast(end - buffer); + buffer[length] = '\0'; + + if (sizeof(Ch) == 1) { + Token token = { reinterpret_cast(buffer), length, index }; + return Append(token, allocator); + } + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) + name[i] = static_cast(buffer[i]); + Token token = { name, length, index }; + return Append(token, allocator); + } + } + + //! Append a token by value, and return a new Pointer + /*! + \param token token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { + if (token.IsString()) + return Append(token.GetString(), token.GetStringLength(), allocator); + else { + RAPIDJSON_ASSERT(token.IsUint64()); + RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); + return Append(static_cast(token.GetUint64()), allocator); + } + } + + //!@name Handling Parse Error + //@{ + + //! Check whether this is a valid pointer. + bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + + //! Get the parsing error offset in code unit. + size_t GetParseErrorOffset() const { return parseErrorOffset_; } + + //! Get the parsing error code. + PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } + + //@} + + //! Get the allocator of this pointer. + Allocator& GetAllocator() { return *allocator_; } + + //!@name Tokens + //@{ + + //! Get the token array (const version only). + const Token* GetTokens() const { return tokens_; } + + //! Get the number of tokens. + size_t GetTokenCount() const { return tokenCount_; } + + //@} + + //!@name Equality/inequality operators + //@{ + + //! Equality operator. + /*! + \note When any pointers are invalid, always returns false. + */ + bool operator==(const GenericPointer& rhs) const { + if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) + return false; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index || + tokens_[i].length != rhs.tokens_[i].length || + (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) + { + return false; + } + } + + return true; + } + + //! Inequality operator. + /*! + \note When any pointers are invalid, always returns true. + */ + bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + + //! Less than operator. + /*! + \note Invalid pointers are always greater than valid ones. + */ + bool operator<(const GenericPointer& rhs) const { + if (!IsValid()) + return false; + if (!rhs.IsValid()) + return true; + + if (tokenCount_ != rhs.tokenCount_) + return tokenCount_ < rhs.tokenCount_; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index) + return tokens_[i].index < rhs.tokens_[i].index; + + if (tokens_[i].length != rhs.tokens_[i].length) + return tokens_[i].length < rhs.tokens_[i].length; + + if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length)) + return cmp < 0; + } + + return false; + } + + //@} + + //!@name Stringify + //@{ + + //! Stringify the pointer into string representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + return Stringify(os); + } + + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool StringifyUriFragment(OutputStream& os) const { + return Stringify(os); + } + + //@} + + //!@name Create value + //@{ + + //! Create a value in a subtree. + /*! + If the value is not exist, it creates all parent values and a JSON Null value. + So it always succeed and return the newly created or existing value. + + Remind that it may change types of parents according to tokens, so it + potentially removes previously stored values. For example, if a document + was an array, and "/foo" is used to create a value, then the document + will be changed to an object, and all existing array elements are lost. + + \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created (a JSON Null value), or already exists value. + */ + ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + bool exist = true; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + if (v->IsArray() && t->name[0] == '-' && t->length == 1) { + v->PushBack(ValueType().Move(), allocator); + v = &((*v)[v->Size() - 1]); + exist = false; + } + else { + if (t->index == kPointerInvalidIndex) { // must be object name + if (!v->IsObject()) + v->SetObject(); // Change to Object + } + else { // object name or array index + if (!v->IsArray() && !v->IsObject()) + v->SetArray(); // Change to Array + } + + if (v->IsArray()) { + if (t->index >= v->Size()) { + v->Reserve(t->index + 1, allocator); + while (t->index >= v->Size()) + v->PushBack(ValueType().Move(), allocator); + exist = false; + } + v = &((*v)[t->index]); + } + else { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) { + v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); + m = v->MemberEnd(); + v = &(--m)->value; // Assumes AddMember() appends at the end + exist = false; + } + else + v = &m->value; + } + } + } + + if (alreadyExist) + *alreadyExist = exist; + + return *v; + } + + //! Creates a value in a document. + /*! + \param document A document to be resolved. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created, or already exists value. + */ + template + ValueType& Create(GenericDocument& document, bool* alreadyExist = 0) const { + return Create(document, document.GetAllocator(), alreadyExist); + } + + //@} + + //!@name Query value + //@{ + + //! Query a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \return Pointer to the value if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a value cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. + */ + ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + break; + v = &m->value; + } + continue; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + break; + v = &((*v)[t->index]); + continue; + default: + break; + } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast(t - tokens_); + return 0; + } + return v; + } + + //! Query a const value in a const subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ + const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { + return Get(const_cast(root), unresolvedTokenIndex); + } + + //@} + + //!@name Query a value with default + //@{ + + //! Query a value in a subtree with default value. + /*! + Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. + So that this function always succeed. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param defaultValue Default value to be cloned if the value was not exists. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); + } + + //! Query a value in a subtree with default null-terminated string. + ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a subtree with default std::basic_string. + ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } +#endif + + //! Query a value in a subtree with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { + return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); + } + + //! Query a value in a document with default value. + template + ValueType& GetWithDefault(GenericDocument& document, const ValueType& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //! Query a value in a document with default null-terminated string. + template + ValueType& GetWithDefault(GenericDocument& document, const Ch* defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a document with default std::basic_string. + template + ValueType& GetWithDefault(GenericDocument& document, const std::basic_string& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } +#endif + + //! Query a value in a document with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(GenericDocument& document, T defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //@} + + //!@name Set a value + //@{ + + //! Set a value in a subtree, with move semantics. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be set. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = value; + } + + //! Set a value in a subtree, with copy semantics. + ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).CopyFrom(value, allocator); + } + + //! Set a null-terminated string in a subtree. + ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Set a std::basic_string in a subtree. + ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } +#endif + + //! Set a primitive value in a subtree. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value).Move(); + } + + //! Set a value in a document, with move semantics. + template + ValueType& Set(GenericDocument& document, ValueType& value) const { + return Create(document) = value; + } + + //! Set a value in a document, with copy semantics. + template + ValueType& Set(GenericDocument& document, const ValueType& value) const { + return Create(document).CopyFrom(value, document.GetAllocator()); + } + + //! Set a null-terminated string in a document. + template + ValueType& Set(GenericDocument& document, const Ch* value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Sets a std::basic_string in a document. + template + ValueType& Set(GenericDocument& document, const std::basic_string& value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } +#endif + + //! Set a primitive value in a document. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(GenericDocument& document, T value) const { + return Create(document) = value; + } + + //@} + + //!@name Swap a value + //@{ + + //! Swap a value with a value in a subtree. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be swapped. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).Swap(value); + } + + //! Swap a value with a value in a document. + template + ValueType& Swap(GenericDocument& document, ValueType& value) const { + return Create(document).Swap(value); + } + + //@} + + //! Erase a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Whether the resolved value is found and erased. + + \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. + */ + bool Erase(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + if (tokenCount_ == 0) // Cannot erase the root + return false; + + ValueType* v = &root; + const Token* last = tokens_ + (tokenCount_ - 1); + for (const Token *t = tokens_; t != last; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + return false; + v = &m->value; + } + break; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + return false; + v = &((*v)[t->index]); + break; + default: + return false; + } + } + + switch (v->GetType()) { + case kObjectType: + return v->EraseMember(GenericStringRef(last->name, last->length)); + case kArrayType: + if (last->index == kPointerInvalidIndex || last->index >= v->Size()) + return false; + v->Erase(v->Begin() + last->index); + return true; + default: + return false; + } + } + +private: + //! Clone the content from rhs to this. + /*! + \param rhs Source pointer. + \param extraToken Extra tokens to be allocated. + \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. + \return Start of non-occupied name buffer, for storing extra names. + */ + Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { + if (!allocator_) // allocator is independently owned. + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens + for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) + nameBufferSize += t->length; + + tokenCount_ = rhs.tokenCount_ + extraToken; + tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + if (rhs.tokenCount_ > 0) { + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + } + if (nameBufferSize > 0) { + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + } + + // Adjust pointers to name buffer + std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; + for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) + t->name += diff; + + return nameBuffer_ + nameBufferSize; + } + + //! Check whether a character should be percent-encoded. + /*! + According to RFC 3986 2.3 Unreserved Characters. + \param c The character (code unit) to be tested. + */ + bool NeedPercentEncode(Ch c) const { + return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); + } + + //! Parse a JSON String or its URI fragment representation into tokens. +#ifndef __clang__ // -Wdocumentation + /*! + \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. + \param length Length of the source string. + \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. + */ +#endif + void Parse(const Ch* source, size_t length) { + RAPIDJSON_ASSERT(source != NULL); + RAPIDJSON_ASSERT(nameBuffer_ == 0); + RAPIDJSON_ASSERT(tokens_ == 0); + + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + // Count number of '/' as tokenCount + tokenCount_ = 0; + for (const Ch* s = source; s != source + length; s++) + if (*s == '/') + tokenCount_++; + + Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); + Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + size_t i = 0; + + // Detect if it is a URI fragment + bool uriFragment = false; + if (source[i] == '#') { + uriFragment = true; + i++; + } + + if (i != length && source[i] != '/') { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } + + while (i < length) { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' + + token->name = name; + bool isNumber = true; + + while (i < length && source[i] != '/') { + Ch c = source[i]; + if (uriFragment) { + // Decoding percent-encoding for URI fragment + if (c == '%') { + PercentDecodeStream is(&source[i], source + length); + GenericInsituStringStream os(name); + Ch* begin = os.PutBegin(); + if (!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + size_t len = os.PutEnd(begin); + i += is.Tell() - 1; + if (len == 1) + c = *name; + else { + name += len; + isNumber = false; + i++; + continue; + } + } + else if (NeedPercentEncode(c)) { + parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; + goto error; + } + } + + i++; + + // Escaping "~0" -> '~', "~1" -> '/' + if (c == '~') { + if (i < length) { + c = source[i]; + if (c == '0') c = '~'; + else if (c == '1') c = '/'; + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; + } + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + } + + // First check for index: all of characters are digit + if (c < '0' || c > '9') + isNumber = false; + + *name++ = c; + } + token->length = static_cast(name - token->name); + if (token->length == 0) + isNumber = false; + *name++ = '\0'; // Null terminator + + // Second check for index: more than one digit cannot have leading zero + if (isNumber && token->length > 1 && token->name[0] == '0') + isNumber = false; + + // String to SizeType conversion + SizeType n = 0; + if (isNumber) { + for (size_t j = 0; j < token->length; j++) { + SizeType m = n * 10 + static_cast(token->name[j] - '0'); + if (m < n) { // overflow detection + isNumber = false; + break; + } + n = m; + } + } + + token->index = isNumber ? n : kPointerInvalidIndex; + token++; + } + + RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer + parseErrorCode_ = kPointerParseErrorNone; + return; + + error: + Allocator::Free(tokens_); + nameBuffer_ = 0; + tokens_ = 0; + tokenCount_ = 0; + parseErrorOffset_ = i; + return; + } + + //! Stringify to string or URI fragment representation. + /*! + \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. + \tparam OutputStream type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + RAPIDJSON_ASSERT(IsValid()); + + if (uriFragment) + os.Put('#'); + + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + os.Put('/'); + for (size_t j = 0; j < t->length; j++) { + Ch c = t->name[j]; + if (c == '~') { + os.Put('~'); + os.Put('0'); + } + else if (c == '/') { + os.Put('~'); + os.Put('1'); + } + else if (uriFragment && NeedPercentEncode(c)) { + // Transcode to UTF8 sequence + GenericStringStream source(&t->name[j]); + PercentEncodeStream target(os); + if (!Transcoder >().Validate(source, target)) + return false; + j += source.Tell() - 1; + } + else + os.Put(c); + } + } + return true; + } + + //! A helper stream for decoding a percent-encoded sequence into code unit. + /*! + This stream decodes %XY triplet into code unit (0-255). + If it encounters invalid characters, it sets output code unit as 0 and + mark invalid, and to be checked by IsValid(). + */ + class PercentDecodeStream { + public: + typedef typename ValueType::Ch Ch; + + //! Constructor + /*! + \param source Start of the stream + \param end Past-the-end of the stream. + */ + PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} + + Ch Take() { + if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet + valid_ = false; + return 0; + } + src_++; + Ch c = 0; + for (int j = 0; j < 2; j++) { + c = static_cast(c << 4); + Ch h = *src_; + if (h >= '0' && h <= '9') c = static_cast(c + h - '0'); + else if (h >= 'A' && h <= 'F') c = static_cast(c + h - 'A' + 10); + else if (h >= 'a' && h <= 'f') c = static_cast(c + h - 'a' + 10); + else { + valid_ = false; + return 0; + } + src_++; + } + return c; + } + + size_t Tell() const { return static_cast(src_ - head_); } + bool IsValid() const { return valid_; } + + private: + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. + const Ch* end_; //!< Past-the-end position. + bool valid_; //!< Whether the parsing is valid. + }; + + //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. + template + class PercentEncodeStream { + public: + PercentEncodeStream(OutputStream& os) : os_(os) {} + void Put(char c) { // UTF-8 must be byte + unsigned char u = static_cast(c); + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + os_.Put('%'); + os_.Put(static_cast(hexDigits[u >> 4])); + os_.Put(static_cast(hexDigits[u & 15])); + } + private: + OutputStream& os_; + }; + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Pointer. + Ch* nameBuffer_; //!< A buffer containing all names in tokens. + Token* tokens_; //!< A list of tokens. + size_t tokenCount_; //!< Number of tokens in tokens_. + size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. + PointerParseErrorCode parseErrorCode_; //!< Parsing error code. +}; + +//! GenericPointer for Value (UTF-8, default allocator). +typedef GenericPointer Pointer; + +//!@name Helper functions for GenericPointer +//@{ + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Create(root, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer& pointer) { + return pointer.Create(document); +} + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Create(document); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const std::basic_string& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, T2 defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* value) { + return pointer.Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const std::basic_string& value) { + return pointer.Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const GenericPointer& pointer, T2 value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string& value) { + return GenericPointer(source, N - 1).Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Swap(root, value, a); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Swap(document, value); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Swap(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +bool EraseValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Erase(root); +} + +template +bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Erase(root); +} + +//@} + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_POINTER_H_ diff --git a/rapidjson/prettywriter.h b/rapidjson/prettywriter.h new file mode 100644 index 0000000..fe45df1 --- /dev/null +++ b/rapidjson/prettywriter.h @@ -0,0 +1,277 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Combination of PrettyWriter format flags. +/*! \see PrettyWriter::SetFormatOptions + */ +enum PrettyFormatOptions { + kFormatDefault = 0, //!< Default pretty formatting. + kFormatSingleLineArray = 1 //!< Format arrays on a single line. +}; + +//! Writer with indentation and spacing. +/*! + \tparam OutputStream Type of output os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class PrettyWriter : public Writer { +public: + typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + + + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + PrettyWriter(PrettyWriter&& rhs) : + Base(std::forward(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} +#endif + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + //! Set pretty writer formatting options. + /*! \param options Formatting options. + */ + PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { + formatOptions_ = options; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kNumberType); + return Base::EndValue(Base::WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kStringType); + return Base::EndValue(Base::WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::EndValue(Base::WriteEndObject()); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::EndValue(Base::WriteEndArray()); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + PrettyPrefix(type); + return Base::EndValue(Base::WriteRawValue(json, length)); + } + +protected: + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + if (formatOptions_ & kFormatSingleLineArray) + Base::os_->Put(' '); + } + + if (!(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, static_cast(indentChar_), count); + } + + Ch indentChar_; + unsigned indentCharCount_; + PrettyFormatOptions formatOptions_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/rapidjson/rapidjson.h b/rapidjson/rapidjson.h new file mode 100644 index 0000000..a4e8953 --- /dev/null +++ b/rapidjson/rapidjson.h @@ -0,0 +1,741 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + Some RapidJSON features are configurable to adapt the library to a wide + variety of platforms, environments and usage scenarios. Most of the + features can be configured in terms of overridden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include // malloc(), realloc(), free(), size_t +#include // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x + +// token concatenation +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in ".." string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 1 +#define RAPIDJSON_PATCH_VERSION 0 +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// __cplusplus macro + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#if defined(_MSC_VER) +#define RAPIDJSON_CPLUSPLUS _MSVC_LANG +#else +#define RAPIDJSON_CPLUSPLUS __cplusplus +#endif + +//!@endcond + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif // RAPIDJSON_HAS_STDSTRING + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_USE_MEMBERSMAP + +/*! \def RAPIDJSON_USE_MEMBERSMAP + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for object members handling in a \c std::multimap + + By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object + members are stored in a \c std::multimap for faster lookup and deletion times, a + trade off with a slightly slower insertion time and a small object allocat(or)ed + memory overhead. + + \hideinitializer +*/ +#ifndef RAPIDJSON_USE_MEMBERSMAP +#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ +#ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" +#else +// Other compilers should have this. +#include +#include +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp +*/ +#ifndef RAPIDJSON_ENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(RAPIDJSON_DOXYGEN_RUNNING) +# define RAPIDJSON_ENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__) +#define RAPIDJSON_64BIT 1 +#else +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. The default is 8 bytes. + User can customize by defining the RAPIDJSON_ALIGN function macro. +*/ +#ifndef RAPIDJSON_ALIGN +#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 + +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast(high32) << 32) | static_cast(low32)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_48BITPOINTER_OPTIMIZATION + +//! Use only lower 48-bit address for some pointers. +/*! + \ingroup RAPIDJSON_CONFIG + + This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address. + The higher 16-bit can be used for storing other data. + \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture. +*/ +#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1 +#else +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 +#endif +#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION + +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1 +#if RAPIDJSON_64BIT != 1 +#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 +#endif +#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast((reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast(reinterpret_cast(x)))) +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast(reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) +#else +#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) +#define RAPIDJSON_GETPOINTER(type, p) (p) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2/Neon optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel + or ARM compatible processors. + + To enable these optimizations, three different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 + + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode + + // Enable ARM Neon optimization. + #define RAPIDJSON_NEON + \endcode + + \c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined. + + If any of these symbols is defined, RapidJSON defines the macro + \c RAPIDJSON_SIMD to indicate the availability of the optimized code. +*/ +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ + || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +RAPIDJSON_NAMESPACE_END +#endif + +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. +*/ +#ifndef RAPIDJSON_ASSERT +#include +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_STATIC_ASSERT + +// Prefer C++11 static_assert, if available +#ifndef RAPIDJSON_STATIC_ASSERT +#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) +#define RAPIDJSON_STATIC_ASSERT(x) \ + static_assert(x, RAPIDJSON_STRINGIFY(x)) +#endif // C++11 +#endif // RAPIDJSON_STATIC_ASSERT + +// Adopt C++03 implementation from boost +#ifndef RAPIDJSON_STATIC_ASSERT +#ifndef __clang__ +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#endif +RAPIDJSON_NAMESPACE_BEGIN +template struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; +template struct StaticAssertTest {}; +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +#ifndef __clang__ +//!@endcond +#endif + +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif // RAPIDJSON_STATIC_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY + +//! Compiler branching hint for expression with high probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression likely to be true. +*/ +#ifndef RAPIDJSON_LIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define RAPIDJSON_LIKELY(x) (x) +#endif +#endif + +//! Compiler branching hint for expression with low probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression unlikely to be true. +*/ +#ifndef RAPIDJSON_UNLIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define RAPIDJSON_UNLIKELY(x) (x) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Helpers + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_END \ +} while((void)0, 0) + +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +#if defined(__has_builtin) +#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x) +#else +#define RAPIDJSON_HAS_BUILTIN(x) 0 +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) + +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif + +#elif defined(_MSC_VER) + +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) + +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) + +#else + +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ + +#endif // RAPIDJSON_DIAG_* + +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L) +#endif + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#elif defined(__clang__) +#if __has_feature(cxx_rvalue_references) && \ + (defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#elif defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#ifndef RAPIDJSON_NOEXCEPT +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT throw() +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT +#endif + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#if (defined(_MSC_VER) && _MSC_VER >= 1700) +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1 +#else +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif +#endif + +#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1700) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 +#else +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR + +/////////////////////////////////////////////////////////////////////////////// +// C++17 features + +#ifndef RAPIDJSON_HAS_CXX17 +#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L) +#endif + +#if RAPIDJSON_HAS_CXX17 +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] +#elif defined(__has_cpp_attribute) +# if __has_cpp_attribute(clang::fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]] +# elif __has_cpp_attribute(fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough)) +# else +# define RAPIDJSON_DELIBERATE_FALLTHROUGH +# endif +#else +# define RAPIDJSON_DELIBERATE_FALLTHROUGH +#endif + +//!@endcond + +//! Assertion (in non-throwing contexts). + /*! \ingroup RAPIDJSON_CONFIG + Some functions provide a \c noexcept guarantee, if the compiler supports it. + In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to + throw an exception. This macro adds a separate customization point for + such cases. + + Defaults to C \c assert() (as \ref RAPIDJSON_ASSERT), if \c noexcept is + supported, and to \ref RAPIDJSON_ASSERT otherwise. + */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NOEXCEPT_ASSERT + +#ifndef RAPIDJSON_NOEXCEPT_ASSERT +#ifdef RAPIDJSON_ASSERT_THROWS +#include +#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x) +#else +#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x) +#endif // RAPIDJSON_ASSERT_THROWS +#endif // RAPIDJSON_NOEXCEPT_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// malloc/realloc/free + +#ifndef RAPIDJSON_MALLOC +///! customization point for global \c malloc +#define RAPIDJSON_MALLOC(size) std::malloc(size) +#endif +#ifndef RAPIDJSON_REALLOC +///! customization point for global \c realloc +#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size) +#endif +#ifndef RAPIDJSON_FREE +///! customization point for global \c free +#define RAPIDJSON_FREE(ptr) std::free(ptr) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// new/delete + +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(TypeName) new TypeName +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Type + +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/rapidjson/reader.h b/rapidjson/reader.h new file mode 100644 index 0000000..09ace4e --- /dev/null +++ b/rapidjson/reader.h @@ -0,0 +1,2244 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_READER_H_ +#define RAPIDJSON_READER_H_ + +/*! \file reader.h */ + +#include "allocators.h" +#include "stream.h" +#include "encodedstream.h" +#include "internal/clzll.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strtod.h" +#include + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#elif defined(RAPIDJSON_NEON) +#include +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(old-style-cast) +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END +#endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + +//! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ +enum ParseFlag { + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. + kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. + kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. + kParseEscapedApostropheFlag = 512, //!< Allow escaped apostrophe in strings. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. +\code +concept Handler { + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType length, bool copy); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \note implements Handler concept +*/ +template, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast(*this).Default(); } + bool Bool(bool) { return static_cast(*this).Default(); } + bool Int(int) { return static_cast(*this).Default(); } + bool Uint(unsigned) { return static_cast(*this).Default(); } + bool Int64(int64_t) { return static_cast(*this).Default(); } + bool Uint64(uint64_t) { return static_cast(*this).Default(); } + bool Double(double) { return static_cast(*this).Default(); } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } + bool StartObject() { return static_cast(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast(*this).Default(); } + bool StartArray() { return static_cast(*this).Default(); } + bool EndArray(SizeType) { return static_cast(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + typename InputStream::Ch c; + while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') + s.Take(); +} + +inline const char* SkipWhitespace(const char* p, const char* end) { + while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + return p; +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The middle of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_NEON) + +//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + return p + 8 + (lz >> 3); + } + } else { + uint32_t lz = internal::clzll(low); + return p + (lz >> 3); + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (; p <= end - 16; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + return p + 8 + (lz >> 3); + } + } else { + uint32_t lz = internal::clzll(low); + return p + (lz >> 3); + } + } + + return SkipWhitespace(p, end); +} + +#endif // RAPIDJSON_NEON + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& is) { + is.src_ = SkipWhitespace_SIMD(is.src_); +} + +template<> inline void SkipWhitespace(EncodedInputStream, MemoryStream>& is) { + is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam SourceEncoding Encoding of the input stream. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. +*/ +template +class GenericReader { +public: + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : + stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse(is, handler); + } + + //! Initialize JSON text token-by-token parsing + /*! + */ + void IterativeParseInit() { + parseResult_.Clear(); + state_ = IterativeParsingStartState; + } + + //! Parse one token from JSON text + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + bool IterativeParseNext(InputStream& is, Handler& handler) { + while (RAPIDJSON_LIKELY(is.Peek() != '\0')) { + SkipWhitespaceAndComments(is); + + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state_, t); + IterativeParsingState d = Transit(state_, t, n, is, handler); + + // If we've finished or hit an error... + if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) { + // Report errors. + if (d == IterativeParsingErrorState) { + HandleError(state_, is); + return false; + } + + // Transition to the finish state. + RAPIDJSON_ASSERT(d == IterativeParsingFinishState); + state_ = d; + + // If StopWhenDone is not set... + if (!(parseFlags & kParseStopWhenDoneFlag)) { + // ... and extra non-whitespace data is found... + SkipWhitespaceAndComments(is); + if (is.Peek() != '\0') { + // ... this is considered an error. + HandleError(state_, is); + return false; + } + } + + // Success! We are done! + return true; + } + + // Transition to the new state. + state_ = d; + + // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now. + if (!IsIterativeParsingDelimiterState(n)) + return true; + } + + // We reached the end of file. + stack_.Clear(); + + if (state_ != IterativeParsingFinishState) { + HandleError(state_, is); + return false; + } + + return true; + } + + //! Check if token-by-token parsing JSON text is complete + /*! \return Whether the JSON has been fully decoded. + */ + RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const { + return IsIterativeParsingCompleteState(state_); + } + + //! Whether a parse error has occurred in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + +private: + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + template + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) { + if (Consume(is, '*')) { + while (true) { + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + else if (Consume(is, '*')) { + if (Consume(is, '/')) + break; + } + else + is.Take(); + } + } + else if (RAPIDJSON_LIKELY(Consume(is, '/'))) + while (is.Peek() != '\0' && is.Take() != '\n') {} + else + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + SkipWhitespace(is); + } + } + } + + // Parse object: { string : value, ... } + template + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, '}')) { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (RAPIDJSON_UNLIKELY(is.Peek() != '"')) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++memberCount; + + switch (is.Peek()) { + case ',': + is.Take(); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + is.Take(); + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy + } + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == '}') { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + // Parse array: [ value, ... ] + template + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ',')) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + } + else if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == ']') { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + template + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) { + if (RAPIDJSON_UNLIKELY(!handler.Null())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(true))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(false))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { + if (RAPIDJSON_LIKELY(is.Peek() == expect)) { + is.Take(); + return true; + } + else + return false; + } + + // Helper function to parse four hexadecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(InputStream& is, size_t escapeOffset) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Peek(); + codepoint <<= 4; + codepoint += static_cast(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + is.Take(); + } + return codepoint; + } + + template + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push() = c; + ++length_; + } + + RAPIDJSON_FORCEINLINE void* Push(SizeType count) { + length_ += count; + return stack_.template Push(count); + } + + size_t Length() const { return length_; } + + Ch* Pop() { + return stack_.template Pop(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream stackStream(stack_); + ParseStringToStream(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (RAPIDJSON_UNLIKELY(!success)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const char escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 +//!@endcond + + for (;;) { + // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. + if (!(parseFlags & kParseValidateEncodingFlag)) + ScanCopyUnescapedString(is, os); + + Ch c = is.Peek(); + if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape + size_t escapeOffset = is.Tell(); // For invalid escaping, report the initial '\\' as error offset + is.Take(); + Ch e = is.Peek(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast(e)])) { + is.Take(); + os.Put(static_cast(escape[static_cast(e)])); + } + else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe + is.Take(); + os.Put('\''); + } + else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode + is.Take(); + unsigned codepoint = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) { + // high surrogate, check if followed by valid low surrogate + if (RAPIDJSON_LIKELY(codepoint <= 0xDBFF)) { + // Handle UTF-16 surrogate pair + if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + unsigned codepoint2 = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + // single low surrogate + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + } + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); + } + else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (RAPIDJSON_UNLIKELY(static_cast(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); + } + else { + size_t offset = is.Tell(); + if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? + !Transcoder::Validate(is, os) : + !Transcoder::Transcode(is, os)))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } + } + } + + template + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { + // Do nothing for generic version + } + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType length; + #ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; + #else + length = static_cast(__builtin_ffs(r) - 1); + #endif + if (length != 0) { + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16, q += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + for (const char* pend = p + length; p != pend; ) + *q++ = *p++; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } +#elif defined(RAPIDJSON_NEON) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + length = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + if (length != 0) { + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + vst1q_u8(reinterpret_cast(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16, q += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + length = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + for (const char* pend = p + length; p != pend; ) { + *q++ = *p++; + } + break; + } + vst1q_u8(reinterpret_cast(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + p += 8 + (lz >> 3); + break; + } + } else { + uint32_t lz = internal::clzll(low); + p += lz >> 3; + break; + } + } + + is.src_ = is.dst_ = p; + } +#endif // RAPIDJSON_NEON + + template + class NumberStream; + + template + class NumberStream { + public: + typedef typename InputStream::Ch Ch; + + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + + RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } + RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } + RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + RAPIDJSON_FORCEINLINE void Push(char) {} + + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const char* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put(static_cast(Base::is.Peek())); + return Base::is.Take(); + } + + RAPIDJSON_FORCEINLINE void Push(char c) { + stackStream.Put(c); + } + + size_t Length() { return stackStream.Length(); } + + const char* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream stackStream; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + + template + void ParseNumber(InputStream& is, Handler& handler) { + internal::StreamLocalCopy copy(is); + NumberStream s(*this, copy.s); + + size_t startOffset = s.Tell(); + double d = 0.0; + bool useNanOrInf = false; + + // Parse minus + bool minus = Consume(s, '-'); + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) { + i = 0; + s.TakePush(); + } + else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) { + i = static_cast(s.TakePush() - '0'); + + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648 + if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 + if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + // Parse NaN or Infinity here + else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { + if (Consume(s, 'N')) { + if (Consume(s, 'a') && Consume(s, 'N')) { + d = std::numeric_limits::quiet_NaN(); + useNanOrInf = true; + } + } + else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) { + if (Consume(s, 'n') && Consume(s, 'f')) { + d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); + useNanOrInf = true; + + if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') + && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + } + + if (RAPIDJSON_UNLIKELY(!useNanOrInf)) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + if (use64bit) { + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (Consume(s, '.')) { + decimalPosition = s.Length(); + + if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = static_cast(i64); +#else + // Use double to store significand in 32-bit architecture + d = static_cast(use64bit ? i64 : i); +#endif + useDouble = true; + } + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (RAPIDJSON_LIKELY(d > 0.0)) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (Consume(s, 'e') || Consume(s, 'E')) { + if (!useDouble) { + d = static_cast(use64bit ? i64 : i); + useDouble = true; + } + + bool expMinus = false; + if (Consume(s, '+')) + ; + else if (Consume(s, '-')) + expMinus = true; + + if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = static_cast(s.Take() - '0'); + if (expMinus) { + // (exp + expFrac) must not underflow int => we're detecting when -exp gets + // dangerously close to INT_MIN (a pessimistic next digit 9 would push it into + // underflow territory): + // + // -(exp * 10 + 9) + expFrac >= INT_MIN + // <=> exp <= (expFrac - INT_MIN - 9) / 10 + RAPIDJSON_ASSERT(expFrac <= 0); + int maxExp = (expFrac + 2147483639) / 10; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) { + while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + + if (parseFlags & kParseNumbersAsStringsFlag) { + if (parseFlags & kParseInsituFlag) { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch* head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + // unable to insert the \0 character here, it will erase the comma after this number + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else { + SizeType numCharsToCopy = static_cast(s.Length()); + StringStream srcStream(s.Pop()); + StackStream dstStream(stack_); + while (numCharsToCopy--) { + Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast(dstStream.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); + } + } + else { + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal + if (d > (std::numeric_limits::max)()) { + // Overflow + // TODO: internal::StrtodX should report overflow (or underflow) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + + cont = handler.Double(minus ? -d : d); + } + else if (useNanOrInf) { + cont = handler.Double(d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(static_cast(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast(~i + 1)); + else + cont = handler.Uint(i); + } + } + } + if (RAPIDJSON_UNLIKELY(!cont)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + } + + // Parse any JSON value + template + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull (is, handler); break; + case 't': ParseTrue (is, handler); break; + case 'f': ParseFalse (is, handler); break; + case '"': ParseString(is, handler); break; + case '{': ParseObject(is, handler); break; + case '[': ParseArray (is, handler); break; + default : + ParseNumber(is, handler); + break; + + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingFinishState = 0, // sink states at top + IterativeParsingErrorState, // sink states at top + IterativeParsingStartState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingMemberValueState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState, + + // Delimiter states (at bottom) + IterativeParsingElementDelimiterState, + IterativeParsingMemberDelimiterState, + IterativeParsingKeyValueDelimiterState, + + cIterativeParsingStateCount + }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || static_cast(c) < 256) + return static_cast(tokenMap[static_cast(c)]); + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + }; // End of G + + return static_cast(G[state][token]); + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + + switch (dst) { + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push(1) = n; + // Initialize and push the member/element count. + *stack_.template Push(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top() = *stack_.template Top() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); + return IterativeParsingErrorState; + } + // Get member count. + SizeType c = *stack_.template Pop(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); + return IterativeParsingErrorState; + } + // Get element count. + SizeType c = *stack_.template Pop(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; + default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; + } + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const { + return s >= IterativeParsingElementDelimiterState; + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const { + return s <= IterativeParsingErrorState; + } + + template + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; + IterativeParsingState state_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader, UTF8<> > Reader; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_READER_H_ diff --git a/rapidjson/schema.h b/rapidjson/schema.h new file mode 100644 index 0000000..a034021 --- /dev/null +++ b/rapidjson/schema.h @@ -0,0 +1,2648 @@ +// Tencent is pleased to support the open source community by making RapidJSON available-> +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved-> +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License-> You may obtain a copy of the License at +// +// http://opensource->org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied-> See the License for the +// specific language governing permissions and limitations under the License-> + +#ifndef RAPIDJSON_SCHEMA_H_ +#define RAPIDJSON_SCHEMA_H_ + +#include "document.h" +#include "pointer.h" +#include "stringbuffer.h" +#include "error/en.h" +#include // abs, floor + +#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 +#endif + +#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) +#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_STDREGEX 0 +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX +#include "internal/regex.h" +#elif RAPIDJSON_SCHEMA_USE_STDREGEX +#include +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX +#define RAPIDJSON_SCHEMA_HAS_REGEX 1 +#else +#define RAPIDJSON_SCHEMA_HAS_REGEX 0 +#endif + +#ifndef RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_VERBOSE 0 +#endif + +#if RAPIDJSON_SCHEMA_VERBOSE +#include "stringbuffer.h" +#endif + +RAPIDJSON_DIAG_PUSH + +#if defined(__GNUC__) +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(weak-vtables) +RAPIDJSON_DIAG_OFF(exit-time-destructors) +RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) +RAPIDJSON_DIAG_OFF(variadic-macros) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Verbose Utilities + +#if RAPIDJSON_SCHEMA_VERBOSE + +namespace internal { + +inline void PrintInvalidKeyword(const char* keyword) { + printf("Fail keyword: %s\n", keyword); +} + +inline void PrintInvalidKeyword(const wchar_t* keyword) { + wprintf(L"Fail keyword: %ls\n", keyword); +} + +inline void PrintInvalidDocument(const char* document) { + printf("Fail document: %s\n\n", document); +} + +inline void PrintInvalidDocument(const wchar_t* document) { + wprintf(L"Fail document: %ls\n\n", document); +} + +inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) { + printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); +} + +inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) { + wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); +} + +} // namespace internal + +#endif // RAPIDJSON_SCHEMA_VERBOSE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_INVALID_KEYWORD_RETURN + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword) +#else +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) +#endif + +#define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + context.invalidCode = code;\ + context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\ + RAPIDJSON_INVALID_KEYWORD_VERBOSE(context.invalidKeyword);\ + return false;\ +RAPIDJSON_MULTILINEMACRO_END + +/////////////////////////////////////////////////////////////////////////////// +// ValidateFlag + +/*! \def RAPIDJSON_VALIDATE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kValidateDefaultFlags definition. + + User can define this as any \c ValidateFlag combinations. +*/ +#ifndef RAPIDJSON_VALIDATE_DEFAULT_FLAGS +#define RAPIDJSON_VALIDATE_DEFAULT_FLAGS kValidateNoFlags +#endif + +//! Combination of validate flags +/*! \see + */ +enum ValidateFlag { + kValidateNoFlags = 0, //!< No flags are set. + kValidateContinueOnErrorFlag = 1, //!< Don't stop after first validation error. + kValidateDefaultFlags = RAPIDJSON_VALIDATE_DEFAULT_FLAGS //!< Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Forward declarations + +template +class GenericSchemaDocument; + +namespace internal { + +template +class Schema; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaValidator + +class ISchemaValidator { +public: + virtual ~ISchemaValidator() {} + virtual bool IsValid() const = 0; + virtual void SetValidateFlags(unsigned flags) = 0; + virtual unsigned GetValidateFlags() const = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaStateFactory + +template +class ISchemaStateFactory { +public: + virtual ~ISchemaStateFactory() {} + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0; + virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* CreateHasher() = 0; + virtual uint64_t GetHashCode(void* hasher) = 0; + virtual void DestroryHasher(void* hasher) = 0; + virtual void* MallocState(size_t size) = 0; + virtual void FreeState(void* p) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// IValidationErrorHandler + +template +class IValidationErrorHandler { +public: + typedef typename SchemaType::Ch Ch; + typedef typename SchemaType::SValue SValue; + + virtual ~IValidationErrorHandler() {} + + virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0; + virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0; + virtual void NotMultipleOf(double actual, const SValue& expected) = 0; + virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0; + + virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0; + virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0; + virtual void DoesNotMatch(const Ch* str, SizeType length) = 0; + + virtual void DisallowedItem(SizeType index) = 0; + virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0; + virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0; + virtual void DuplicateItems(SizeType index1, SizeType index2) = 0; + + virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0; + virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0; + virtual void StartMissingProperties() = 0; + virtual void AddMissingProperty(const SValue& name) = 0; + virtual bool EndMissingProperties() = 0; + virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void DisallowedProperty(const Ch* name, SizeType length) = 0; + + virtual void StartDependencyErrors() = 0; + virtual void StartMissingDependentProperties() = 0; + virtual void AddMissingDependentProperty(const SValue& targetName) = 0; + virtual void EndMissingDependentProperties(const SValue& sourceName) = 0; + virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0; + virtual bool EndDependencyErrors() = 0; + + virtual void DisallowedValue(const ValidateErrorCode code) = 0; + virtual void StartDisallowedType() = 0; + virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0; + virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0; + virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched) = 0; + virtual void Disallowed() = 0; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Hasher + +// For comparison of compound value +template +class Hasher { +public: + typedef typename Encoding::Ch Ch; + + Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} + + bool Null() { return WriteType(kNullType); } + bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); } + bool Int(int i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Double(double d) { + Number n; + if (d < 0) n.u.i = static_cast(d); + else n.u.u = static_cast(d); + n.d = d; + return WriteNumber(n); + } + + bool RawNumber(const Ch* str, SizeType len, bool) { + WriteBuffer(kNumberType, str, len * sizeof(Ch)); + return true; + } + + bool String(const Ch* str, SizeType len, bool) { + WriteBuffer(kStringType, str, len * sizeof(Ch)); + return true; + } + + bool StartObject() { return true; } + bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); } + bool EndObject(SizeType memberCount) { + uint64_t h = Hash(0, kObjectType); + uint64_t* kv = stack_.template Pop(memberCount * 2); + for (SizeType i = 0; i < memberCount; i++) + h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive + *stack_.template Push() = h; + return true; + } + + bool StartArray() { return true; } + bool EndArray(SizeType elementCount) { + uint64_t h = Hash(0, kArrayType); + uint64_t* e = stack_.template Pop(elementCount); + for (SizeType i = 0; i < elementCount; i++) + h = Hash(h, e[i]); // Use hash to achieve element order sensitive + *stack_.template Push() = h; + return true; + } + + bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); } + + uint64_t GetHashCode() const { + RAPIDJSON_ASSERT(IsValid()); + return *stack_.template Top(); + } + +private: + static const size_t kDefaultSize = 256; + struct Number { + union U { + uint64_t u; + int64_t i; + }u; + double d; + }; + + bool WriteType(Type type) { return WriteBuffer(type, 0, 0); } + + bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); } + + bool WriteBuffer(Type type, const void* data, size_t len) { + // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ + uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); + const unsigned char* d = static_cast(data); + for (size_t i = 0; i < len; i++) + h = Hash(h, d[i]); + *stack_.template Push() = h; + return true; + } + + static uint64_t Hash(uint64_t h, uint64_t d) { + static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3); + h ^= d; + h *= kPrime; + return h; + } + + Stack stack_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidationContext + +template +struct SchemaValidationContext { + typedef Schema SchemaType; + typedef ISchemaStateFactory SchemaValidatorFactoryType; + typedef IValidationErrorHandler ErrorHandlerType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; + + enum PatternValidatorType { + kPatternValidatorOnly, + kPatternValidatorWithProperty, + kPatternValidatorWithAdditionalProperty + }; + + SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) : + factory(f), + error_handler(eh), + schema(s), + valueSchema(), + invalidKeyword(), + invalidCode(), + hasher(), + arrayElementHashCodes(), + validators(), + validatorCount(), + patternPropertiesValidators(), + patternPropertiesValidatorCount(), + patternPropertiesSchemas(), + patternPropertiesSchemaCount(), + valuePatternValidatorType(kPatternValidatorOnly), + propertyExist(), + inArray(false), + valueUniqueness(false), + arrayUniqueness(false) + { + } + + ~SchemaValidationContext() { + if (hasher) + factory.DestroryHasher(hasher); + if (validators) { + for (SizeType i = 0; i < validatorCount; i++) + factory.DestroySchemaValidator(validators[i]); + factory.FreeState(validators); + } + if (patternPropertiesValidators) { + for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + factory.FreeState(patternPropertiesValidators); + } + if (patternPropertiesSchemas) + factory.FreeState(patternPropertiesSchemas); + if (propertyExist) + factory.FreeState(propertyExist); + } + + SchemaValidatorFactoryType& factory; + ErrorHandlerType& error_handler; + const SchemaType* schema; + const SchemaType* valueSchema; + const Ch* invalidKeyword; + ValidateErrorCode invalidCode; + void* hasher; // Only validator access + void* arrayElementHashCodes; // Only validator access this + ISchemaValidator** validators; + SizeType validatorCount; + ISchemaValidator** patternPropertiesValidators; + SizeType patternPropertiesValidatorCount; + const SchemaType** patternPropertiesSchemas; + SizeType patternPropertiesSchemaCount; + PatternValidatorType valuePatternValidatorType; + PatternValidatorType objectPatternValidatorType; + SizeType arrayElementIndex; + bool* propertyExist; + bool inArray; + bool valueUniqueness; + bool arrayUniqueness; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Schema + +template +class Schema { +public: + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef SchemaValidationContext Context; + typedef Schema SchemaType; + typedef GenericValue SValue; + typedef IValidationErrorHandler ErrorHandler; + friend class GenericSchemaDocument; + + Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : + allocator_(allocator), + uri_(schemaDocument->GetURI(), *allocator), + pointer_(p, allocator), + typeless_(schemaDocument->GetTypeless()), + enum_(), + enumCount_(), + not_(), + type_((1 << kTotalSchemaType) - 1), // typeless + validatorCount_(), + notValidatorIndex_(), + properties_(), + additionalPropertiesSchema_(), + patternProperties_(), + patternPropertyCount_(), + propertyCount_(), + minProperties_(), + maxProperties_(SizeType(~0)), + additionalProperties_(true), + hasDependencies_(), + hasRequired_(), + hasSchemaDependencies_(), + additionalItemsSchema_(), + itemsList_(), + itemsTuple_(), + itemsTupleCount_(), + minItems_(), + maxItems_(SizeType(~0)), + additionalItems_(true), + uniqueItems_(false), + pattern_(), + minLength_(0), + maxLength_(~SizeType(0)), + exclusiveMinimum_(false), + exclusiveMaximum_(false), + defaultValueLength_(0) + { + typedef typename ValueType::ConstValueIterator ConstValueIterator; + typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + + if (!value.IsObject()) + return; + + if (const ValueType* v = GetMember(value, GetTypeString())) { + type_ = 0; + if (v->IsString()) + AddType(*v); + else if (v->IsArray()) + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) + AddType(*itr); + } + + if (const ValueType* v = GetMember(value, GetEnumString())) { + if (v->IsArray() && v->Size() > 0) { + enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { + typedef Hasher > EnumHasherType; + char buffer[256u + 24]; + MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); + EnumHasherType h(&hasherAllocator, 256); + itr->Accept(h); + enum_[enumCount_++] = h.GetHashCode(); + } + } + } + + if (schemaDocument) { + AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); + AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); + AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); + + if (const ValueType* v = GetMember(value, GetNotString())) { + schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document); + notValidatorIndex_ = validatorCount_; + validatorCount_++; + } + } + + // Object + + const ValueType* properties = GetMember(value, GetPropertiesString()); + const ValueType* required = GetMember(value, GetRequiredString()); + const ValueType* dependencies = GetMember(value, GetDependenciesString()); + { + // Gather properties from properties/required/dependencies + SValue allProperties(kArrayType); + + if (properties && properties->IsObject()) + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) + AddUniqueElement(allProperties, itr->name); + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) + AddUniqueElement(allProperties, *itr); + + if (dependencies && dependencies->IsObject()) + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + AddUniqueElement(allProperties, itr->name); + if (itr->value.IsArray()) + for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i) + if (i->IsString()) + AddUniqueElement(allProperties, *i); + } + + if (allProperties.Size() > 0) { + propertyCount_ = allProperties.Size(); + properties_ = static_cast(allocator_->Malloc(sizeof(Property) * propertyCount_)); + for (SizeType i = 0; i < propertyCount_; i++) { + new (&properties_[i]) Property(); + properties_[i].name = allProperties[i]; + properties_[i].schema = typeless_; + } + } + } + + if (properties && properties->IsObject()) { + PointerType q = p.Append(GetPropertiesString(), allocator_); + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) { + SizeType index; + if (FindPropertyIndex(itr->name, &index)) + schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document); + } + } + + if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); + patternPropertyCount_ = 0; + + for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { + new (&patternProperties_[patternPropertyCount_]) PatternProperty(); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document); + patternPropertyCount_++; + } + } + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) { + SizeType index; + if (FindPropertyIndex(*itr, &index)) { + properties_[index].required = true; + hasRequired_ = true; + } + } + + if (dependencies && dependencies->IsObject()) { + PointerType q = p.Append(GetDependenciesString(), allocator_); + hasDependencies_ = true; + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + SizeType sourceIndex; + if (FindPropertyIndex(itr->name, &sourceIndex)) { + if (itr->value.IsArray()) { + properties_[sourceIndex].dependencies = static_cast(allocator_->Malloc(sizeof(bool) * propertyCount_)); + std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); + for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { + SizeType targetIndex; + if (FindPropertyIndex(*targetItr, &targetIndex)) + properties_[sourceIndex].dependencies[targetIndex] = true; + } + } + else if (itr->value.IsObject()) { + hasSchemaDependencies_ = true; + schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document); + properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; + validatorCount_++; + } + } + } + } + + if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) { + if (v->IsBool()) + additionalProperties_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document); + } + + AssignIfExist(minProperties_, value, GetMinPropertiesString()); + AssignIfExist(maxProperties_, value, GetMaxPropertiesString()); + + // Array + if (const ValueType* v = GetMember(value, GetItemsString())) { + PointerType q = p.Append(GetItemsString(), allocator_); + if (v->IsObject()) // List validation + schemaDocument->CreateSchema(&itemsList_, q, *v, document); + else if (v->IsArray()) { // Tuple validation + itemsTuple_ = static_cast(allocator_->Malloc(sizeof(const Schema*) * v->Size())); + SizeType index = 0; + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) + schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document); + } + } + + AssignIfExist(minItems_, value, GetMinItemsString()); + AssignIfExist(maxItems_, value, GetMaxItemsString()); + + if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) { + if (v->IsBool()) + additionalItems_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document); + } + + AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); + + // String + AssignIfExist(minLength_, value, GetMinLengthString()); + AssignIfExist(maxLength_, value, GetMaxLengthString()); + + if (const ValueType* v = GetMember(value, GetPatternString())) + pattern_ = CreatePattern(*v); + + // Number + if (const ValueType* v = GetMember(value, GetMinimumString())) + if (v->IsNumber()) + minimum_.CopyFrom(*v, *allocator_); + + if (const ValueType* v = GetMember(value, GetMaximumString())) + if (v->IsNumber()) + maximum_.CopyFrom(*v, *allocator_); + + AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString()); + AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString()); + + if (const ValueType* v = GetMember(value, GetMultipleOfString())) + if (v->IsNumber() && v->GetDouble() > 0.0) + multipleOf_.CopyFrom(*v, *allocator_); + + // Default + if (const ValueType* v = GetMember(value, GetDefaultValueString())) + if (v->IsString()) + defaultValueLength_ = v->GetStringLength(); + + } + + ~Schema() { + AllocatorType::Free(enum_); + if (properties_) { + for (SizeType i = 0; i < propertyCount_; i++) + properties_[i].~Property(); + AllocatorType::Free(properties_); + } + if (patternProperties_) { + for (SizeType i = 0; i < patternPropertyCount_; i++) + patternProperties_[i].~PatternProperty(); + AllocatorType::Free(patternProperties_); + } + AllocatorType::Free(itemsTuple_); +#if RAPIDJSON_SCHEMA_HAS_REGEX + if (pattern_) { + pattern_->~RegexType(); + AllocatorType::Free(pattern_); + } +#endif + } + + const SValue& GetURI() const { + return uri_; + } + + const PointerType& GetPointer() const { + return pointer_; + } + + bool BeginValue(Context& context) const { + if (context.inArray) { + if (uniqueItems_) + context.valueUniqueness = true; + + if (itemsList_) + context.valueSchema = itemsList_; + else if (itemsTuple_) { + if (context.arrayElementIndex < itemsTupleCount_) + context.valueSchema = itemsTuple_[context.arrayElementIndex]; + else if (additionalItemsSchema_) + context.valueSchema = additionalItemsSchema_; + else if (additionalItems_) + context.valueSchema = typeless_; + else { + context.error_handler.DisallowedItem(context.arrayElementIndex); + // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error + context.valueSchema = typeless_; + // Must bump arrayElementIndex for when kValidateContinueOnErrorFlag is set + context.arrayElementIndex++; + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalItems); + } + } + else + context.valueSchema = typeless_; + + context.arrayElementIndex++; + } + return true; + } + + RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { + // Only check pattern properties if we have validators + if (context.patternPropertiesValidatorCount > 0) { + bool otherValid = false; + SizeType count = context.patternPropertiesValidatorCount; + if (context.objectPatternValidatorType != Context::kPatternValidatorOnly) + otherValid = context.patternPropertiesValidators[--count]->IsValid(); + + bool patternValid = true; + for (SizeType i = 0; i < count; i++) + if (!context.patternPropertiesValidators[i]->IsValid()) { + patternValid = false; + break; + } + + if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { + if (!patternValid) { + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { + if (!patternValid || !otherValid) { + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty) + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + + // For enums only check if we have a hasher + if (enum_ && context.hasher) { + const uint64_t h = context.factory.GetHashCode(context.hasher); + for (SizeType i = 0; i < enumCount_; i++) + if (enum_[i] == h) + goto foundEnum; + context.error_handler.DisallowedValue(kValidateErrorEnum); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorEnum); + foundEnum:; + } + + // Only check allOf etc if we have validators + if (context.validatorCount > 0) { + if (allOf_.schemas) + for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) + if (!context.validators[i]->IsValid()) { + context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf); + } + + if (anyOf_.schemas) { + for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) + if (context.validators[i]->IsValid()) + goto foundAny; + context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf); + foundAny:; + } + + if (oneOf_.schemas) { + bool oneValid = false; + for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if (context.validators[i]->IsValid()) { + if (oneValid) { + context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch); + } else + oneValid = true; + } + if (!oneValid) { + context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, false); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf); + } + } + + if (not_ && context.validators[notValidatorIndex_]->IsValid()) { + context.error_handler.Disallowed(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot); + } + } + + return true; + } + + bool Null(Context& context) const { + if (!(type_ & (1 << kNullSchemaType))) { + DisallowedType(context, GetNullString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return CreateParallelValidator(context); + } + + bool Bool(Context& context, bool) const { + if (!(type_ & (1 << kBooleanSchemaType))) { + DisallowedType(context, GetBooleanString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return CreateParallelValidator(context); + } + + bool Int(Context& context, int i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint(Context& context, unsigned u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Int64(Context& context, int64_t i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint64(Context& context, uint64_t u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Double(Context& context, double d) const { + if (!(type_ & (1 << kNumberSchemaType))) { + DisallowedType(context, GetNumberString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d)) + return false; + + if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) + return false; + + if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) + return false; + + return CreateParallelValidator(context); + } + + bool String(Context& context, const Ch* str, SizeType length, bool) const { + if (!(type_ & (1 << kStringSchemaType))) { + DisallowedType(context, GetStringString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (internal::CountStringCodePoint(str, length, &count)) { + if (count < minLength_) { + context.error_handler.TooShort(str, length, minLength_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinLength); + } + if (count > maxLength_) { + context.error_handler.TooLong(str, length, maxLength_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxLength); + } + } + } + + if (pattern_ && !IsPatternMatch(pattern_, str, length)) { + context.error_handler.DoesNotMatch(str, length); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPattern); + } + + return CreateParallelValidator(context); + } + + bool StartObject(Context& context) const { + if (!(type_ & (1 << kObjectSchemaType))) { + DisallowedType(context, GetObjectString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (hasDependencies_ || hasRequired_) { + context.propertyExist = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); + std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_); + } + + if (patternProperties_) { // pre-allocate schema array + SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType + context.patternPropertiesSchemas = static_cast(context.factory.MallocState(sizeof(const SchemaType*) * count)); + context.patternPropertiesSchemaCount = 0; + std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); + } + + return CreateParallelValidator(context); + } + + bool Key(Context& context, const Ch* str, SizeType len, bool) const { + if (patternProperties_) { + context.patternPropertiesSchemaCount = 0; + for (SizeType i = 0; i < patternPropertyCount_; i++) + if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; + context.valueSchema = typeless_; + } + } + + SizeType index = 0; + if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; + context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; + } + else + context.valueSchema = properties_[index].schema; + + if (context.propertyExist) + context.propertyExist[index] = true; + + return true; + } + + if (additionalPropertiesSchema_) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; + context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; + } + else + context.valueSchema = additionalPropertiesSchema_; + return true; + } + else if (additionalProperties_) { + context.valueSchema = typeless_; + return true; + } + + if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties + // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error + context.valueSchema = typeless_; + context.error_handler.DisallowedProperty(str, len); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalProperties); + } + + return true; + } + + bool EndObject(Context& context, SizeType memberCount) const { + if (hasRequired_) { + context.error_handler.StartMissingProperties(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].required && !context.propertyExist[index]) + if (properties_[index].schema->defaultValueLength_ == 0 ) + context.error_handler.AddMissingProperty(properties_[index].name); + if (context.error_handler.EndMissingProperties()) + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired); + } + + if (memberCount < minProperties_) { + context.error_handler.TooFewProperties(memberCount, minProperties_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinProperties); + } + + if (memberCount > maxProperties_) { + context.error_handler.TooManyProperties(memberCount, maxProperties_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxProperties); + } + + if (hasDependencies_) { + context.error_handler.StartDependencyErrors(); + for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) { + const Property& source = properties_[sourceIndex]; + if (context.propertyExist[sourceIndex]) { + if (source.dependencies) { + context.error_handler.StartMissingDependentProperties(); + for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) + if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex]) + context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name); + context.error_handler.EndMissingDependentProperties(source.name); + } + else if (source.dependenciesSchema) { + ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex]; + if (!dependenciesValidator->IsValid()) + context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator); + } + } + } + if (context.error_handler.EndDependencyErrors()) + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorDependencies); + } + + return true; + } + + bool StartArray(Context& context) const { + context.arrayElementIndex = 0; + context.inArray = true; // Ensure we note that we are in an array + + if (!(type_ & (1 << kArraySchemaType))) { + DisallowedType(context, GetArrayString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + return CreateParallelValidator(context); + } + + bool EndArray(Context& context, SizeType elementCount) const { + context.inArray = false; + + if (elementCount < minItems_) { + context.error_handler.TooFewItems(elementCount, minItems_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinItems); + } + + if (elementCount > maxItems_) { + context.error_handler.TooManyItems(elementCount, maxItems_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxItems); + } + + return true; + } + + static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) { + switch (validateErrorCode) { + case kValidateErrorMultipleOf: return GetMultipleOfString(); + case kValidateErrorMaximum: return GetMaximumString(); + case kValidateErrorExclusiveMaximum: return GetMaximumString(); // Same + case kValidateErrorMinimum: return GetMinimumString(); + case kValidateErrorExclusiveMinimum: return GetMinimumString(); // Same + + case kValidateErrorMaxLength: return GetMaxLengthString(); + case kValidateErrorMinLength: return GetMinLengthString(); + case kValidateErrorPattern: return GetPatternString(); + + case kValidateErrorMaxItems: return GetMaxItemsString(); + case kValidateErrorMinItems: return GetMinItemsString(); + case kValidateErrorUniqueItems: return GetUniqueItemsString(); + case kValidateErrorAdditionalItems: return GetAdditionalItemsString(); + + case kValidateErrorMaxProperties: return GetMaxPropertiesString(); + case kValidateErrorMinProperties: return GetMinPropertiesString(); + case kValidateErrorRequired: return GetRequiredString(); + case kValidateErrorAdditionalProperties: return GetAdditionalPropertiesString(); + case kValidateErrorPatternProperties: return GetPatternPropertiesString(); + case kValidateErrorDependencies: return GetDependenciesString(); + + case kValidateErrorEnum: return GetEnumString(); + case kValidateErrorType: return GetTypeString(); + + case kValidateErrorOneOf: return GetOneOfString(); + case kValidateErrorOneOfMatch: return GetOneOfString(); // Same + case kValidateErrorAllOf: return GetAllOfString(); + case kValidateErrorAnyOf: return GetAnyOfString(); + case kValidateErrorNot: return GetNotString(); + + default: return GetNullString(); + } + } + + + // Generate functions for string literal according to Ch +#define RAPIDJSON_STRING_(name, ...) \ + static const ValueType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const ValueType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1));\ + return v;\ + } + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n') + RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't') + RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y') + RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g') + RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r') + RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r') + RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e') + RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm') + RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f') + RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f') + RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f') + RAPIDJSON_STRING_(Not, 'n', 'o', 't') + RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd') + RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's') + RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n') + RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') + RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't') + +#undef RAPIDJSON_STRING_ + +private: + enum SchemaValueType { + kNullSchemaType, + kBooleanSchemaType, + kObjectSchemaType, + kArraySchemaType, + kStringSchemaType, + kNumberSchemaType, + kIntegerSchemaType, + kTotalSchemaType + }; + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + typedef internal::GenericRegex RegexType; +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + typedef std::basic_regex RegexType; +#else + typedef char RegexType; +#endif + + struct SchemaArray { + SchemaArray() : schemas(), count() {} + ~SchemaArray() { AllocatorType::Free(schemas); } + const SchemaType** schemas; + SizeType begin; // begin index of context.validators + SizeType count; + }; + + template + void AddUniqueElement(V1& a, const V2& v) { + for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + if (*itr == v) + return; + V1 c(v, *allocator_); + a.PushBack(c, *allocator_); + } + + static const ValueType* GetMember(const ValueType& value, const ValueType& name) { + typename ValueType::ConstMemberIterator itr = value.FindMember(name); + return itr != value.MemberEnd() ? &(itr->value) : 0; + } + + static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsBool()) + out = v->GetBool(); + } + + static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsUint64() && v->GetUint64() <= SizeType(~0)) + out = static_cast(v->GetUint64()); + } + + void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) { + if (const ValueType* v = GetMember(value, name)) { + if (v->IsArray() && v->Size() > 0) { + PointerType q = p.Append(name, allocator_); + out.count = v->Size(); + out.schemas = static_cast(allocator_->Malloc(out.count * sizeof(const Schema*))); + memset(out.schemas, 0, sizeof(Schema*)* out.count); + for (SizeType i = 0; i < out.count; i++) + schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document); + out.begin = validatorCount_; + validatorCount_ += out.count; + } + } + } + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + template + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) { + RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_); + if (!r->IsValid()) { + r->~RegexType(); + AllocatorType::Free(r); + r = 0; + } + return r; + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { + GenericRegexSearch rs(*pattern); + return rs.Search(str); + } +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + template + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) { + RegexType *r = static_cast(allocator_->Malloc(sizeof(RegexType))); + try { + return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); + } + catch (const std::regex_error&) { + AllocatorType::Free(r); + } + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) { + std::match_results r; + return std::regex_search(str, str + length, r, *pattern); + } +#else + template + RegexType* CreatePattern(const ValueType&) { return 0; } + + static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } +#endif // RAPIDJSON_SCHEMA_USE_STDREGEX + + void AddType(const ValueType& type) { + if (type == GetNullString() ) type_ |= 1 << kNullSchemaType; + else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType; + else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType; + else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType; + else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType; + else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType; + else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); + } + + bool CreateParallelValidator(Context& context) const { + if (enum_ || context.arrayUniqueness) + context.hasher = context.factory.CreateHasher(); + + if (validatorCount_) { + RAPIDJSON_ASSERT(context.validators == 0); + context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); + context.validatorCount = validatorCount_; + + // Always return after first failure for these sub-validators + if (allOf_.schemas) + CreateSchemaValidators(context, allOf_, false); + + if (anyOf_.schemas) + CreateSchemaValidators(context, anyOf_, false); + + if (oneOf_.schemas) + CreateSchemaValidators(context, oneOf_, false); + + if (not_) + context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_, false); + + if (hasSchemaDependencies_) { + for (SizeType i = 0; i < propertyCount_; i++) + if (properties_[i].dependenciesSchema) + context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema, false); + } + } + + return true; + } + + void CreateSchemaValidators(Context& context, const SchemaArray& schemas, const bool inheritContinueOnErrors) const { + for (SizeType i = 0; i < schemas.count; i++) + context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i], inheritContinueOnErrors); + } + + // O(n) + bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { + SizeType len = name.GetStringLength(); + const Ch* str = name.GetString(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].name.GetStringLength() == len && + (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) + { + *outIndex = index; + return true; + } + return false; + } + + bool CheckInt(Context& context, int64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { + DisallowedType(context, GetIntegerString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull()) { + if (minimum_.IsInt64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + } + else if (minimum_.IsUint64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); // i <= max(int64_t) < minimum.GetUint64() + } + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsInt64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + } + else if (maximum_.IsUint64()) { } + /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64() + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) { + context.error_handler.NotMultipleOf(i, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckUint(Context& context, uint64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { + DisallowedType(context, GetIntegerString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull()) { + if (minimum_.IsUint64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + } + else if (minimum_.IsInt64()) + /* do nothing */; // i >= 0 > minimum.Getint64() + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsUint64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + } + else if (maximum_.IsInt64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); // i >= 0 > maximum_ + } + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (i % multipleOf_.GetUint64() != 0) { + context.error_handler.NotMultipleOf(i, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckDoubleMinimum(Context& context, double d) const { + if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) { + context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + return true; + } + + bool CheckDoubleMaximum(Context& context, double d) const { + if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) { + context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + return true; + } + + bool CheckDoubleMultipleOf(Context& context, double d) const { + double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); + double q = std::floor(a / b); + double r = a - q * b; + if (r > 0.0) { + context.error_handler.NotMultipleOf(d, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + return true; + } + + void DisallowedType(Context& context, const ValueType& actualType) const { + ErrorHandler& eh = context.error_handler; + eh.StartDisallowedType(); + + if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString()); + if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString()); + if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString()); + if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString()); + if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString()); + + if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString()); + else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString()); + + eh.EndDisallowedType(actualType); + } + + struct Property { + Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} + ~Property() { AllocatorType::Free(dependencies); } + SValue name; + const SchemaType* schema; + const SchemaType* dependenciesSchema; + SizeType dependenciesValidatorIndex; + bool* dependencies; + bool required; + }; + + struct PatternProperty { + PatternProperty() : schema(), pattern() {} + ~PatternProperty() { + if (pattern) { + pattern->~RegexType(); + AllocatorType::Free(pattern); + } + } + const SchemaType* schema; + RegexType* pattern; + }; + + AllocatorType* allocator_; + SValue uri_; + PointerType pointer_; + const SchemaType* typeless_; + uint64_t* enum_; + SizeType enumCount_; + SchemaArray allOf_; + SchemaArray anyOf_; + SchemaArray oneOf_; + const SchemaType* not_; + unsigned type_; // bitmask of kSchemaType + SizeType validatorCount_; + SizeType notValidatorIndex_; + + Property* properties_; + const SchemaType* additionalPropertiesSchema_; + PatternProperty* patternProperties_; + SizeType patternPropertyCount_; + SizeType propertyCount_; + SizeType minProperties_; + SizeType maxProperties_; + bool additionalProperties_; + bool hasDependencies_; + bool hasRequired_; + bool hasSchemaDependencies_; + + const SchemaType* additionalItemsSchema_; + const SchemaType* itemsList_; + const SchemaType** itemsTuple_; + SizeType itemsTupleCount_; + SizeType minItems_; + SizeType maxItems_; + bool additionalItems_; + bool uniqueItems_; + + RegexType* pattern_; + SizeType minLength_; + SizeType maxLength_; + + SValue minimum_; + SValue maximum_; + SValue multipleOf_; + bool exclusiveMinimum_; + bool exclusiveMaximum_; + + SizeType defaultValueLength_; +}; + +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + *documentStack.template Push() = '/'; + char buffer[21]; + size_t length = static_cast((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); + for (size_t i = 0; i < length; i++) + *documentStack.template Push() = static_cast(buffer[i]); + } +}; + +// Partial specialized version for char to prevent buffer copying. +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + if (sizeof(SizeType) == 4) { + char *buffer = documentStack.template Push(1 + 10); // '/' + uint + *buffer++ = '/'; + const char* end = internal::u32toa(index, buffer); + documentStack.template Pop(static_cast(10 - (end - buffer))); + } + else { + char *buffer = documentStack.template Push(1 + 20); // '/' + uint64 + *buffer++ = '/'; + const char* end = internal::u64toa(index, buffer); + documentStack.template Pop(static_cast(20 - (end - buffer))); + } + } +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// IGenericRemoteSchemaDocumentProvider + +template +class IGenericRemoteSchemaDocumentProvider { +public: + typedef typename SchemaDocumentType::Ch Ch; + + virtual ~IGenericRemoteSchemaDocumentProvider() {} + virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaDocument + +//! JSON schema document. +/*! + A JSON schema document is a compiled version of a JSON schema. + It is basically a tree of internal::Schema. + + \note This is an immutable class (i.e. its instance cannot be modified after construction). + \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding. + \tparam Allocator Allocator type for allocating memory of this document. +*/ +template +class GenericSchemaDocument { +public: + typedef ValueT ValueType; + typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProviderType; + typedef Allocator AllocatorType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef internal::Schema SchemaType; + typedef GenericPointer PointerType; + typedef GenericValue URIType; + friend class internal::Schema; + template + friend class GenericSchemaValidator; + + //! Constructor. + /*! + Compile a JSON document into schema document. + + \param document A JSON document as source. + \param uri The base URI of this schema document for purposes of violation reporting. + \param uriLength Length of \c name, in code points. + \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. + \param allocator An optional allocator instance for allocating memory. Can be null. + */ + explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0, + IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), + typeless_(), + schemaMap_(allocator, kInitialSchemaMapSize), + schemaRef_(allocator, kInitialSchemaRefSize) + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + Ch noUri[1] = {0}; + uri_.SetString(uri ? uri : noUri, uriLength, *allocator_); + + typeless_ = static_cast(allocator_->Malloc(sizeof(SchemaType))); + new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_); + + // Generate root schema, it will call CreateSchema() to create sub-schemas, + // And call AddRefSchema() if there are $ref. + CreateSchemaRecursive(&root_, PointerType(), document, document); + + // Resolve $ref + while (!schemaRef_.Empty()) { + SchemaRefEntry* refEntry = schemaRef_.template Pop(1); + if (const SchemaType* s = GetSchema(refEntry->target)) { + if (refEntry->schema) + *refEntry->schema = s; + + // Create entry in map if not exist + if (!GetSchema(refEntry->source)) { + new (schemaMap_.template Push()) SchemaEntry(refEntry->source, const_cast(s), false, allocator_); + } + } + else if (refEntry->schema) + *refEntry->schema = typeless_; + + refEntry->~SchemaRefEntry(); + } + + RAPIDJSON_ASSERT(root_ != 0); + + schemaRef_.ShrinkToFit(); // Deallocate all memory for ref + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : + remoteProvider_(rhs.remoteProvider_), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + root_(rhs.root_), + typeless_(rhs.typeless_), + schemaMap_(std::move(rhs.schemaMap_)), + schemaRef_(std::move(rhs.schemaRef_)), + uri_(std::move(rhs.uri_)) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.typeless_ = 0; + } +#endif + + //! Destructor + ~GenericSchemaDocument() { + while (!schemaMap_.Empty()) + schemaMap_.template Pop(1)->~SchemaEntry(); + + if (typeless_) { + typeless_->~SchemaType(); + Allocator::Free(typeless_); + } + + RAPIDJSON_DELETE(ownAllocator_); + } + + const URIType& GetURI() const { return uri_; } + + //! Get the root schema. + const SchemaType& GetRoot() const { return *root_; } + +private: + //! Prohibit copying + GenericSchemaDocument(const GenericSchemaDocument&); + //! Prohibit assignment + GenericSchemaDocument& operator=(const GenericSchemaDocument&); + + struct SchemaRefEntry { + SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {} + PointerType source; + PointerType target; + const SchemaType** schema; + }; + + struct SchemaEntry { + SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} + ~SchemaEntry() { + if (owned) { + schema->~SchemaType(); + Allocator::Free(schema); + } + } + PointerType pointer; + SchemaType* schema; + bool owned; + }; + + void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + if (schema) + *schema = typeless_; + + if (v.GetType() == kObjectType) { + const SchemaType* s = GetSchema(pointer); + if (!s) + CreateSchema(schema, pointer, v, document); + + for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) + CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document); + } + else if (v.GetType() == kArrayType) + for (SizeType i = 0; i < v.Size(); i++) + CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document); + } + + void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + RAPIDJSON_ASSERT(pointer.IsValid()); + if (v.IsObject()) { + if (!HandleRefSchema(pointer, schema, v, document)) { + SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_); + new (schemaMap_.template Push()) SchemaEntry(pointer, s, true, allocator_); + if (schema) + *schema = s; + } + } + } + + bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) { + static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' }; + static const ValueType kRefValue(kRefString, 4); + + typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue); + if (itr == v.MemberEnd()) + return false; + + if (itr->value.IsString()) { + SizeType len = itr->value.GetStringLength(); + if (len > 0) { + const Ch* s = itr->value.GetString(); + SizeType i = 0; + while (i < len && s[i] != '#') // Find the first # + i++; + + if (i > 0) { // Remote reference, resolve immediately + if (remoteProvider_) { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) { + PointerType pointer(&s[i], len - i, allocator_); + if (pointer.IsValid()) { + if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) { + if (schema) + *schema = sc; + new (schemaMap_.template Push()) SchemaEntry(source, const_cast(sc), false, allocator_); + return true; + } + } + } + } + } + else if (s[i] == '#') { // Local reference, defer resolution + PointerType pointer(&s[i], len - i, allocator_); + if (pointer.IsValid()) { + if (const ValueType* nv = pointer.Get(document)) + if (HandleRefSchema(source, schema, *nv, document)) + return true; + + new (schemaRef_.template Push()) SchemaRefEntry(source, pointer, schema, allocator_); + return true; + } + } + } + } + return false; + } + + const SchemaType* GetSchema(const PointerType& pointer) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (pointer == target->pointer) + return target->schema; + return 0; + } + + PointerType GetPointer(const SchemaType* schema) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (schema == target->schema) + return target->pointer; + return PointerType(); + } + + const SchemaType* GetTypeless() const { return typeless_; } + + static const size_t kInitialSchemaMapSize = 64; + static const size_t kInitialSchemaRefSize = 64; + + IRemoteSchemaDocumentProviderType* remoteProvider_; + Allocator *allocator_; + Allocator *ownAllocator_; + const SchemaType* root_; //!< Root schema. + SchemaType* typeless_; + internal::Stack schemaMap_; // Stores created Pointer -> Schemas + internal::Stack schemaRef_; // Stores Pointer from $ref and schema which holds the $ref + URIType uri_; +}; + +//! GenericSchemaDocument using Value type. +typedef GenericSchemaDocument SchemaDocument; +//! IGenericRemoteSchemaDocumentProvider using SchemaDocument. +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaValidator + +//! JSON Schema Validator. +/*! + A SAX style JSON schema validator. + It uses a \c GenericSchemaDocument to validate SAX events. + It delegates the incoming SAX events to an output handler. + The default output handler does nothing. + It can be reused multiple times by calling \c Reset(). + + \tparam SchemaDocumentType Type of schema document. + \tparam OutputHandler Type of output handler. Default handler does nothing. + \tparam StateAllocator Allocator for storing the internal validation states. +*/ +template < + typename SchemaDocumentType, + typename OutputHandler = BaseReaderHandler, + typename StateAllocator = CrtAllocator> +class GenericSchemaValidator : + public internal::ISchemaStateFactory, + public internal::ISchemaValidator, + public internal::IValidationErrorHandler { +public: + typedef typename SchemaDocumentType::SchemaType SchemaType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename SchemaType::EncodingType EncodingType; + typedef typename SchemaType::SValue SValue; + typedef typename EncodingType::Ch Ch; + typedef GenericStringRef StringRefType; + typedef GenericValue ValueType; + + //! Constructor without output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(0), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! Constructor with output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + OutputHandler& outputHandler, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(&outputHandler), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! Destructor. + ~GenericSchemaValidator() { + Reset(); + RAPIDJSON_DELETE(ownStateAllocator_); + } + + //! Reset the internal states. + void Reset() { + while (!schemaStack_.Empty()) + PopSchema(); + documentStack_.Clear(); + ResetError(); + } + + //! Reset the error state. + void ResetError() { + error_.SetObject(); + currentError_.SetNull(); + missingDependents_.SetNull(); + valid_ = true; + } + + //! Implementation of ISchemaValidator + void SetValidateFlags(unsigned flags) { + flags_ = flags; + } + virtual unsigned GetValidateFlags() const { + return flags_; + } + + //! Checks whether the current state is valid. + // Implementation of ISchemaValidator + virtual bool IsValid() const { + if (!valid_) return false; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return false; + return true; + } + + //! Gets the error object. + ValueType& GetError() { return error_; } + const ValueType& GetError() const { return error_; } + + //! Gets the JSON pointer pointed to the invalid schema. + // If reporting all errors, the stack will be empty. + PointerType GetInvalidSchemaPointer() const { + return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer(); + } + + //! Gets the keyword of invalid schema. + // If reporting all errors, the stack will be empty, so return "errors". + const Ch* GetInvalidSchemaKeyword() const { + if (!schemaStack_.Empty()) return CurrentContext().invalidKeyword; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return (const Ch*)GetErrorsString(); + return 0; + } + + //! Gets the error code of invalid schema. + // If reporting all errors, the stack will be empty, so return kValidateErrors. + ValidateErrorCode GetInvalidSchemaCode() const { + if (!schemaStack_.Empty()) return CurrentContext().invalidCode; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return kValidateErrors; + return kValidateErrorNone; + } + + //! Gets the JSON pointer pointed to the invalid value. + // If reporting all errors, the stack will be empty. + PointerType GetInvalidDocumentPointer() const { + if (documentStack_.Empty()) { + return PointerType(); + } + else { + return PointerType(documentStack_.template Bottom(), documentStack_.GetSize() / sizeof(Ch)); + } + } + + void NotMultipleOf(int64_t actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void NotMultipleOf(uint64_t actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void NotMultipleOf(double actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void AboveMaximum(double actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + void BelowMinimum(double actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + + void TooLong(const Ch* str, SizeType length, SizeType expected) { + AddNumberError(kValidateErrorMaxLength, + ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move()); + } + void TooShort(const Ch* str, SizeType length, SizeType expected) { + AddNumberError(kValidateErrorMinLength, + ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move()); + } + void DoesNotMatch(const Ch* str, SizeType length) { + currentError_.SetObject(); + currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorPattern); + } + + void DisallowedItem(SizeType index) { + currentError_.SetObject(); + currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorAdditionalItems, true); + } + void TooFewItems(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMinItems, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void TooManyItems(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMaxItems, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void DuplicateItems(SizeType index1, SizeType index2) { + ValueType duplicates(kArrayType); + duplicates.PushBack(index1, GetStateAllocator()); + duplicates.PushBack(index2, GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator()); + AddCurrentError(kValidateErrorUniqueItems, true); + } + + void TooManyProperties(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMaxProperties, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void TooFewProperties(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMinProperties, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void StartMissingProperties() { + currentError_.SetArray(); + } + void AddMissingProperty(const SValue& name) { + currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator()); + } + bool EndMissingProperties() { + if (currentError_.Empty()) + return false; + ValueType error(kObjectType); + error.AddMember(GetMissingString(), currentError_, GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorRequired); + return true; + } + void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) { + for (SizeType i = 0; i < count; ++i) + MergeError(static_cast(subvalidators[i])->GetError()); + } + void DisallowedProperty(const Ch* name, SizeType length) { + currentError_.SetObject(); + currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorAdditionalProperties, true); + } + + void StartDependencyErrors() { + currentError_.SetObject(); + } + void StartMissingDependentProperties() { + missingDependents_.SetArray(); + } + void AddMissingDependentProperty(const SValue& targetName) { + missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator()); + } + void EndMissingDependentProperties(const SValue& sourceName) { + if (!missingDependents_.Empty()) { + // Create equivalent 'required' error + ValueType error(kObjectType); + ValidateErrorCode code = kValidateErrorRequired; + error.AddMember(GetMissingString(), missingDependents_.Move(), GetStateAllocator()); + AddErrorCode(error, code); + AddErrorInstanceLocation(error, false); + // When appending to a pointer ensure its allocator is used + PointerType schemaRef = GetInvalidSchemaPointer().Append(SchemaType::GetValidateErrorKeyword(kValidateErrorDependencies), &GetInvalidSchemaPointer().GetAllocator()); + AddErrorSchemaLocation(error, schemaRef.Append(sourceName.GetString(), sourceName.GetStringLength(), &GetInvalidSchemaPointer().GetAllocator())); + ValueType wrapper(kObjectType); + wrapper.AddMember(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator()).Move(), error, GetStateAllocator()); + currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), wrapper, GetStateAllocator()); + } + } + void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) { + currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), + static_cast(subvalidator)->GetError(), GetStateAllocator()); + } + bool EndDependencyErrors() { + if (currentError_.ObjectEmpty()) + return false; + ValueType error(kObjectType); + error.AddMember(GetErrorsString(), currentError_, GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorDependencies); + return true; + } + + void DisallowedValue(const ValidateErrorCode code = kValidateErrorEnum) { + currentError_.SetObject(); + AddCurrentError(code); + } + void StartDisallowedType() { + currentError_.SetArray(); + } + void AddExpectedType(const typename SchemaType::ValueType& expectedType) { + currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator()); + } + void EndDisallowedType(const typename SchemaType::ValueType& actualType) { + ValueType error(kObjectType); + error.AddMember(GetExpectedString(), currentError_, GetStateAllocator()); + error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorType); + } + void NotAllOf(ISchemaValidator** subvalidators, SizeType count) { + // Treat allOf like oneOf and anyOf to match https://rapidjson.org/md_doc_schema.html#allOf-anyOf-oneOf + AddErrorArray(kValidateErrorAllOf, subvalidators, count); + //for (SizeType i = 0; i < count; ++i) { + // MergeError(static_cast(subvalidators[i])->GetError()); + //} + } + void NoneOf(ISchemaValidator** subvalidators, SizeType count) { + AddErrorArray(kValidateErrorAnyOf, subvalidators, count); + } + void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched = false) { + AddErrorArray(matched ? kValidateErrorOneOfMatch : kValidateErrorOneOf, subvalidators, count); + } + void Disallowed() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorNot); + } + +#define RAPIDJSON_STRING_(name, ...) \ + static const StringRefType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const StringRefType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1)); \ + return v;\ + } + + RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') + RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f') + RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd') + RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l') + RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd') + RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g') + RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's') + RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') + RAPIDJSON_STRING_(ErrorMessage, 'e', 'r', 'r', 'o', 'r', 'M', 'e', 's', 's', 'a', 'g', 'e') + RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's') + +#undef RAPIDJSON_STRING_ + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + *documentStack_.template Push() = '\0';\ + documentStack_.template Pop(1);\ + internal::PrintInvalidDocument(documentStack_.template Bottom());\ +RAPIDJSON_MULTILINEMACRO_END +#else +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() +#endif + +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ + if (!valid_) return false; \ + if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ + return valid_ = false;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ + for (Context* context = schemaStack_.template Bottom(); context != schemaStack_.template End(); context++) {\ + if (context->hasher)\ + static_cast(context->hasher)->method arg2;\ + if (context->validators)\ + for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ + static_cast(context->validators[i_])->method arg2;\ + if (context->patternPropertiesValidators)\ + for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ + static_cast(context->patternPropertiesValidators[i_])->method arg2;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ + valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\ + return valid_; + +#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ + RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) + + bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); } + bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); } + bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); } + bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); } + bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); } + bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); } + bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); } + bool RawNumber(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + bool String(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + + bool StartObject() { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); + return valid_ = !outputHandler_ || outputHandler_->StartObject(); + } + + bool Key(const Ch* str, SizeType len, bool copy) { + if (!valid_) return false; + AppendToken(str, len); + if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); + return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy); + } + + bool EndObject(SizeType memberCount) { + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); + if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); + } + + bool StartArray() { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); + return valid_ = !outputHandler_ || outputHandler_->StartArray(); + } + + bool EndArray(SizeType elementCount) { + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); + if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); + } + +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ +#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ +#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ + + // Implementation of ISchemaStateFactory + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root, const bool inheritContinueOnErrors) { + ISchemaValidator* sv = new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom(), documentStack_.GetSize(), +#if RAPIDJSON_SCHEMA_VERBOSE + depth_ + 1, +#endif + &GetStateAllocator()); + sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(unsigned)kValidateContinueOnErrorFlag); + return sv; + } + + virtual void DestroySchemaValidator(ISchemaValidator* validator) { + GenericSchemaValidator* v = static_cast(validator); + v->~GenericSchemaValidator(); + StateAllocator::Free(v); + } + + virtual void* CreateHasher() { + return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator()); + } + + virtual uint64_t GetHashCode(void* hasher) { + return static_cast(hasher)->GetHashCode(); + } + + virtual void DestroryHasher(void* hasher) { + HasherType* h = static_cast(hasher); + h->~HasherType(); + StateAllocator::Free(h); + } + + virtual void* MallocState(size_t size) { + return GetStateAllocator().Malloc(size); + } + + virtual void FreeState(void* p) { + StateAllocator::Free(p); + } + +private: + typedef typename SchemaType::Context Context; + typedef GenericValue, StateAllocator> HashCodeArray; + typedef internal::Hasher HasherType; + + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + const SchemaType& root, + const char* basePath, size_t basePathSize, +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth, +#endif + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(root), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(0), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(depth) +#endif + { + if (basePath && basePathSize) + memcpy(documentStack_.template Push(basePathSize), basePath, basePathSize); + } + + StateAllocator& GetStateAllocator() { + if (!stateAllocator_) + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)(); + return *stateAllocator_; + } + + bool GetContinueOnErrors() const { + return flags_ & kValidateContinueOnErrorFlag; + } + + bool BeginValue() { + if (schemaStack_.Empty()) + PushSchema(root_); + else { + if (CurrentContext().inArray) + internal::TokenHelper, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex); + + if (!CurrentSchema().BeginValue(CurrentContext()) && !GetContinueOnErrors()) + return false; + + SizeType count = CurrentContext().patternPropertiesSchemaCount; + const SchemaType** sa = CurrentContext().patternPropertiesSchemas; + typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; + bool valueUniqueness = CurrentContext().valueUniqueness; + RAPIDJSON_ASSERT(CurrentContext().valueSchema); + PushSchema(*CurrentContext().valueSchema); + + if (count > 0) { + CurrentContext().objectPatternValidatorType = patternValidatorType; + ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; + SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; + va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); + for (SizeType i = 0; i < count; i++) + va[validatorCount++] = CreateSchemaValidator(*sa[i], true); // Inherit continueOnError + } + + CurrentContext().arrayUniqueness = valueUniqueness; + } + return true; + } + + bool EndValue() { + if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors()) + return false; + +#if RAPIDJSON_SCHEMA_VERBOSE + GenericStringBuffer sb; + schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); + + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); + internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom()); +#endif + void* hasher = CurrentContext().hasher; + uint64_t h = hasher && CurrentContext().arrayUniqueness ? static_cast(hasher)->GetHashCode() : 0; + + PopSchema(); + + if (!schemaStack_.Empty()) { + Context& context = CurrentContext(); + // Only check uniqueness if there is a hasher + if (hasher && context.valueUniqueness) { + HashCodeArray* a = static_cast(context.arrayElementHashCodes); + if (!a) + CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType); + for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) + if (itr->GetUint64() == h) { + DuplicateItems(static_cast(itr - a->Begin()), a->Size()); + // Cleanup before returning if continuing + if (GetContinueOnErrors()) { + a->PushBack(h, GetStateAllocator()); + while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/'); + } + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems); + } + a->PushBack(h, GetStateAllocator()); + } + } + + // Remove the last token of document pointer + while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/') + ; + + return true; + } + + void AppendToken(const Ch* str, SizeType len) { + documentStack_.template Reserve(1 + len * 2); // worst case all characters are escaped as two characters + *documentStack_.template PushUnsafe() = '/'; + for (SizeType i = 0; i < len; i++) { + if (str[i] == '~') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '0'; + } + else if (str[i] == '/') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '1'; + } + else + *documentStack_.template PushUnsafe() = str[i]; + } + } + + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, *this, &schema); } + + RAPIDJSON_FORCEINLINE void PopSchema() { + Context* c = schemaStack_.template Pop(1); + if (HashCodeArray* a = static_cast(c->arrayElementHashCodes)) { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + c->~Context(); + } + + void AddErrorInstanceLocation(ValueType& result, bool parent) { + GenericStringBuffer sb; + PointerType instancePointer = GetInvalidDocumentPointer(); + ((parent && instancePointer.GetTokenCount() > 0) + ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1) + : instancePointer).StringifyUriFragment(sb); + ValueType instanceRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), + GetStateAllocator()); + result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator()); + } + + void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) { + GenericStringBuffer sb; + SizeType len = CurrentSchema().GetURI().GetStringLength(); + if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch)); + if (schema.GetTokenCount()) schema.StringifyUriFragment(sb); + else GetInvalidSchemaPointer().StringifyUriFragment(sb); + ValueType schemaRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), + GetStateAllocator()); + result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator()); + } + + void AddErrorCode(ValueType& result, const ValidateErrorCode code) { + result.AddMember(GetErrorCodeString(), code, GetStateAllocator()); + } + + void AddError(ValueType& keyword, ValueType& error) { + typename ValueType::MemberIterator member = error_.FindMember(keyword); + if (member == error_.MemberEnd()) + error_.AddMember(keyword, error, GetStateAllocator()); + else { + if (member->value.IsObject()) { + ValueType errors(kArrayType); + errors.PushBack(member->value, GetStateAllocator()); + member->value = errors; + } + member->value.PushBack(error, GetStateAllocator()); + } + } + + void AddCurrentError(const ValidateErrorCode code, bool parent = false) { + AddErrorCode(currentError_, code); + AddErrorInstanceLocation(currentError_, parent); + AddErrorSchemaLocation(currentError_); + AddError(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator(), false).Move(), currentError_); + } + + void MergeError(ValueType& other) { + for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) { + AddError(it->name, it->value); + } + } + + void AddNumberError(const ValidateErrorCode code, ValueType& actual, const SValue& expected, + const typename SchemaType::ValueType& (*exclusive)() = 0) { + currentError_.SetObject(); + currentError_.AddMember(GetActualString(), actual, GetStateAllocator()); + currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator()); + if (exclusive) + currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator()); + AddCurrentError(code); + } + + void AddErrorArray(const ValidateErrorCode code, + ISchemaValidator** subvalidators, SizeType count) { + ValueType errors(kArrayType); + for (SizeType i = 0; i < count; ++i) + errors.PushBack(static_cast(subvalidators[i])->GetError(), GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator()); + AddCurrentError(code); + } + + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top()->schema; } + Context& CurrentContext() { return *schemaStack_.template Top(); } + const Context& CurrentContext() const { return *schemaStack_.template Top(); } + + static const size_t kDefaultSchemaStackCapacity = 1024; + static const size_t kDefaultDocumentStackCapacity = 256; + const SchemaDocumentType* schemaDocument_; + const SchemaType& root_; + StateAllocator* stateAllocator_; + StateAllocator* ownStateAllocator_; + internal::Stack schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack documentStack_; //!< stack to store the current path of validating document (Ch) + OutputHandler* outputHandler_; + ValueType error_; + ValueType currentError_; + ValueType missingDependents_; + bool valid_; + unsigned flags_; +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth_; +#endif +}; + +typedef GenericSchemaValidator SchemaValidator; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidatingReader + +//! A helper class for parsing with validation. +/*! + This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate(). + + \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam SourceEncoding Encoding of the input stream. + \tparam SchemaDocumentType Type of schema document. + \tparam StackAllocator Allocator type for stack. +*/ +template < + unsigned parseFlags, + typename InputStream, + typename SourceEncoding, + typename SchemaDocumentType = SchemaDocument, + typename StackAllocator = CrtAllocator> +class SchemaValidatingReader { +public: + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename InputStream::Ch Ch; + typedef GenericValue ValueType; + + //! Constructor + /*! + \param is Input stream. + \param sd Schema document. + */ + SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), invalidSchemaCode_(kValidateErrorNone), error_(kObjectType), isValid_(true) {} + + template + bool operator()(Handler& handler) { + GenericReader reader; + GenericSchemaValidator validator(sd_, handler); + parseResult_ = reader.template Parse(is_, validator); + + isValid_ = validator.IsValid(); + if (isValid_) { + invalidSchemaPointer_ = PointerType(); + invalidSchemaKeyword_ = 0; + invalidDocumentPointer_ = PointerType(); + error_.SetObject(); + } + else { + invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); + invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); + invalidSchemaCode_ = validator.GetInvalidSchemaCode(); + invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); + error_.CopyFrom(validator.GetError(), allocator_); + } + + return parseResult_; + } + + const ParseResult& GetParseResult() const { return parseResult_; } + bool IsValid() const { return isValid_; } + const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; } + const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; } + const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; } + const ValueType& GetError() const { return error_; } + ValidateErrorCode GetInvalidSchemaCode() const { return invalidSchemaCode_; } + +private: + InputStream& is_; + const SchemaDocumentType& sd_; + + ParseResult parseResult_; + PointerType invalidSchemaPointer_; + const Ch* invalidSchemaKeyword_; + PointerType invalidDocumentPointer_; + ValidateErrorCode invalidSchemaCode_; + StackAllocator allocator_; + ValueType error_; + bool isValid_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_SCHEMA_H_ diff --git a/rapidjson/stream.h b/rapidjson/stream.h new file mode 100644 index 0000000..1fd7091 --- /dev/null +++ b/rapidjson/stream.h @@ -0,0 +1,223 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "rapidjson.h" + +#ifndef RAPIDJSON_STREAM_H_ +#define RAPIDJSON_STREAM_H_ + +#include "encodings.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits. + */ + enum { copyOptimization = 0 }; +}; + +//! Reserve n characters for writing to a stream. +template +inline void PutReserve(Stream& stream, size_t count) { + (void)stream; + (void)count; +} + +//! Write character to a stream, presuming buffer is reserved. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { + stream.Put(c); +} + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + PutReserve(stream, n); + for (size_t i = 0; i < n; i++) + PutUnsafe(stream, c); +} + +/////////////////////////////////////////////////////////////////////////////// +// GenericStreamWrapper + +//! A Stream Wrapper +/*! \tThis string stream is a wrapper for any stream by just forwarding any + \treceived message to the origin stream. + \note implements Stream concept +*/ + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4702) // unreachable code +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +template > +class GenericStreamWrapper { +public: + typedef typename Encoding::Ch Ch; + GenericStreamWrapper(InputStream& is): is_(is) {} + + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() { return is_.Tell(); } + Ch* PutBegin() { return is_.PutBegin(); } + void Put(Ch ch) { is_.Put(ch); } + void Flush() { is_.Flush(); } + size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); } + + // wrapper for MemoryStream + const Ch* Peek4() const { return is_.Peek4(); } + + // wrapper for AutoUTFInputStream + UTFType GetType() const { return is_.GetType(); } + bool HasBOM() const { return is_.HasBOM(); } + +protected: + InputStream& is_; +}; + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_POP +#endif + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream > InsituStringStream; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STREAM_H_ diff --git a/rapidjson/stringbuffer.h b/rapidjson/stringbuffer.h new file mode 100644 index 0000000..82ad3ca --- /dev/null +++ b/rapidjson/stringbuffer.h @@ -0,0 +1,121 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#include "internal/stack.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif + + void Put(Ch c) { *stack_.template Push() = c; } + void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop(1); + } + + void Reserve(size_t count) { stack_.template Reserve(count); } + Ch* Push(size_t count) { return stack_.template Push(count); } + Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); + + return stack_.template Bottom(); + } + + //! Get the size of string in bytes in the string buffer. + size_t GetSize() const { return stack_.GetSize(); } + + //! Get the length of string in Ch in the string buffer. + size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer > StringBuffer; + +template +inline void PutReserve(GenericStringBuffer& stream, size_t count) { + stream.Reserve(count); +} + +template +inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { + stream.PutUnsafe(c); +} + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { + std::memset(stream.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/rapidjson/uri.h b/rapidjson/uri.h new file mode 100644 index 0000000..f93e508 --- /dev/null +++ b/rapidjson/uri.h @@ -0,0 +1,481 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// (C) Copyright IBM Corporation 2021 +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_URI_H_ +#define RAPIDJSON_URI_H_ + +#include "internal/strfunc.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// GenericUri + +template +class GenericUri { +public: + typedef typename ValueType::Ch Ch; +#if RAPIDJSON_HAS_STDSTRING + typedef std::basic_string String; +#endif + + //! Constructors + GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + } + + GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri, len); + } + + GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri, internal::StrLen(uri)); + } + + // Use with specializations of GenericValue + template GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + const Ch* u = uri.template Get(); // TypeHelper from document.h + Parse(u, internal::StrLen(u)); + } + +#if RAPIDJSON_HAS_STDSTRING + GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri.c_str(), internal::StrLen(uri.c_str())); + } +#endif + + //! Copy constructor + GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() { + *this = rhs; + } + + //! Copy constructor + GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + *this = rhs; + } + + //! Destructor. + ~GenericUri() { + Free(); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator + GenericUri& operator=(const GenericUri& rhs) { + if (this != &rhs) { + // Do not delete ownAllocator + Free(); + Allocate(rhs.GetStringLength()); + auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength()); + path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength()); + query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength()); + frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength()); + base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength()); + uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength()); + CopyPart(uri_, rhs.uri_, rhs.GetStringLength()); + } + return *this; + } + + //! Getters + // Use with specializations of GenericValue + template void Get(T& uri, Allocator& allocator) { + uri.template Set(this->GetString(), allocator); // TypeHelper from document.h + } + + const Ch* GetString() const { return uri_; } + SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen(uri_); } + const Ch* GetBaseString() const { return base_; } + SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen(base_); } + const Ch* GetSchemeString() const { return scheme_; } + SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen(scheme_); } + const Ch* GetAuthString() const { return auth_; } + SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen(auth_); } + const Ch* GetPathString() const { return path_; } + SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen(path_); } + const Ch* GetQueryString() const { return query_; } + SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen(query_); } + const Ch* GetFragString() const { return frag_; } + SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen(frag_); } + +#if RAPIDJSON_HAS_STDSTRING + static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); } + static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); } + static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); } + static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); } + static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); } + static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); } + static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); } +#endif + + //! Equality operators + bool operator==(const GenericUri& rhs) const { + return Match(rhs, true); + } + + bool operator!=(const GenericUri& rhs) const { + return !Match(rhs, true); + } + + bool Match(const GenericUri& uri, bool full = true) const { + Ch* s1; + Ch* s2; + if (full) { + s1 = uri_; + s2 = uri.uri_; + } else { + s1 = base_; + s2 = uri.base_; + } + if (s1 == s2) return true; + if (s1 == 0 || s2 == 0) return false; + return internal::StrCmp(s1, s2) == 0; + } + + //! Resolve this URI against another (base) URI in accordance with URI resolution rules. + // See https://tools.ietf.org/html/rfc3986 + // Use for resolving an id or $ref with an in-scope id. + // Returns a new GenericUri for the resolved URI. + GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) { + GenericUri resuri; + resuri.allocator_ = allocator; + // Ensure enough space for combining paths + resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash + + if (!(GetSchemeStringLength() == 0)) { + // Use all of this URI + resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength()); + resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + resuri.RemoveDotSegments(); + } else { + // Use the base scheme + resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength()); + if (!(GetAuthStringLength() == 0)) { + // Use this auth, path, query + resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + resuri.RemoveDotSegments(); + } else { + // Use the base auth + resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength()); + if (GetPathStringLength() == 0) { + // Use the base path + resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength()); + if (GetQueryStringLength() == 0) { + // Use the base query + resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength()); + } else { + // Use this query + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + } + } else { + if (path_[0] == '/') { + // Absolute path - use all of this path + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.RemoveDotSegments(); + } else { + // Relative path - append this path to base path after base path's last slash + size_t pos = 0; + if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) { + resuri.path_[pos] = '/'; + pos++; + } + size_t lastslashpos = baseuri.GetPathStringLength(); + while (lastslashpos > 0) { + if (baseuri.path_[lastslashpos - 1] == '/') break; + lastslashpos--; + } + std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch)); + pos += lastslashpos; + resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength()); + resuri.RemoveDotSegments(); + } + // Use this query + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + } + } + } + // Always use this frag + resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength()); + + // Re-constitute base_ and uri_ + resuri.SetBase(); + resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1; + resuri.SetUri(); + return resuri; + } + + //! Get the allocator of this GenericUri. + Allocator& GetAllocator() { return *allocator_; } + +private: + // Allocate memory for a URI + // Returns total amount allocated + std::size_t Allocate(std::size_t len) { + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated. + // Order: scheme, auth, path, query, frag, base, uri + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + size_t total = (3 * len + 7) * sizeof(Ch); + scheme_ = static_cast(allocator_->Malloc(total)); + *scheme_ = '\0'; + auth_ = scheme_; + auth_++; + *auth_ = '\0'; + path_ = auth_; + path_++; + *path_ = '\0'; + query_ = path_; + query_++; + *query_ = '\0'; + frag_ = query_; + frag_++; + *frag_ = '\0'; + base_ = frag_; + base_++; + *base_ = '\0'; + uri_ = base_; + uri_++; + *uri_ = '\0'; + return total; + } + + // Free memory for a URI + void Free() { + if (scheme_) { + Allocator::Free(scheme_); + scheme_ = 0; + } + } + + // Parse a URI into constituent scheme, authority, path, query, & fragment parts + // Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per + // https://tools.ietf.org/html/rfc3986 + void Parse(const Ch* uri, std::size_t len) { + std::size_t start = 0, pos1 = 0, pos2 = 0; + Allocate(len); + + // Look for scheme ([^:/?#]+):)? + if (start < len) { + while (pos1 < len) { + if (uri[pos1] == ':') break; + pos1++; + } + if (pos1 != len) { + while (pos2 < len) { + if (uri[pos2] == '/') break; + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + if (pos1 < pos2) { + pos1++; + std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch)); + scheme_[pos1] = '\0'; + start = pos1; + } + } + } + // Look for auth (//([^/?#]*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + auth_ = scheme_ + GetSchemeStringLength(); + auth_++; + *auth_ = '\0'; + if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') { + pos2 = start + 2; + while (pos2 < len) { + if (uri[pos2] == '/') break; + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch)); + auth_[pos2 - start] = '\0'; + start = pos2; + } + // Look for path ([^?#]*) + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + path_ = auth_ + GetAuthStringLength(); + path_++; + *path_ = '\0'; + if (start < len) { + pos2 = start; + while (pos2 < len) { + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + if (start != pos2) { + std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch)); + path_[pos2 - start] = '\0'; + if (path_[0] == '/') + RemoveDotSegments(); // absolute path - normalize + start = pos2; + } + } + // Look for query (\?([^#]*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + query_ = path_ + GetPathStringLength(); + query_++; + *query_ = '\0'; + if (start < len && uri[start] == '?') { + pos2 = start + 1; + while (pos2 < len) { + if (uri[pos2] == '#') break; + pos2++; + } + if (start != pos2) { + std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch)); + query_[pos2 - start] = '\0'; + start = pos2; + } + } + // Look for fragment (#(.*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + frag_ = query_ + GetQueryStringLength(); + frag_++; + *frag_ = '\0'; + if (start < len && uri[start] == '#') { + std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch)); + frag_[len - start] = '\0'; + } + + // Re-constitute base_ and uri_ + base_ = frag_ + GetFragStringLength() + 1; + SetBase(); + uri_ = base_ + GetBaseStringLength() + 1; + SetUri(); + } + + // Reconstitute base + void SetBase() { + Ch* next = base_; + std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch)); + next+= GetSchemeStringLength(); + std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch)); + next+= GetAuthStringLength(); + std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch)); + next+= GetPathStringLength(); + std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch)); + next+= GetQueryStringLength(); + *next = '\0'; + } + + // Reconstitute uri + void SetUri() { + Ch* next = uri_; + std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch)); + next+= GetBaseStringLength(); + std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch)); + next+= GetFragStringLength(); + *next = '\0'; + } + + // Copy a part from one GenericUri to another + // Return the pointer to the next part to be copied to + Ch* CopyPart(Ch* to, Ch* from, std::size_t len) { + RAPIDJSON_ASSERT(to != 0); + RAPIDJSON_ASSERT(from != 0); + std::memcpy(to, from, len * sizeof(Ch)); + to[len] = '\0'; + Ch* next = to + len + 1; + return next; + } + + // Remove . and .. segments from the path_ member. + // https://tools.ietf.org/html/rfc3986 + // This is done in place as we are only removing segments. + void RemoveDotSegments() { + std::size_t pathlen = GetPathStringLength(); + std::size_t pathpos = 0; // Position in path_ + std::size_t newpos = 0; // Position in new path_ + + // Loop through each segment in original path_ + while (pathpos < pathlen) { + // Get next segment, bounded by '/' or end + size_t slashpos = 0; + while ((pathpos + slashpos) < pathlen) { + if (path_[pathpos + slashpos] == '/') break; + slashpos++; + } + // Check for .. and . segments + if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') { + // Backup a .. segment in the new path_ + // We expect to find a previously added slash at the end or nothing + RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/'); + size_t lastslashpos = newpos; + // Make sure we don't go beyond the start segment + if (lastslashpos > 1) { + // Find the next to last slash and back up to it + lastslashpos--; + while (lastslashpos > 0) { + if (path_[lastslashpos - 1] == '/') break; + lastslashpos--; + } + // Set the new path_ position + newpos = lastslashpos; + } + } else if (slashpos == 1 && path_[pathpos] == '.') { + // Discard . segment, leaves new path_ unchanged + } else { + // Move any other kind of segment to the new path_ + RAPIDJSON_ASSERT(newpos <= pathpos); + std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch)); + newpos += slashpos; + // Add slash if not at end + if ((pathpos + slashpos) < pathlen) { + path_[newpos] = '/'; + newpos++; + } + } + // Move to next segment + pathpos += slashpos + 1; + } + path_[newpos] = '\0'; + } + + Ch* uri_; // Everything + Ch* base_; // Everything except fragment + Ch* scheme_; // Includes the : + Ch* auth_; // Includes the // + Ch* path_; // Absolute if starts with / + Ch* query_; // Includes the ? + Ch* frag_; // Includes the # + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Uri. +}; + +//! GenericUri for Value (UTF-8, default allocator). +typedef GenericUri Uri; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_URI_H_ diff --git a/rapidjson/writer.h b/rapidjson/writer.h new file mode 100644 index 0000000..8b38921 --- /dev/null +++ b/rapidjson/writer.h @@ -0,0 +1,710 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "stream.h" +#include "internal/clzll.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include // placement new + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#elif defined(RAPIDJSON_NEON) +#include +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// WriteFlag + +/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kWriteDefaultFlags definition. + + User can define this as any \c WriteFlag combinations. +*/ +#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS +#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags +#endif + +//! Combination of writeFlags +enum WriteFlag { + kWriteNoFlags = 0, //!< No flags are set. + kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. + kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS +}; + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + static const int kDefaultMaxDecimalPlaces = 324; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Writer(Writer&& rhs) : + os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { + rhs.os_ = 0; + } +#endif + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + int GetMaxDecimalPlaces() const { + return maxDecimalPlaces_; + } + + //! Sets the maximum number of decimal places for double output. + /*! + This setting truncates the output with specified number of decimal places. + + For example, + + \code + writer.SetMaxDecimalPlaces(3); + writer.StartArray(); + writer.Double(0.12345); // "0.123" + writer.Double(0.0001); // "0.0" + writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) + writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) + writer.EndArray(); + \endcode + + The default setting does not truncate any decimal places. You can restore to this setting by calling + \code + writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); + \endcode + */ + void SetMaxDecimalPlaces(int maxDecimalPlaces) { + maxDecimalPlaces_ = maxDecimalPlaces; + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } + bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } + bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } + bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kNumberType); + return EndValue(WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kStringType); + return EndValue(WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) + { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + level_stack_.template Pop(1); + return EndValue(WriteEndObject()); + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + return EndValue(WriteEndArray()); + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + Prefix(type); + return EndValue(WriteRawValue(json, length)); + } + + //! Flush the output stream. + /*! + Allows the user to flush the output stream immediately. + */ + void Flush() { + os_->Flush(); + } + + static const size_t kDefaultLevelDepth = 32; + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + bool WriteNull() { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); + } + else { + PutReserve(*os_, 5); + PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + if (!(writeFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char buffer[25]; + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + if (TargetEncoding::supportUnicode) + PutReserve(*os_, 2 + length * 6); // "\uxxxx..." + else + PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + + PutUnsafe(*os_, '\"'); + GenericStringStream is(str); + while (ScanWriteUnescapedString(is, length)) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && static_cast(c) >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) + return false; + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(lead ) & 15]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || static_cast(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast(c)])) { + is.Take(); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast(escape[static_cast(c)])); + if (escape[static_cast(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast(c) & 0xF]); + } + } + else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + return false; + } + PutUnsafe(*os_, '\"'); + return true; + } + + bool ScanWriteUnescapedString(GenericStringStream& is, size_t length) { + return RAPIDJSON_LIKELY(is.Tell() < length); + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + bool WriteRawValue(const Ch* json, size_t length) { + PutReserve(*os_, length); + GenericStringStream is(json); + while (RAPIDJSON_LIKELY(is.Tell() < length)) { + RAPIDJSON_ASSERT(is.Peek() != '\0'); + if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + return false; + } + return true; + } + + void Prefix(Type type) { + (void)type; + if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root + Level* level = level_stack_.template Top(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + // Flush the value if it is the top level one. + bool EndValue(bool ret) { + if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text + Flush(); + return ret; + } + + OutputStream* os_; + internal::Stack level_stack_; + int maxDecimalPlaces_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). + if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + os_->Pop(static_cast(25 - (end - buffer))); + return true; +} + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (; p != endAligned; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType len; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + len = offset; +#else + len = static_cast(__builtin_ffs(r) - 1); +#endif + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#elif defined(RAPIDJSON_NEON) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (; p != endAligned; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType len = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + len = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + len = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + vst1q_u8(reinterpret_cast(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#endif // RAPIDJSON_NEON + +RAPIDJSON_NAMESPACE_END + +#if defined(_MSC_VER) || defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/stemmerGiveUp.h b/stemmerGiveUp.h new file mode 100644 index 0000000..e062215 --- /dev/null +++ b/stemmerGiveUp.h @@ -0,0 +1,334 @@ + +/* This is the Porter stemming algorithm, coded up in ANSI C by the + author. It may be be regarded as canonical, in that it follows the + algorithm presented in + + Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14, + no. 3, pp 130-137, + + only differing from it at the points marked --DEPARTURE-- below. + + See also http://www.tartarus.org/~martin/PorterStemmer + + The algorithm as described in the paper could be exactly replicated + by adjusting the points of DEPARTURE, but this is barely necessary, + because (a) the points of DEPARTURE are definitely improvements, and + (b) no encoding of the Porter stemmer I have seen is anything like + as exact as this version, even with the points of DEPARTURE! + + You can compile it on Unix with 'gcc -O3 -o stem stem.c' after which + 'stem' takes a list of inputs and sends the stemmed equivalent to + stdout. + + The algorithm as encoded here is particularly fast. + + Release 1: was many years ago + Release 2: 11 Apr 2013 + fixes a bug noted by Matt Patenaude , + + case 'o': if (ends("\03" "ion") && (b[j] == 's' || b[j] == 't')) break; + ==> + case 'o': if (ends("\03" "ion") && j >= k0 && (b[j] == 's' || b[j] == 't')) break; + + to avoid accessing b[k0-1] when the word in b is "ion". + Release 3: 25 Mar 2014 + fixes a similar bug noted by Klemens Baum , + that if step1ab leaves a one letter result (ied -> i, aing -> a etc), + step2 and step4 access the byte before the first letter. So we skip + steps after step1ab unless k > k0. +*/ + +#include /* for memmove */ + +#define TRUE 1 +#define FALSE 0 + +/* The main part of the stemming algorithm starts here. b is a buffer + holding a word to be stemmed. The letters are in b[k0], b[k0+1] ... + ending at b[k]. In fact k0 = 0 in this demo program. k is readjusted + downwards as the stemming progresses. Zero termination is not in fact + used in the algorithm. + + Note that only lower case sequences are stemmed. Forcing to lower case + should be done before stem(...) is called. +*/ + +static char * b; /* buffer for word to be stemmed */ +static int k,k0,j; /* j is a general offset into the string */ + +/* cons(i) is TRUE <=> b[i] is a consonant. */ + +static int cons(int i) +{ switch (b[i]) + { case 'a': case 'e': case 'i': case 'o': case 'u': return FALSE; + case 'y': return (i==k0) ? TRUE : !cons(i-1); + default: return TRUE; + } +} + +/* m() measures the number of consonant sequences between k0 and j. if c is + a consonant sequence and v a vowel sequence, and <..> indicates arbitrary + presence, + + gives 0 + vc gives 1 + vcvc gives 2 + vcvcvc gives 3 + .... +*/ + +static int m() +{ int n = 0; + int i = k0; + while(TRUE) + { if (i > j) return n; + if (! cons(i)) break; i++; + } + i++; + while(TRUE) + { while(TRUE) + { if (i > j) return n; + if (cons(i)) break; + i++; + } + i++; + n++; + while(TRUE) + { if (i > j) return n; + if (! cons(i)) break; + i++; + } + i++; + } +} + +/* vowelinstem() is TRUE <=> k0,...j contains a vowel */ + +static int vowelinstem() +{ int i; for (i = k0; i <= j; i++) if (! cons(i)) return TRUE; + return FALSE; +} + +/* doublec(j) is TRUE <=> j,(j-1) contain a double consonant. */ + +static int doublec(int j) +{ if (j < k0+1) return FALSE; + if (b[j] != b[j-1]) return FALSE; + return cons(j); +} + +/* cvc(i) is TRUE <=> i-2,i-1,i has the form consonant - vowel - consonant + and also if the second c is not w,x or y. this is used when trying to + restore an e at the end of a short word. e.g. + + cav(e), lov(e), hop(e), crim(e), but + snow, box, tray. + +*/ + +static int cvc(int i) +{ if (i < k0+2 || !cons(i) || cons(i-1) || !cons(i-2)) return FALSE; + { int ch = b[i]; + if (ch == 'w' || ch == 'x' || ch == 'y') return FALSE; + } + return TRUE; +} + +/* ends(s) is TRUE <=> k0,...k ends with the string s. */ + +static int ends(char * s) +{ int length = s[0]; + if (s[length] != b[k]) return FALSE; /* tiny speed-up */ + if (length > k-k0+1) return FALSE; + if (memcmp(b+k-length+1,s+1,length) != 0) return FALSE; + j = k-length; + return TRUE; +} + +/* setto(s) sets (j+1),...k to the characters in the string s, readjusting + k. */ + +static void setto(char * s) +{ int length = s[0]; + memmove(b+j+1,s+1,length); + k = j+length; +} + +/* r(s) is used further down. */ + +static void r(char * s) { if (m() > 0) setto(s); } + +/* step1ab() gets rid of plurals and -ed or -ing. e.g. + + caresses -> caress + ponies -> poni + ties -> ti + caress -> caress + cats -> cat + + feed -> feed + agreed -> agree + disabled -> disable + + matting -> mat + mating -> mate + meeting -> meet + milling -> mill + messing -> mess + + meetings -> meet + +*/ + +static void step1ab() +{ if (b[k] == 's') + { if (ends("\04" "sses")) k -= 2; else + if (ends("\03" "ies")) setto("\01" "i"); else + if (b[k-1] != 's') k--; + } + if (ends("\03" "eed")) { if (m() > 0) k--; } else + if ((ends("\02" "ed") || ends("\03" "ing")) && vowelinstem()) + { k = j; + if (ends("\02" "at")) setto("\03" "ate"); else + if (ends("\02" "bl")) setto("\03" "ble"); else + if (ends("\02" "iz")) setto("\03" "ize"); else + if (doublec(k)) + { k--; + { int ch = b[k]; + if (ch == 'l' || ch == 's' || ch == 'z') k++; + } + } + else if (m() == 1 && cvc(k)) setto("\01" "e"); + } +} + +/* step1c() turns terminal y to i when there is another vowel in the stem. */ + +static void step1c() { if (ends("\01" "y") && vowelinstem()) b[k] = 'i'; } + + +/* step2() maps double suffices to single ones. so -ization ( = -ize plus + -ation) maps to -ize etc. note that the string before the suffix must give + m() > 0. */ + +static void step2() { switch (b[k-1]) + { + case 'a': if (ends("\07" "ational")) { r("\03" "ate"); break; } + if (ends("\06" "tional")) { r("\04" "tion"); break; } + break; + case 'c': if (ends("\04" "enci")) { r("\04" "ence"); break; } + if (ends("\04" "anci")) { r("\04" "ance"); break; } + break; + case 'e': if (ends("\04" "izer")) { r("\03" "ize"); break; } + break; + case 'l': if (ends("\03" "bli")) { r("\03" "ble"); break; } /*-DEPARTURE-*/ + + /* To match the published algorithm, replace this line with + case 'l': if (ends("\04" "abli")) { r("\04" "able"); break; } */ + + if (ends("\04" "alli")) { r("\02" "al"); break; } + if (ends("\05" "entli")) { r("\03" "ent"); break; } + if (ends("\03" "eli")) { r("\01" "e"); break; } + if (ends("\05" "ousli")) { r("\03" "ous"); break; } + break; + case 'o': if (ends("\07" "ization")) { r("\03" "ize"); break; } + if (ends("\05" "ation")) { r("\03" "ate"); break; } + if (ends("\04" "ator")) { r("\03" "ate"); break; } + break; + case 's': if (ends("\05" "alism")) { r("\02" "al"); break; } + if (ends("\07" "iveness")) { r("\03" "ive"); break; } + if (ends("\07" "fulness")) { r("\03" "ful"); break; } + if (ends("\07" "ousness")) { r("\03" "ous"); break; } + break; + case 't': if (ends("\05" "aliti")) { r("\02" "al"); break; } + if (ends("\05" "iviti")) { r("\03" "ive"); break; } + if (ends("\06" "biliti")) { r("\03" "ble"); break; } + break; + case 'g': if (ends("\04" "logi")) { r("\03" "log"); break; } /*-DEPARTURE-*/ + + /* To match the published algorithm, delete this line */ + + } } + +/* step3() deals with -ic-, -full, -ness etc. similar strategy to step2. */ + +static void step3() { switch (b[k]) + { + case 'e': if (ends("\05" "icate")) { r("\02" "ic"); break; } + if (ends("\05" "ative")) { r("\00" ""); break; } + if (ends("\05" "alize")) { r("\02" "al"); break; } + break; + case 'i': if (ends("\05" "iciti")) { r("\02" "ic"); break; } + break; + case 'l': if (ends("\04" "ical")) { r("\02" "ic"); break; } + if (ends("\03" "ful")) { r("\00" ""); break; } + break; + case 's': if (ends("\04" "ness")) { r("\00" ""); break; } + break; + } } + +/* step4() takes off -ant, -ence etc., in context vcvc. */ + +static void step4() +{ switch (b[k-1]) + { case 'a': if (ends("\02" "al")) break; return; + case 'c': if (ends("\04" "ance")) break; + if (ends("\04" "ence")) break; return; + case 'e': if (ends("\02" "er")) break; return; + case 'i': if (ends("\02" "ic")) break; return; + case 'l': if (ends("\04" "able")) break; + if (ends("\04" "ible")) break; return; + case 'n': if (ends("\03" "ant")) break; + if (ends("\05" "ement")) break; + if (ends("\04" "ment")) break; + if (ends("\03" "ent")) break; return; + case 'o': if (ends("\03" "ion") && j >= k0 && (b[j] == 's' || b[j] == 't')) break; + if (ends("\02" "ou")) break; return; + /* takes care of -ous */ + case 's': if (ends("\03" "ism")) break; return; + case 't': if (ends("\03" "ate")) break; + if (ends("\03" "iti")) break; return; + case 'u': if (ends("\03" "ous")) break; return; + case 'v': if (ends("\03" "ive")) break; return; + case 'z': if (ends("\03" "ize")) break; return; + default: return; + } + if (m() > 1) k = j; +} + +/* step5() removes a final -e if m() > 1, and changes -ll to -l if + m() > 1. */ + +static void step5() +{ j = k; + if (b[k] == 'e') + { int a = m(); + if (a > 1 || a == 1 && !cvc(k-1)) k--; + } + if (b[k] == 'l' && doublec(k) && m() > 1) k--; +} + +/* In stem(p,i,j), p is a char pointer, and the string to be stemmed is from + p[i] to p[j] inclusive. Typically i is zero and j is the offset to the last + character of a string, (p[j+1] == '\0'). The stemmer adjusts the + characters p[i] ... p[j] and returns the new end-point of the string, k. + Stemming never increases word length, so i <= k <= j. To turn the stemmer + into a module, declare 'stem' as extern, and delete the remainder of this + file. +*/ + +int stem(char * p, int i, int j) +{ b = p; k = j; k0 = i; /* copy the parameters into statics */ + if (k <= k0+1) return k; /*-DEPARTURE-*/ + + /* With this line, strings of length 1 or 2 don't go through the + stemming process, although no mention is made of this in the + published algorithm. Remove the line to match the published + algorithm. */ + + step1ab(); + if (k > k0) { + step1c(); step2(); step3(); step4(); step5(); + } + return k; +} diff --git a/vectorHelper.cpp b/vectorHelper.cpp new file mode 100644 index 0000000..696f110 --- /dev/null +++ b/vectorHelper.cpp @@ -0,0 +1,64 @@ +// +// Created by willk on 5/1/2022. +// + +#include "vectorHelper.h" + +vector vectorHelper::combineAnd(vector *a, vector *b) { + vector returnVector; + + for(string tmpA : *a) { + for(string tmpB : *b) { + if(tmpA == tmpB) { + returnVector.push_back(tmpA); + } + } + } + + return returnVector; +} + + + +void vectorHelper::pruneVector(vector *a) { + for(int i = 0; i < a->size(); i++) { + for(int j = i+1; j < a->size(); j++) { + if(a->at(i) == a->at(j)) { + a->erase(a->begin()+j); + j--; + } + } + } +} + +vector vectorHelper::combineOr(vector *a, vector *b) { + vector returnString; + for(string tmpA : *a) { + returnString.push_back(tmpA); + } + for(string tmpB : *b) { + returnString.push_back(tmpB); + } + + pruneVector(&returnString); + return returnString; +} + +vector vectorHelper::combineNot(vector *a, vector *remove) { + vector returnVector = *a; + + for(int i = 0; i < remove->size(); i++) { + for(int j = 0; j < returnVector.size(); j++) { + if(returnVector.at(j) == remove->at(i)) { + returnVector.erase(returnVector.begin()+j); + j--; + } + } + } + + return returnVector; +} + + + + diff --git a/vectorHelper.h b/vectorHelper.h new file mode 100644 index 0000000..58b5078 --- /dev/null +++ b/vectorHelper.h @@ -0,0 +1,19 @@ +// +// Created by willk on 5/1/2022. +// +#include +#include +#ifndef INC_22S_FINAL_PROJ_VECTORHELPER_H +#define INC_22S_FINAL_PROJ_VECTORHELPER_H +using namespace std; +#endif //INC_22S_FINAL_PROJ_VECTORHELPER_H +class vectorHelper { +public: + vector combineAnd(vector*, vector*); + void pruneVector(vector*); + + vector combineOr(vector *, vector *); + + vector combineNot(vector*, vector *); + +}; \ No newline at end of file diff --git a/wordObject.cpp b/wordObject.cpp new file mode 100644 index 0000000..526d72f --- /dev/null +++ b/wordObject.cpp @@ -0,0 +1,5 @@ +// +// Created by willk on 4/18/2022. +// + +#include "wordObject.h" diff --git a/wordObject.h b/wordObject.h new file mode 100644 index 0000000..bc768ef --- /dev/null +++ b/wordObject.h @@ -0,0 +1,35 @@ +// +// Created by willk on 4/18/2022. +// + +#ifndef INC_22S_FINAL_PROJ_WORDOBJECT_H +#define INC_22S_FINAL_PROJ_WORDOBJECT_H + +#include +#include +using namespace std; + +class word{ +public: + int count = 0; + string id; + vector documents; + + word(string input) { + id = input; + } + word() { + + } + + + bool operator <(const word& input) { + return id < input.id; + } + + bool operator ==(const word& input) { + return id == input.id; + } +}; + +#endif //INC_22S_FINAL_PROJ_WORDOBJECT_H