Compare commits
	
		
			1 Commits
		
	
	
		
			foundryvtt
			...
			Arnok_Upda
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 27b922ecd5 | 
							
								
								
									
										16
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -1,18 +1,4 @@ | |||||||
| # 0.21.0.0 | v0.20.0.0 + v0.20.0.1 | ||||||
| # 0.21.1.0 |  | ||||||
|  |  | ||||||
| Alignement sur SWADE v1.1.X et traductions de clés manquantes |  | ||||||
|  |  | ||||||
| # 0.21.0.0 |  | ||||||
|  |  | ||||||
| Alignement sur SWADE v1.1.X |  | ||||||
|  |  | ||||||
| # 0.20.0.3 |  | ||||||
|  |  | ||||||
|   Repository migration |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # 0.20.0.1 |  | ||||||
|  |  | ||||||
|   Migration of the the module,change of the module owner |   Migration of the the module,change of the module owner | ||||||
|   Corrections sur le manifest |   Corrections sur le manifest | ||||||
|   | |||||||
							
								
								
									
										181
									
								
								fr.json
									
									
									
									
									
								
							
							
						
						
									
										181
									
								
								fr.json
									
									
									
									
									
								
							| @@ -18,8 +18,6 @@ | |||||||
|   "ITEM.TypeSkill": "Compétence", |   "ITEM.TypeSkill": "Compétence", | ||||||
|   "ITEM.TypePower": "Pouvoir", |   "ITEM.TypePower": "Pouvoir", | ||||||
|   "ITEM.TypeAbility": "Capacité", |   "ITEM.TypeAbility": "Capacité", | ||||||
|   "CARD.TypeAdventure":" Cartes d'aventure", |  | ||||||
|   "CARD.TypePoker":" Cartes de Poker", |  | ||||||
|   "SWADE.Name": "Nom", |   "SWADE.Name": "Nom", | ||||||
|   "SWADE.Tough": "Résistance", |   "SWADE.Tough": "Résistance", | ||||||
|   "SWADE.Race": "Espèce", |   "SWADE.Race": "Espèce", | ||||||
| @@ -308,48 +306,15 @@ | |||||||
|   "SWADE.Crew": "Équipage requis", |   "SWADE.Crew": "Équipage requis", | ||||||
|   "SWADE.Passengers": "Passagers", |   "SWADE.Passengers": "Passagers", | ||||||
|  |  | ||||||
|   "SWADE.ActAfterCurrentCombatant":"Agir après le combattant actuel", |  | ||||||
|   "SWADE.ActNow": "Agir maintenant", |  | ||||||
|   "SWADE.ActionDeckPresetDark":"Cartes d'action (Sombre)", |  | ||||||
|   "SWADE.ActionDeckPresetLight":" Action Deck (Light)", |  | ||||||
|   "SWADE.ActionDeckReset":" Reset Action Deck", |  | ||||||
|   "SWADE.ActionDeckResetNotification":"Réinitialise les cartes d'action", |  | ||||||
|   "SWADE.ActivateArcaneDevice":"Activer l'objet", |  | ||||||
|   "SWADE.AddTokenFollowers":"Ajouter les tokens sélectionnés comme suivants", |  | ||||||
|   "SWADE.AnimalSmartsMarker":"Un", |  | ||||||
|   "SWADE.ArcaneDevice":"Objet Arcanique", |  | ||||||
|   "SWADE.ArcaneSkill":"Compétence d'arcane", |  | ||||||
|   "SWADE.Archetype":"Archétype", |  | ||||||
|   "SWADE.ArchetypeAbilities":"Capacités d'archetype", |  | ||||||
|   "SWADE.ButtonReset":"Ré-initialisation", |  | ||||||
|   "SWADE.ButtonSubmit":"Soumettre", |  | ||||||
|   "SWADE.ConvictionActivate":"Faire appel à leur convictin!", |  | ||||||
|   "SWADE.CoreSkill":"Compétence de base", |  | ||||||
|   "SWADE.CoreSkills":"Compétences de base", |  | ||||||
|   "SWADE.CoreSkillsDesc":" >-", |  | ||||||
|   "SWADE.DrawInit":"Lancer l'initiative", |  | ||||||
|   "SWADE.Follow":"Suivre {name}", |  | ||||||
|   "SWADE.GroupByName":"Grouper par nom", |  | ||||||
|   "SWADE.Hold":"Conserver", |  | ||||||
|   "SWADE.LoseTurn":"Toggle Lose Turn", |  | ||||||
|   "SWADE.MakeGroupLeader":"Faire un Chef de groupe", |  | ||||||
|   "SWADE.PPCost":"Coût en PP", |  | ||||||
|   "SWADE.RemoveGroupLeader":"Supprimer le chef de groupe", |  | ||||||
|   "SWADE.SelectColor":"Selectionner une couleur", |  | ||||||
|   "SWADE.SetGroupColor":"Choisir une couleur de groupe", |  | ||||||
|   "SWADE.Unfollow":"Arrêter de suivre {name}", |  | ||||||
|   "SWADE.WeaponsAndArmor":"Armes & Armuress", |  | ||||||
|   "SWADE.WildCard":"Joker", |  | ||||||
|    |  | ||||||
|   "SWADE.String": "Texte", |   "SWADE.String": "Texte", | ||||||
|   "SWADE.Number": "Nombre", |   "SWADE.Number": "Nombre", | ||||||
|   "SWADE.Checkbox": "Checkbox", |   "SWADE.Checkbox": "Checkbox", | ||||||
|   "SWADE.Ace": "As", |   "SWADE.Ace": "As", | ||||||
|   "SWADE.NoPowerPoints": "Pas de Points de Pouvoir", |   "SWADE.NoPowerPoints": "Pas de Points de Pouvoir", | ||||||
|   "SWADE.NoPowerPointsDesc": "Lorsque activé, cette option cache toutes les interactions avec les Points de Pouvoir", |   "SWADE.NoPowerPointsDesc": "Lorsque activé, cette option cache toutes les interactions avec les Points de Pouvoir", | ||||||
|   "SWADE.WealthType": "Type de Richesse", |   "SWADE.WealthType": "Type de Santé", | ||||||
|   "SWADE.WealthDie": "Dé de Richesse", |   "SWADE.WealthDie": "Type de Mort", | ||||||
|   "SWADE.WealthTypeDesc": "Choississez comment suivre la richesse des personnages et leur argent", |   "SWADE.WealthTypeDesc": "Choississez comment suivre la santé des personnages et leur argent", | ||||||
|   "SWADE.CurrencyName": "Nom de monnaie", |   "SWADE.CurrencyName": "Nom de monnaie", | ||||||
|   "SWADE.CurrencyNameDesc": "Nommez la monnaie utilisée", |   "SWADE.CurrencyNameDesc": "Nommez la monnaie utilisée", | ||||||
|   "SWADE.TraitRolls": "Jets de Trait", |   "SWADE.TraitRolls": "Jets de Trait", | ||||||
| @@ -357,7 +322,7 @@ | |||||||
|   "SWADE.AltTrait": "Trait Alternatif", |   "SWADE.AltTrait": "Trait Alternatif", | ||||||
|   "SWADE.ClickSuggestions": "Cliquez pour les suggestions", |   "SWADE.ClickSuggestions": "Cliquez pour les suggestions", | ||||||
|   "SWADE.Quick": "Rapide", |   "SWADE.Quick": "Rapide", | ||||||
|   "SWADE.BonusDamage": "Bonus aux dommanes", |   "SWADE.BonusDamage": "Bonus aux dégâts", | ||||||
|   "SWADE.CoreSkillsPack": "Compendium des Compatences de base", |   "SWADE.CoreSkillsPack": "Compendium des Compatences de base", | ||||||
|   "SWADE.CoreSkillsPackDesc": "Choisissez le compendium d'ou proviennent les compétences de base", |   "SWADE.CoreSkillsPackDesc": "Choisissez le compendium d'ou proviennent les compétences de base", | ||||||
|   "SWADE.Joker": "Joker", |   "SWADE.Joker": "Joker", | ||||||
| @@ -366,11 +331,11 @@ | |||||||
|   "SWADE.SubtractPPDesc": "Soustraire le cout en PP du total disponible", |   "SWADE.SubtractPPDesc": "Soustraire le cout en PP du total disponible", | ||||||
|   "SWADE.AddPPDesc": "Ajouter le cout en PP au total disponible", |   "SWADE.AddPPDesc": "Ajouter le cout en PP au total disponible", | ||||||
|   "SWADE.RightClickZoom": "Click droit pour zoomer", |   "SWADE.RightClickZoom": "Click droit pour zoomer", | ||||||
|   "SWADE.SysMigrationWarning": "Votre installation de SWADE est ancienne et ne peut pas être migrée à la nouvelle version. La migration va être tentée, mais des erreurs vont se produire", |   "SWADE.SysMigrationWarning": "Votre installation de SWADE est ancienne et ne peut pas être migrée à la nouvelle version. La migration va être tentée, mais des erreurs peuvent se produire", | ||||||
|   "SWADE.SomethingWrongWithCardComp": "Une erreur s'est produite avec le Compendium de Cartes, basculement le réglage par défaut", |   "SWADE.SomethingWrongWithCardComp": "Une erreur s'est produite avec le Compendium de Cartes, positionnement sur le réglage par défaut", | ||||||
|   "SWADE.DeckShuffled": "Le paquet de cartes a été automatiquement mélangé", |   "SWADE.DeckShuffled": "Le paquet de cartes a été automatiquement mélangé", | ||||||
|   "SWADE.BasePace": "Allure de base", |   "SWADE.BasePace": "Allure de base", | ||||||
|   "SWADE.WarningPackLocked": "Vous ne pouvez éditer un Compendium verouillé. Dévérouillez le d'abord.", |   "SWADE.WarningPackLocked": "Vous ne pouvez pas éditer un Compendium verouillé. Dévérouillez le d'abord.", | ||||||
|   "SWADE.ActionCardEditor": "Editeur de cartes d'action", |   "SWADE.ActionCardEditor": "Editeur de cartes d'action", | ||||||
|   "SWADE.CardFace": "Figure", |   "SWADE.CardFace": "Figure", | ||||||
|   "SWADE.CardValue": "Valeur", |   "SWADE.CardValue": "Valeur", | ||||||
| @@ -383,13 +348,13 @@ | |||||||
|   "SWADE.CharacterSummary": "Résumé de personnage", |   "SWADE.CharacterSummary": "Résumé de personnage", | ||||||
|   "SWADE.CopyHtml": "Copier le HTML", |   "SWADE.CopyHtml": "Copier le HTML", | ||||||
|   "SWADE.CopyMarkdown": "Copier le Markdown", |   "SWADE.CopyMarkdown": "Copier le Markdown", | ||||||
|   "SWADE.InitCardDeck": "Jeu de carte pour l'Initiative", |   "SWADE.InitCardDeck": "Jeu de carte pour l'initiative", | ||||||
|   "SWADE.Imperial": "Imperiale", |   "SWADE.Imperial": "Imperiale", | ||||||
|   "SWADE.Metric": "Métrique", |   "SWADE.Metric": "Métrique", | ||||||
|   "SWADE.WeightUnitLabel": "Unite de poids", |   "SWADE.WeightUnitLabel": "Unite de poids", | ||||||
|   "SWADE.WeightUnitDesc": "Indique si les poids sont mesurés en livres ou en kilogrammes. Changer ce paramètre ne changera PAS le poids des items, uniquement le calcul de l'encombrement", |   "SWADE.WeightUnitDesc": "Indique si les poids sont mesurés en livres ou en kilogrammes. Changer ce paramètre ne changera PAS le poids des items, uniquement le calcul de l'encombrement", | ||||||
|   "SWADE.UseAttributeShorts": "Utiliser des noms d'attributs cours", |   "SWADE.UseAttributeShorts": "Utiliser des noms d'attributs courts", | ||||||
|   "SWADE.UseAttributeShortsDesc": "Activez cette option si vous voulez des noms d'attributs court sur les fiches de PJs et PNJs (ie Agi au lieu de Agilité, etc.)", |   "SWADE.UseAttributeShortsDesc": "Activez cette option si vous voulez des noms d'attributs courts sur les fiches de PJs et PNJs (ie Agi au lieu de Agilité ...)", | ||||||
|   "SWADE.BennyImageSheet": "Jeton", |   "SWADE.BennyImageSheet": "Jeton", | ||||||
|   "SWADE.BennyImageSheetDesc": "Sélectionnez l'image voulue pour les jetons sur la fiche de Personnage", |   "SWADE.BennyImageSheetDesc": "Sélectionnez l'image voulue pour les jetons sur la fiche de Personnage", | ||||||
|   "SWADE.Benny3DFront": "Texture de face", |   "SWADE.Benny3DFront": "Texture de face", | ||||||
| @@ -401,20 +366,20 @@ | |||||||
|   "SWADE.HardChoices": "Choix Cornéliens", |   "SWADE.HardChoices": "Choix Cornéliens", | ||||||
|   "SWADE.HardChoicesDesc": "Cocher cette option activera les règles de Choix Cornéliens", |   "SWADE.HardChoicesDesc": "Cocher cette option activera les règles de Choix Cornéliens", | ||||||
|   "SWADE.WealthSelectionNoneOther": "Aucun/Autre", |   "SWADE.WealthSelectionNoneOther": "Aucun/Autre", | ||||||
|   "SWADE.Benny3DFrontBump": "Front Bump Map", |   "SWADE.Benny3DFrontBump": "Relief texture de face", | ||||||
|   "SWADE.Benny3DBackBump": "Back Bump Map", |   "SWADE.Benny3DBackBump": "Relief texture arrière", | ||||||
|   "SWADE.Benny3DFrontBumpDesc": "Front bump map of the benny", |   "SWADE.Benny3DFrontBumpDesc": "Rendu de texture de jetons de face", | ||||||
|   "SWADE.Benny3DBackBumpDesc": "Back bump map of the benny", |   "SWADE.Benny3DBackBumpDesc": "Rendu de texture de jetons arrière", | ||||||
|   "SWADE.ActionTraitMod": "Modificateur de Trait d'Action", |   "SWADE.ActionTraitMod": "Modificateur de Trait d'Action", | ||||||
|   "SWADE.ActionDmgMod": "Modificateur de dégats", |   "SWADE.ActionDmgMod": "Modificateur de dégâts", | ||||||
|   "SWADE.ItemTraitMod": "Modificatteur de trait d'item", |   "SWADE.ItemTraitMod": "Modificatteur de trait d'item", | ||||||
|   "SWADE.ItemDmgMod": "Modification d'Item de dégats", |   "SWADE.ItemDmgMod": "Modification d'Item de dégâts", | ||||||
|   "SWADE.Duplicates": "Dupliqués trouvés", |   "SWADE.Duplicates": "Doublons trouvés", | ||||||
|   "SWADE.DuplicateItemsBodyText": "En ajoutant le {type} <strong>{name}</strong> à l'acteur {target}, les éléments dupliqués (nom/type) ont été trouvés. Les nouveaux items ont été renommés", |   "SWADE.DuplicateItemsBodyText": "En ajoutant le {type} <strong>{name}</strong> à l'acteur {target}, les éléments dupliqués (nom/type) ont été trouvés. Les nouveaux items ont été renommés", | ||||||
|   "SWADE.NoActionDeckFound": "Aucun jeu de cartes d'action trouvés, création en cours", |   "SWADE.NoActionDeckFound": "Aucun jeu de cartes d'action trouvé, création en cours", | ||||||
|   "SWADE.NoActionDeckDiscardPileFound": "Aucune défausse de carte d'action trouvé, création en cours", |   "SWADE.NoActionDeckDiscardPileFound": "Aucune défausse de carte d'action trouvée, création en cours", | ||||||
|   "SWADE.InitDiscardPile": "Défausse de l'Initiative", |   "SWADE.InitDiscardPile": "Défausse de l'Initiative", | ||||||
|   "SWADE.Wealth": "Santé", |   "SWADE.Wealth": "Richesse", | ||||||
|   "SWADE.Characters": "Personnages", |   "SWADE.Characters": "Personnages", | ||||||
|   "SWADE.SettingRules": "Règles d'Univers", |   "SWADE.SettingRules": "Règles d'Univers", | ||||||
|   "SWADE.WorldBasics": "Bases du Monde", |   "SWADE.WorldBasics": "Bases du Monde", | ||||||
| @@ -428,17 +393,17 @@ | |||||||
|   "SWADE.Illumination.Dim": "Pénombre", |   "SWADE.Illumination.Dim": "Pénombre", | ||||||
|   "SWADE.Illumination.Dark": "Obscurité", |   "SWADE.Illumination.Dark": "Obscurité", | ||||||
|   "SWADE.Illumination.Pitch": "Noir", |   "SWADE.Illumination.Pitch": "Noir", | ||||||
|   "SWADE.Cover.Light": "Couvert Léger", |   "SWADE.Cover.Light": "Couvert léger", | ||||||
|   "SWADE.Cover.Medium": "Couvert Moyen", |   "SWADE.Cover.Medium": "Couvert moyen", | ||||||
|   "SWADE.Cover.Heavy": "Couvert Important", |   "SWADE.Cover.Heavy": "Couvert important", | ||||||
|   "SWADE.Cover.Total": "Couvert Total", |   "SWADE.Cover.Total": "Couvert total", | ||||||
|   "SWADE.Range.Medium": "Portée Moyenne", |   "SWADE.Range.Medium": "Portée moyenne", | ||||||
|   "SWADE.Range.Long": "Portée Longue", |   "SWADE.Range.Long": "Portée longue", | ||||||
|   "SWADE.Range.Extreme": "Portée Extrême", |   "SWADE.Range.Extreme": "Portée extrême", | ||||||
|   "SWADE.ModOther": "Autres Modificateurs", |   "SWADE.ModOther": "Autres modificateurs", | ||||||
|   "SWADE.Snapfire": "Snapfire", |   "SWADE.Snapfire": "Tir Statique", | ||||||
|   "SWADE.UnstablePlatform": "Plateforme Instable", |   "SWADE.UnstablePlatform": "Plateforme instable", | ||||||
|   "SWADE.CannotAddRaceToRace": "Vous ne pouvez ajouter une race/archetype à une race/archetype !", |   "SWADE.CannotAddRaceToRace": "Vous ne pouvez ajouter une race/archétype à une race/archétype !", | ||||||
|   "SWADE.ApplyEncumbrance": "Appliquer les pénalités d'Encombrement", |   "SWADE.ApplyEncumbrance": "Appliquer les pénalités d'Encombrement", | ||||||
|   "SWADE.ApplyEncumbranceHint": "Appliquer les pénalités d'Encombrement. Gardez à l'esprit que cela n'effectue pas les tests de Vigueur pour résister à la Fatigue", |   "SWADE.ApplyEncumbranceHint": "Appliquer les pénalités d'Encombrement. Gardez à l'esprit que cela n'effectue pas les tests de Vigueur pour résister à la Fatigue", | ||||||
|   "SWADE.LayOutChaseWithDeck": "Utiliser les cartes pour gérer la poursuite", |   "SWADE.LayOutChaseWithDeck": "Utiliser les cartes pour gérer la poursuite", | ||||||
| @@ -456,92 +421,50 @@ | |||||||
|   "SWADE.Expiration.EndAuto": "Fin du tour, automatique", |   "SWADE.Expiration.EndAuto": "Fin du tour, automatique", | ||||||
|   "SWADE.Expiration.EndPrompt": "Fin du tour, demande", |   "SWADE.Expiration.EndPrompt": "Fin du tour, demande", | ||||||
|   "SWADE.Expiration.None": "Aucun", |   "SWADE.Expiration.None": "Aucun", | ||||||
|   "SWADE.Expiration.LooseTurnOnHold": "Lose Turn on Hold", |   "SWADE.Expiration.LooseTurnOnHold": "perte du tour en attente", | ||||||
|   "SWADE.RemoveEffectTitle": "Supprimer {label} ?", |   "SWADE.RemoveEffectTitle": "Supprimer {label} ?", | ||||||
|   "SWADE.RemoveEffectBody": "<p style='text-align: center;'>Supprimer <strong>{label}</strong> de <strong>{parent}</strong>?</p>", |   "SWADE.RemoveEffectBody": "<p style='text-align: center;'>Supprimer <strong>{label}</strong> de <strong>{parent}</strong>?</p>", | ||||||
|   "SWADE.PPAbbreviation": "PP", |   "SWADE.PPAbbreviation": "PP", | ||||||
|  |  | ||||||
|   "SWADE.ShowInChat": "Afficher dans le tchat", |  | ||||||
|   "SWADE.ExpandDescription": "Agrandir pur montrer la description", |  | ||||||
|   "SWADE.Favorite": "Favorite", |  | ||||||
|   "SWADE.Equip": "Equiper", |  | ||||||
|   "SWADE.RollDamage": "Lancer les dégats", |  | ||||||
|   "SWADE.SystemLinks.Changelog": "Changelog", |  | ||||||
|   "SWADE.SystemLinks.Wiki": "Wiki", |  | ||||||
|   "SWADE.SystemLinks.ReportAnIssue": "Rapporter un problème", |  | ||||||
|   "SWADE.Keybindings.OpenFavoriteCards.Name": "Ouvrir la main préférée", |  | ||||||
|   "SWADE.Keybindings.OpenFavoriteCards.UserConfigLabel": "Main préférée", |  | ||||||
|   "SWADE.Keybindings.OpenFavoriteCards.Hint": "Vous pouvez paramétrer votre main préférée dans la configuration utilisateur", |  | ||||||
|   "SWADE.Keybindings.OpenFavoriteCards.NoCardsWarning": "Vous n'avez pas de main préférée", |  | ||||||
|   "SWADE.Keybindings.Bennies.Name": "Dépenser/Recevoir un Jeton", |  | ||||||
|   "SWADE.Keybindings.Bennies.Hint": "Appuyer pour dépenser un Jeton, gardez ALT appuyez tout en cliquant pour recevoir un Jeton", |  | ||||||
|   "SWADE.OpenOrigin": "Ouvrir l'origine", |  | ||||||
|   "SWADE.EffectsTemporary": "Effets temporaires", |  | ||||||
|   "SWADE.EffectsPermanent": "Effets permanents", |  | ||||||
|   "SWADE.Ranks.Novice": "Novice", |  | ||||||
|   "SWADE.Ranks.Seasoned": "Seasoned", |  | ||||||
|   "SWADE.Ranks.Veteran": "Veteran", |  | ||||||
|   "SWADE.Ranks.Heroic": "Héroïque", |  | ||||||
|   "SWADE.Ranks.Legendary": "Légendaire", |  | ||||||
|   "SWADE.Advances.EditorTitle": "Editeur avancé", |  | ||||||
|   "SWADE.Advances.Toggle": "Activer/Desactiver le plan de progression", |  | ||||||
|   "SWADE.Advances.Delete": "Supprimer la progression", |  | ||||||
|   "SWADE.Advances.Planned": "Planifié", |  | ||||||
|   "SWADE.Advances.Modes.Legacy": "Normal", |  | ||||||
|   "SWADE.Advances.Modes.Expanded": "Etendu", |  | ||||||
|   "SWADE.Advances.Types.Edge": "Nouvel atout", |  | ||||||
|   "SWADE.Advances.Types.SingleSkill": "Augmentation d'une Compétence", |  | ||||||
|   "SWADE.Advances.Types.TwoSkills": "Augmentation de 2 Compétences", |  | ||||||
|   "SWADE.Advances.Types.Attribute": "Augmentation d'un Attribut", |  | ||||||
|   "SWADE.Advances.Types.Hindrance": "Réduire un Handicap", |  | ||||||
|   "SWADE.AddAdvance": "Ajouter une progression", |  | ||||||
|   "SWADE.Appearance": "Apparence", |  | ||||||
|   "SWADE.CharacterGoals": "Objectifs", |  | ||||||
|   "SWADE.Background": "Background", |  | ||||||
|   "SWADE.ActiveEffects.Add": "Ajouter un Active Effect", |  | ||||||
|   "SWADE.ActiveEffects.Source": "Source", |  | ||||||
|   "SWADE.Advances.Number": "Numéro d'avancement", |  | ||||||
|  |  | ||||||
|   "Actor": "Acteur", |   "Actor": "Acteur", | ||||||
|   "Vehicles": "Véhicules", |   "Vehicles": "Véhicules", | ||||||
|   "Ground Vehicles": "Véhicules Terrestres", |   "Ground Vehicles": "Véhicules terrestres", | ||||||
|   "Civilian Vehicles": "Véhicules Civiles", |   "Civilian Vehicles": "Véhicules civils", | ||||||
|   "Futuristic Military Vehicles": "Véhicules Militaires Futuristes", |   "Futuristic Military Vehicles": "Véhicules militaires futuristes", | ||||||
|   "World War II Military Vehicles": "Véhicules Militaires de la Seconde Guerre Mondiale", |   "World War II Military Vehicles": "Véhicules militaires de la Seconde Guerre mondiale", | ||||||
|   "Aircraft": "Aviation", |   "Aircraft": "Aviation", | ||||||
|   "Civilian": "Civile", |   "Civilian": "Civil", | ||||||
|   "Bestiary": "Bestiaire",  |   "Bestiary": "Bestiaire",  | ||||||
|   "Modern Military Aircraft": "Avions Militaires Modernes", |   "Modern Military Aircraft": "Avions militaires modernes", | ||||||
|   "World War II Military Aircraft": "Avions Seconde Guerre Mondiale", |   "World War II Military Aircraft": "Avions Seconde Guerre mondiale", | ||||||
|   "Watercraft": "Maritime", |   "Watercraft": "Maritime", | ||||||
|   "Equipment": "Equipement", |   "Equipment": "Equipement", | ||||||
|   "Armor": "Armures", |   "Armor": "Armures", | ||||||
|   "Ammo": "Munitions", |   "Ammo": "Munitions", | ||||||
|   "Common Gear": "Matériel de base", |   "Common Gear": "Matériel de base", | ||||||
|   "Modern Firearms": "Armes à feu Modernes", |   "Modern Firearms": "Armes à feu modernes", | ||||||
|   "Personal Weapons": "Armes de contact", |   "Personal Weapons": "Armes de contact", | ||||||
|   "Special Weapons": "Armes spéciales", |   "Special Weapons": "Armes spéciales", | ||||||
|   "Natural/Improvised Weapons": "Armes Naturelles/Improvisées", |   "Natural/Improvised Weapons": "Armes naturelles/improvisées", | ||||||
|   "Skills": "Compétences", |   "Skills": "Compétences", | ||||||
|   "Edges": "Atouts", |   "Edges": "Atouts", | ||||||
|   "Background Edges": "Atouts de Background", |   "Background Edges": "Atouts de background", | ||||||
|   "Combat Edges": "Atouts de Combat", |   "Combat Edges": "Atouts de combat", | ||||||
|   "Leadership Edges": "Atouts de Commandement", |   "Leadership Edges": "Atouts de commandement", | ||||||
|   "Legendary Edges": "Atouts Légendaires", |   "Legendary Edges": "Atouts légendaires", | ||||||
|   "Power Edges": "Atouts de Pouvoirs", |   "Power Edges": "Atouts de pouvoirs", | ||||||
|   "Professional Edges": "Atouts Professionnels", |   "Professional Edges": "Atouts professionnels", | ||||||
|   "Social Edges": "Atouts Sociaux", |   "Social Edges": "Atouts cociaux", | ||||||
|   "Weird Edges": "Atouts Etranges", |   "Weird Edges": "Atouts étranges", | ||||||
|   "Hindrances": "Handicaps", |   "Hindrances": "Handicaps", | ||||||
|   "Powers": "Pouvoirs", |   "Powers": "Pouvoirs", | ||||||
|   "Special Abilities": "Capacités Spéciales", |   "Special Abilities": "Capacités spéciales", | ||||||
|   "1. Characters": "1. Personnages", |   "1. Characters": "1. Personnages", | ||||||
|   "2. Gear": "2. Matériel", |   "2. Gear": "2. Matériel", | ||||||
|   "3. Rules": "3. Règles", |   "3. Rules": "3. Règles", | ||||||
|   "5. Powers": "5. Pouvoirs", |   "5. Powers": "5. Pouvoirs", | ||||||
|   "6. Bestiary": "6. Bestiaire", |   "6. Bestiary": "6. Bestiaire", | ||||||
|   "7. Game Mastering": "6. Conseils aux Maîtres de Jeu", |   "7. Game Mastering": "6. Conseils aux Maîtres de Jeu", | ||||||
|   "Character Creation": "Création de Personnages", |   "Character Creation": "Création de personnages", | ||||||
|   "The Adventure toolkit": "Boite à Outils des Aventures", |   "The Adventure toolkit": "Boite à outils des aventures" | ||||||
|   "name":" Portée" |  | ||||||
| }   | }   | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|   "name": "swade-fr", |   "name": "swade-fr", | ||||||
|   "title": "SWADE - Traduction française", |   "title": "SWADE - Traduction française", | ||||||
|   "description": "Ajoute le français (FRANCE) au système SWADE.<p> Une traduction Babele des compendiums est inclue mais optionnelle. (Encore en test, à utiliser à vos risques et périls !) </p> <p>*** Join the official Discord server: <a href='https://discord.gg/foundryvtt'> Official Discord</a></p><p>*** Rejoignez la communauté Francophone: <a href='https://discord.gg/pPSDNJk'>Discord francophone</a></p>", |   "description": "Ajoute le français (FRANCE) au système SWADE.<p> Une traduction Babele des compendiums est inclue mais optionnelle. (Encore en test, à utiliser à vos risques et périls !) </p> <p>*** Join the official Discord server: <a href='https://discord.gg/foundryvtt'> Official Discord</a></p><p>*** Rejoignez la communauté Francophone: <a href='https://discord.gg/pPSDNJk'>Discord francophone</a></p>", | ||||||
|   "version": "0.21.1.0", |   "version": "0.20.0.2", | ||||||
|   "minimumCoreVersion" : "0.7.9", |   "minimumCoreVersion" : "0.7.9", | ||||||
|   "compatibleCoreVersion" : "9", |   "compatibleCoreVersion" : "9", | ||||||
|   "author": "BoboursToutCool, Gronyon, Kyane, LeRatierBretonnien, Sasmira, U~man,X.O. de Vorcen", |   "author": "BoboursToutCool, Gronyon, Kyane, LeRatierBretonnien, Sasmira, U~man,X.O. de Vorcen", | ||||||
| @@ -63,7 +63,7 @@ | |||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|    |    | ||||||
|   "url": "https://www.uberwald.me/gitea/public//foundryvtt-swade-fr", |   "url": "https://gitlab.com/LeRatierBretonnien/foundryvtt-swade-fr", | ||||||
|   "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-swade-fr/raw/branch/master/module.json", |   "manifest": "https://gitlab.com/LeRatierBretonnien/foundryvtt-swade-fr/-/raw/master/module.json", | ||||||
|   "download": "https://www.uberwald.me/gitea/public/foundryvtt-swade-fr/archive/foundryvtt-swade-fr-0.21.1.0.zip" |   "download": "https://gitlab.com/LeRatierBretonnien/foundryvtt-swade-fr/-/archive/master/foundryvtt-swade-fr-master.zip" | ||||||
| } | } | ||||||
| @@ -1,39 +0,0 @@ | |||||||
| package.path = package.path .. ";luajson/?.lua" |  | ||||||
| local JSON = require"json" |  | ||||||
|  |  | ||||||
| local enjsonf = "../../swade/src/lang/en.yml" |  | ||||||
| local frjsonf = "../fr.json" |  | ||||||
|  |  | ||||||
| local fp = io.open(enjsonf, "r") |  | ||||||
| local line = fp:read() |  | ||||||
| local entags = {} |  | ||||||
| while line do |  | ||||||
|   --print("LINE", line)  |  | ||||||
|   local key, value = line:match("([%w%.]*):([>%-%+%p%s%w%d%.]*)" ) |  | ||||||
|   if key then  |  | ||||||
|     entags[key] = value |  | ||||||
|   end |  | ||||||
|   line = fp:read() |  | ||||||
| end |  | ||||||
| fp:close() |  | ||||||
|  |  | ||||||
| fp = io.open(frjsonf, "r") |  | ||||||
| local frtags = JSON.decode( fp:read("*a") ) |  | ||||||
| fp:close() |  | ||||||
|  |  | ||||||
| local todisplay  = {} |  | ||||||
| for tag, value in pairs(entags) do |  | ||||||
|   if not frtags[tag] then  |  | ||||||
|     todisplay[#todisplay+1] = { tag=tag, value=value } |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| table.sort(todisplay, function (a, b)  |  | ||||||
|     return a.tag < b.tag  |  | ||||||
|   end |  | ||||||
| ) |  | ||||||
| for _, tagDef in pairs(todisplay) do |  | ||||||
|   print('"'.. tagDef.tag ..'":"'.. tagDef.value..'",') |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1,625 +0,0 @@ | |||||||
| --[[ |  | ||||||
| LPEGLJ |  | ||||||
| lpcap.lua |  | ||||||
| Capture functions |  | ||||||
| Copyright (C) 2014 Rostislav Sacek. |  | ||||||
| based on LPeg v1.0 - PEG pattern matching for Lua |  | ||||||
| Lua.org & PUC-Rio  written by Roberto Ierusalimschy |  | ||||||
| http://www.inf.puc-rio.br/~roberto/lpeg/ |  | ||||||
|  |  | ||||||
| ** Permission is hereby granted, free of charge, to any person obtaining |  | ||||||
| ** a copy of this software and associated documentation files (the |  | ||||||
| ** "Software"), to deal in the Software without restriction, including |  | ||||||
| ** without limitation the rights to use, copy, modify, merge, publish, |  | ||||||
| ** distribute, sublicense, and/or sell copies of the Software, and to |  | ||||||
| ** permit persons to whom the Software is furnished to do so, subject to |  | ||||||
| ** the following conditions: |  | ||||||
| ** |  | ||||||
| ** The above copyright notice and this permission notice shall be |  | ||||||
| ** included in all copies or substantial portions of the Software. |  | ||||||
| ** |  | ||||||
| ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |  | ||||||
| ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |  | ||||||
| ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |  | ||||||
| ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |  | ||||||
| ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |  | ||||||
| ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |  | ||||||
| ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |  | ||||||
| ** |  | ||||||
| ** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] |  | ||||||
| --]] |  | ||||||
| local ffi = require "ffi" |  | ||||||
|  |  | ||||||
| local Cclose = 0 |  | ||||||
| local Cposition = 1 |  | ||||||
| local Cconst = 2 |  | ||||||
| local Cbackref = 3 |  | ||||||
| local Carg = 4 |  | ||||||
| local Csimple = 5 |  | ||||||
| local Ctable = 6 |  | ||||||
| local Cfunction = 7 |  | ||||||
| local Cquery = 8 |  | ||||||
| local Cstring = 9 |  | ||||||
| local Cnum = 10 |  | ||||||
| local Csubst = 11 |  | ||||||
| local Cfold = 12 |  | ||||||
| local Cruntime = 13 |  | ||||||
| local Cgroup = 14 |  | ||||||
|  |  | ||||||
| local MAXSTRCAPS = 10 |  | ||||||
|  |  | ||||||
| local pushcapture |  | ||||||
| local addonestring |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Goes back in a list of captures looking for an open capture |  | ||||||
| -- corresponding to a close |  | ||||||
|  |  | ||||||
| local function findopen(cs, index) |  | ||||||
|     local n = 0; -- number of closes waiting an open |  | ||||||
|     while true do |  | ||||||
|         index = index - 1 |  | ||||||
|         if cs.ocap[index].kind == Cclose then |  | ||||||
|             n = n + 1 -- one more open to skip |  | ||||||
|         elseif cs.ocap[index].siz == 0 then |  | ||||||
|             if n == 0 then |  | ||||||
|                 return index |  | ||||||
|             end |  | ||||||
|             n = n - 1 |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function checknextcap(cs, captop) |  | ||||||
|     local cap = cs.cap; |  | ||||||
|     -- not a single capture?    ((cap)->siz != 0) |  | ||||||
|     if cs.ocap[cap].siz == 0 then |  | ||||||
|         local n = 0; -- number of opens waiting a close |  | ||||||
|         -- look for corresponding close |  | ||||||
|         while true do |  | ||||||
|             cap = cap + 1 |  | ||||||
|             if cap > captop then return end |  | ||||||
|             if cs.ocap[cap].kind == Cclose then |  | ||||||
|                 n = n - 1 |  | ||||||
|                 if n + 1 == 0 then |  | ||||||
|                     break; |  | ||||||
|                 end |  | ||||||
|             elseif cs.ocap[cap].siz == 0 then |  | ||||||
|                 n = n + 1 |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     cap = cap + 1; -- + 1 to skip last close (or entire single capture) |  | ||||||
|     if cap > captop then return end |  | ||||||
|     return true |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Go to the next capture |  | ||||||
|  |  | ||||||
| local function nextcap(cs) |  | ||||||
|     local cap = cs.cap; |  | ||||||
|     -- not a single capture?    ((cap)->siz != 0) |  | ||||||
|     if cs.ocap[cap].siz == 0 then |  | ||||||
|         local n = 0; -- number of opens waiting a close |  | ||||||
|         -- look for corresponding close |  | ||||||
|         while true do |  | ||||||
|             cap = cap + 1 |  | ||||||
|             if cs.ocap[cap].kind == Cclose then |  | ||||||
|                 n = n - 1 |  | ||||||
|                 if n + 1 == 0 then |  | ||||||
|                     break; |  | ||||||
|                 end |  | ||||||
|             elseif cs.ocap[cap].siz == 0 then |  | ||||||
|                 n = n + 1 |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     cs.cap = cap + 1; -- + 1 to skip last close (or entire single capture) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Push on the Lua stack all values generated by nested captures inside |  | ||||||
| -- the current capture. Returns number of values pushed. 'addextra' |  | ||||||
| -- makes it push the entire match after all captured values. The |  | ||||||
| -- entire match is pushed also if there are no other nested values, |  | ||||||
| -- so the function never returns zero. |  | ||||||
|  |  | ||||||
| local function pushnestedvalues(cs, addextra, out, valuetable) |  | ||||||
|     local co = cs.cap |  | ||||||
|     cs.cap = cs.cap + 1 |  | ||||||
|     -- no nested captures? |  | ||||||
|     if cs.ocap[cs.cap - 1].siz ~= 0 then |  | ||||||
|         local st = cs.ocap[co].s |  | ||||||
|         local l = cs.ocap[co].siz - 1 |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = cs.s and cs.s:sub(st, st + l - 1) or cs.stream(st, st + l - 1) |  | ||||||
|         return 1; -- that is it |  | ||||||
|     else |  | ||||||
|         local n = 0; |  | ||||||
|         while cs.ocap[cs.cap].kind ~= Cclose do -- repeat for all nested patterns |  | ||||||
|         n = n + pushcapture(cs, out, valuetable); |  | ||||||
|         end |  | ||||||
|         -- need extra? |  | ||||||
|         if addextra or n == 0 then |  | ||||||
|             local st = cs.ocap[co].s |  | ||||||
|             local l = cs.ocap[cs.cap].s - cs.ocap[co].s |  | ||||||
|             out.outindex = out.outindex + 1 |  | ||||||
|             out.out[out.outindex] = cs.s and cs.s:sub(st, st + l - 1) or cs.stream(st, st + l - 1) |  | ||||||
|             n = n + 1 |  | ||||||
|         end |  | ||||||
|         cs.cap = cs.cap + 1 -- skip close entry |  | ||||||
|         return n; |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Push only the first value generated by nested captures |  | ||||||
|  |  | ||||||
| local function pushonenestedvalue(cs, out, valuetable) |  | ||||||
|     local n = pushnestedvalues(cs, false, out, valuetable) |  | ||||||
|     for i = n, 2, -1 do |  | ||||||
|         out.out[out.outindex] = nil |  | ||||||
|         out.outindex = out.outindex - 1 |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Try to find a named group capture with the name given at the top of |  | ||||||
| -- the stack; goes backward from 'cap'. |  | ||||||
|  |  | ||||||
| local function findback(cs, cap, name, valuetable) |  | ||||||
|     -- repeat until end of list |  | ||||||
|     while cap > 0 do |  | ||||||
|         cap = cap - 1 |  | ||||||
|         local continue |  | ||||||
|         if cs.ocap[cap].kind == Cclose then |  | ||||||
|             cap = findopen(cs, cap); -- skip nested captures |  | ||||||
|         elseif cs.ocap[cap].siz == 0 then |  | ||||||
|             continue = true -- opening an enclosing capture: skip and get previous |  | ||||||
|         end |  | ||||||
|         if not continue and cs.ocap[cap].kind == Cgroup and cs.ocap[cap].idx ~= 0 then |  | ||||||
|             local gname = valuetable[cs.ocap[cap].idx] -- get group name |  | ||||||
|             -- right group? |  | ||||||
|             if name == gname then |  | ||||||
|                 return cap; |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     error(("back reference '%s' not found"):format(name), 0) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Back-reference capture. Return number of values pushed. |  | ||||||
|  |  | ||||||
| local function backrefcap(cs, out, valuetable) |  | ||||||
|     local curr = cs.cap; |  | ||||||
|     local name = valuetable[cs.ocap[cs.cap].idx] -- reference name |  | ||||||
|     cs.cap = findback(cs, curr, name, valuetable) -- find corresponding group |  | ||||||
|     local n = pushnestedvalues(cs, false, out, valuetable); -- push group's values |  | ||||||
|     cs.cap = curr + 1; |  | ||||||
|     return n; |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Table capture: creates a new table and populates it with nested |  | ||||||
| -- captures. |  | ||||||
|  |  | ||||||
| local function tablecap(cs, out, valuetable) |  | ||||||
|     local n = 0; |  | ||||||
|     local t = {} |  | ||||||
|     cs.cap = cs.cap + 1 |  | ||||||
|     -- table is empty |  | ||||||
|     if cs.ocap[cs.cap - 1].siz == 0 then |  | ||||||
|         while cs.ocap[cs.cap].kind ~= Cclose do |  | ||||||
|             local subout = { outindex = 0, out = {} } |  | ||||||
|             -- named group? |  | ||||||
|             if cs.ocap[cs.cap].kind == Cgroup and cs.ocap[cs.cap].idx ~= 0 then |  | ||||||
|                 local groupname = valuetable[cs.ocap[cs.cap].idx] -- push group name |  | ||||||
|                 pushonenestedvalue(cs, subout, valuetable) |  | ||||||
|                 t[groupname] = subout.out[1] |  | ||||||
|             else |  | ||||||
|                 -- not a named group |  | ||||||
|                 local k = pushcapture(cs, subout, valuetable) |  | ||||||
|                 -- store all values into table |  | ||||||
|                 for i = 1, subout.outindex do |  | ||||||
|                     t[i + n] = subout.out[i] |  | ||||||
|                 end |  | ||||||
|                 n = n + k; |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|         cs.cap = cs.cap + 1 -- skip close entry |  | ||||||
|     end |  | ||||||
|     out.outindex = out.outindex + 1 |  | ||||||
|     out.out[out.outindex] = t |  | ||||||
|     return 1; -- number of values pushed (only the table) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Table-query capture |  | ||||||
|  |  | ||||||
| local function querycap(cs, out, valuetable) |  | ||||||
|     local table = valuetable[cs.ocap[cs.cap].idx] |  | ||||||
|     local subout = { outindex = 0, out = {} } |  | ||||||
|     pushonenestedvalue(cs, subout, valuetable) -- get nested capture |  | ||||||
|     -- query cap. value at table |  | ||||||
|     if table[subout.out[1]] ~= nil then |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = table[subout.out[1]] |  | ||||||
|         return 1 |  | ||||||
|     end |  | ||||||
|     return 0 |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Fold capture |  | ||||||
|  |  | ||||||
| local function foldcap(cs, out, valuetable) |  | ||||||
|     local fce = valuetable[cs.ocap[cs.cap].idx] |  | ||||||
|     cs.cap = cs.cap + 1 |  | ||||||
|     -- no nested captures? |  | ||||||
|     -- or no nested captures (large subject)? |  | ||||||
|     if cs.ocap[cs.cap - 1].siz ~= 0 or |  | ||||||
|             cs.ocap[cs.cap].kind == Cclose then |  | ||||||
|         error("no initial value for fold capture", 0); |  | ||||||
|     end |  | ||||||
|     local subout = { outindex = 0; out = {} } |  | ||||||
|     local n = pushcapture(cs, subout, valuetable) -- nested captures with no values? |  | ||||||
|     if n == 0 then |  | ||||||
|         error("no initial value for fold capture", 0); |  | ||||||
|     end |  | ||||||
|     local acumulator = subout.out[1] -- leave only one result for accumulator |  | ||||||
|     while cs.ocap[cs.cap].kind ~= Cclose do |  | ||||||
|         local subout = { outindex = 0; out = {} } |  | ||||||
|         n = pushcapture(cs, subout, valuetable); -- get next capture's values |  | ||||||
|         acumulator = fce(acumulator, unpack(subout.out, 1, subout.outindex)) -- call folding function |  | ||||||
|     end |  | ||||||
|     cs.cap = cs.cap + 1; -- skip close entry |  | ||||||
|     out.outindex = out.outindex + 1 |  | ||||||
|     out.out[out.outindex] = acumulator |  | ||||||
|     return 1; -- only accumulator left on the stack |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function retcount(...) |  | ||||||
|     return select('#', ...), { ... } |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Function capture |  | ||||||
|  |  | ||||||
| local function functioncap(cs, out, valuetable) |  | ||||||
|     local fce = valuetable[cs.ocap[cs.cap].idx] --  push function |  | ||||||
|     local subout = { outindex = 0, out = {} } |  | ||||||
|     local n = pushnestedvalues(cs, false, subout, valuetable); -- push nested captures |  | ||||||
|     local count, ret = retcount(fce(unpack(subout.out, 1, n))) -- call function |  | ||||||
|     for i = 1, count do |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = ret[i] |  | ||||||
|     end |  | ||||||
|     return count |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Select capture |  | ||||||
|  |  | ||||||
| local function numcap(cs, out, valuetable) |  | ||||||
|     local idx = valuetable[cs.ocap[cs.cap].idx] -- value to select |  | ||||||
|     -- no values? |  | ||||||
|     if idx == 0 then |  | ||||||
|         nextcap(cs); -- skip entire capture |  | ||||||
|         return 0; -- no value produced |  | ||||||
|     else |  | ||||||
|         local subout = { outindex = 0, out = {} } |  | ||||||
|         local n = pushnestedvalues(cs, false, subout, valuetable) |  | ||||||
|         -- invalid index? |  | ||||||
|         if n < idx then |  | ||||||
|             error(("no capture '%d'"):format(idx), 0) |  | ||||||
|         else |  | ||||||
|             out.outindex = out.outindex + 1 |  | ||||||
|             out.out[out.outindex] = subout.out[idx] -- get selected capture |  | ||||||
|             return 1; |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Calls a runtime capture. Returns number of captures removed by |  | ||||||
| -- the call, including the initial Cgroup. (Captures to be added are |  | ||||||
| -- on the Lua stack.) |  | ||||||
|  |  | ||||||
| local function runtimecap(cs, close, s, out, valuetable) |  | ||||||
|     local open = findopen(cs, close) |  | ||||||
|     assert(cs.ocap[open].kind == Cgroup) |  | ||||||
|     cs.ocap[close].kind = Cclose; -- closes the group |  | ||||||
|     cs.ocap[close].s = s; |  | ||||||
|     cs.cap = open; |  | ||||||
|     local fce = valuetable[cs.ocap[cs.cap].idx] -- push function to be called |  | ||||||
|     local subout = { outindex = 0, out = {} } |  | ||||||
|     local n = pushnestedvalues(cs, false, subout, valuetable); -- push nested captures |  | ||||||
|     local count, ret = retcount(fce(cs.s or cs.stream, s, unpack(subout.out, 1, n))) -- call dynamic function |  | ||||||
|     for i = 1, count do |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = ret[i] |  | ||||||
|     end |  | ||||||
|     return close - open -- number of captures of all kinds removed |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Collect values from current capture into array 'cps'. Current |  | ||||||
| -- capture must be Cstring (first call) or Csimple (recursive calls). |  | ||||||
| -- (In first call, fills %0 with whole match for Cstring.) |  | ||||||
| -- Returns number of elements in the array that were filled. |  | ||||||
|  |  | ||||||
| local function getstrcaps(cs, cps, n) |  | ||||||
|     local k = n |  | ||||||
|     n = n + 1 |  | ||||||
|     cps[k + 1].isstring = true; -- get string value |  | ||||||
|     cps[k + 1].startstr = cs.ocap[cs.cap].s; -- starts here |  | ||||||
|     cs.cap = cs.cap + 1 |  | ||||||
|     -- nested captures? |  | ||||||
|     if cs.ocap[cs.cap - 1].siz == 0 then |  | ||||||
|         -- traverse them |  | ||||||
|         while cs.ocap[cs.cap].kind ~= Cclose do |  | ||||||
|             -- too many captures? |  | ||||||
|             if n >= MAXSTRCAPS then |  | ||||||
|                 nextcap(cs); -- skip extra captures (will not need them) |  | ||||||
|             elseif cs.ocap[cs.cap].kind == Csimple then |  | ||||||
|                 -- string? |  | ||||||
|                 n = getstrcaps(cs, cps, n); -- put info. into array |  | ||||||
|             else |  | ||||||
|                 cps[n + 1].isstring = false; -- not a string |  | ||||||
|                 cps[n + 1].origcap = cs.cap; -- keep original capture |  | ||||||
|                 nextcap(cs); |  | ||||||
|                 n = n + 1; |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|         cs.cap = cs.cap + 1 -- skip close |  | ||||||
|     end |  | ||||||
|     cps[k + 1].endstr = cs.ocap[cs.cap - 1].s + cs.ocap[cs.cap - 1].siz - 1 -- ends here |  | ||||||
|     return n; |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- add next capture value (which should be a string) to buffer 'b' |  | ||||||
|  |  | ||||||
| -- String capture: add result to buffer 'b' (instead of pushing |  | ||||||
| -- it into the stack) |  | ||||||
|  |  | ||||||
| local function stringcap(cs, b, valuetable) |  | ||||||
|     local cps = {} |  | ||||||
|     for i = 1, MAXSTRCAPS do |  | ||||||
|         cps[#cps + 1] = {} |  | ||||||
|     end |  | ||||||
|     local fmt = valuetable[cs.ocap[cs.cap].idx] |  | ||||||
|     local n = getstrcaps(cs, cps, 0) - 1; -- collect nested captures |  | ||||||
|     local i = 1 |  | ||||||
|     -- traverse them |  | ||||||
|     while i <= #fmt do |  | ||||||
|         local c = fmt:sub(i, i) |  | ||||||
|         -- not an escape? |  | ||||||
|         if c ~= '%' then |  | ||||||
|             b[#b + 1] = c -- add it to buffer |  | ||||||
|         elseif fmt:sub(i + 1, i + 1) < '0' or fmt:sub(i + 1, i + 1) > '9' then |  | ||||||
|             -- not followed by a digit? |  | ||||||
|             i = i + 1 |  | ||||||
|             b[#b + 1] = fmt:sub(i, i) |  | ||||||
|         else |  | ||||||
|             i = i + 1 |  | ||||||
|             local l = fmt:sub(i, i) - '0'; -- capture index |  | ||||||
|             if l > n then |  | ||||||
|                 error(("invalid capture index (%d)"):format(l), 0) |  | ||||||
|             elseif cps[l + 1].isstring then |  | ||||||
|                 b[#b + 1] = cs.s and cs.s:sub(cps[l + 1].startstr, cps[l + 1].endstr - cps[l + 1].startstr + cps[l + 1].startstr - 1) or |  | ||||||
|                         cs.stream(cps[l + 1].startstr, cps[l + 1].endstr - cps[l + 1].startstr + cps[l + 1].startstr - 1) |  | ||||||
|             else |  | ||||||
|                 local curr = cs.cap; |  | ||||||
|                 cs.cap = cps[l + 1].origcap; -- go back to evaluate that nested capture |  | ||||||
|                 if not addonestring(cs, b, "capture", valuetable) then |  | ||||||
|                     error(("no values in capture index %d"):format(l), 0) |  | ||||||
|                 end |  | ||||||
|                 cs.cap = curr; -- continue from where it stopped |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|         i = i + 1 |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Substitution capture: add result to buffer 'b' |  | ||||||
|  |  | ||||||
| local function substcap(cs, b, valuetable) |  | ||||||
|     local curr = cs.ocap[cs.cap].s; |  | ||||||
|     -- no nested captures? |  | ||||||
|     if cs.ocap[cs.cap].siz ~= 0 then |  | ||||||
|         -- keep original text |  | ||||||
|         b[#b + 1] = cs.s and cs.s:sub(curr, cs.ocap[cs.cap].siz - 1 + curr - 1) or |  | ||||||
|                 cs.stream(curr, cs.ocap[cs.cap].siz - 1 + curr - 1) |  | ||||||
|     else |  | ||||||
|         cs.cap = cs.cap + 1 -- skip open entry |  | ||||||
|         -- traverse nested captures |  | ||||||
|         while cs.ocap[cs.cap].kind ~= Cclose do |  | ||||||
|             local next = cs.ocap[cs.cap].s; |  | ||||||
|             b[#b + 1] = cs.s and cs.s:sub(curr, next - curr + curr - 1) or |  | ||||||
|                     cs.stream(curr, next - curr + curr - 1) -- add text up to capture |  | ||||||
|             if addonestring(cs, b, "replacement", valuetable) then |  | ||||||
|                 curr = cs.ocap[cs.cap - 1].s + cs.ocap[cs.cap - 1].siz - 1; -- continue after match |  | ||||||
|             else |  | ||||||
|                 -- no capture value |  | ||||||
|                 curr = next; -- keep original text in final result |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|         b[#b + 1] = cs.s and cs.s:sub(curr, curr + cs.ocap[cs.cap].s - curr - 1) or |  | ||||||
|                 cs.stream(curr, curr + cs.ocap[cs.cap].s - curr - 1) -- add last piece of text |  | ||||||
|     end |  | ||||||
|     cs.cap = cs.cap + 1 -- go to next capture |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Evaluates a capture and adds its first value to buffer 'b'; returns |  | ||||||
| -- whether there was a value |  | ||||||
|  |  | ||||||
| function addonestring(cs, b, what, valuetable) |  | ||||||
|     local tag = cs.ocap[cs.cap].kind |  | ||||||
|     if tag == Cstring then |  | ||||||
|         stringcap(cs, b, valuetable); -- add capture directly to buffer |  | ||||||
|         return 1 |  | ||||||
|     elseif tag == Csubst then |  | ||||||
|         substcap(cs, b, valuetable); -- add capture directly to buffer |  | ||||||
|         return 1 |  | ||||||
|     else |  | ||||||
|         local subout = { outindex = 0, out = {} } |  | ||||||
|         local n = pushcapture(cs, subout, valuetable); |  | ||||||
|         if n > 0 then |  | ||||||
|             if type(subout.out[1]) ~= 'string' and type(subout.out[1]) ~= 'number' then |  | ||||||
|                 error(("invalid %s value (a %s)"):format(what, type(subout.out[1])), 0) |  | ||||||
|             end |  | ||||||
|             b[#b + 1] = subout.out[1] |  | ||||||
|             return n |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Push all values of the current capture into the stack; returns |  | ||||||
| -- number of values pushed |  | ||||||
|  |  | ||||||
| function pushcapture(cs, out, valuetable) |  | ||||||
|     local type = cs.ocap[cs.cap].kind |  | ||||||
|     if type == Cposition then |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = cs.ocap[cs.cap].s |  | ||||||
|         cs.cap = cs.cap + 1; |  | ||||||
|         return 1; |  | ||||||
|     elseif type == Cconst then |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = valuetable[cs.ocap[cs.cap].idx] |  | ||||||
|         cs.cap = cs.cap + 1 |  | ||||||
|         return 1; |  | ||||||
|     elseif type == Carg then |  | ||||||
|         local arg = valuetable[cs.ocap[cs.cap].idx] |  | ||||||
|         cs.cap = cs.cap + 1 |  | ||||||
|         if arg > cs.ptopcount then |  | ||||||
|             error(("reference to absent extra argument #%d"):format(arg), 0) |  | ||||||
|         end |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = cs.ptop[arg] |  | ||||||
|         return 1; |  | ||||||
|     elseif type == Csimple then |  | ||||||
|         local k = pushnestedvalues(cs, true, out, valuetable) |  | ||||||
|         local index = out.outindex |  | ||||||
|         table.insert(out.out, index - k + 1, out.out[index]) |  | ||||||
|         out[index + 1] = nil |  | ||||||
|         return k; |  | ||||||
|     elseif type == Cruntime then |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = valuetable[cs.ocap[cs.cap].idx] |  | ||||||
|         cs.cap = cs.cap + 1; |  | ||||||
|         return 1; |  | ||||||
|     elseif type == Cstring then |  | ||||||
|         local b = {} |  | ||||||
|         stringcap(cs, b, valuetable) |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = table.concat(b) |  | ||||||
|         return 1; |  | ||||||
|     elseif type == Csubst then |  | ||||||
|         local b = {} |  | ||||||
|         substcap(cs, b, valuetable); |  | ||||||
|         out.outindex = out.outindex + 1 |  | ||||||
|         out.out[out.outindex] = table.concat(b) |  | ||||||
|         return 1; |  | ||||||
|     elseif type == Cgroup then |  | ||||||
|         -- anonymous group? |  | ||||||
|         if cs.ocap[cs.cap].idx == 0 then |  | ||||||
|             return pushnestedvalues(cs, false, out, valuetable); -- add all nested values |  | ||||||
|         else |  | ||||||
|             -- named group: add no values |  | ||||||
|             nextcap(cs); -- skip capture |  | ||||||
|             return 0 |  | ||||||
|         end |  | ||||||
|     elseif type == Cbackref then |  | ||||||
|         return backrefcap(cs, out, valuetable) |  | ||||||
|     elseif type == Ctable then |  | ||||||
|         return tablecap(cs, out, valuetable) |  | ||||||
|     elseif type == Cfunction then |  | ||||||
|         return functioncap(cs, out, valuetable) |  | ||||||
|     elseif type == Cnum then |  | ||||||
|         return numcap(cs, out, valuetable) |  | ||||||
|     elseif type == Cquery then |  | ||||||
|         return querycap(cs, out, valuetable) |  | ||||||
|     elseif type == Cfold then |  | ||||||
|         return foldcap(cs, out, valuetable) |  | ||||||
|     else |  | ||||||
|         assert(false) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Prepare a CapState structure and traverse the entire list of |  | ||||||
| -- captures in the stack pushing its results. 's' is the subject |  | ||||||
| -- string, 'r' is the final position of the match, and 'ptop' |  | ||||||
| -- the index in the stack where some useful values were pushed. |  | ||||||
| -- Returns the number of results pushed. (If the list produces no |  | ||||||
| -- results, push the final position of the match.) |  | ||||||
|  |  | ||||||
| local function getcaptures(capture, s, stream, r, valuetable, ...) |  | ||||||
|     local n = 0; |  | ||||||
|     local cs = { cap = 0 } |  | ||||||
|     local out = { outindex = 0; out = {} } |  | ||||||
|     -- is there any capture? |  | ||||||
|     if capture[cs.cap].kind ~= Cclose then |  | ||||||
|         cs.ocap = capture |  | ||||||
|         cs.s = s; |  | ||||||
|         cs.stream = stream |  | ||||||
|         cs.ptopcount, cs.ptop = retcount(...) |  | ||||||
|         repeat -- collect their values |  | ||||||
|             n = n + pushcapture(cs, out, valuetable) |  | ||||||
|         until cs.ocap[cs.cap].kind == Cclose |  | ||||||
|     end |  | ||||||
|     -- no capture values? |  | ||||||
|     if n == 0 then |  | ||||||
|         if not r then |  | ||||||
|             return |  | ||||||
|         else |  | ||||||
|             return r |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     assert(out.outindex < 7998, "(too many captures)") |  | ||||||
|     return unpack(out.out, 1, out.outindex) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function getcapturesruntime(capture, s, stream, notdelete, min, max, captop, valuetable, ...) |  | ||||||
|     local n = 0; |  | ||||||
|     local cs = { cap = min } |  | ||||||
|     local out = { outindex = 0; out = {} } |  | ||||||
|     cs.ocap = capture |  | ||||||
|     cs.s = s |  | ||||||
|     cs.stream = stream |  | ||||||
|     cs.ptopcount, cs.ptop = retcount(...) |  | ||||||
|     local start = 0 |  | ||||||
|     repeat -- collect their values |  | ||||||
|         if not checknextcap(cs, max) then break end |  | ||||||
|         local notdelete = notdelete or capture[cs.cap].kind == Cgroup and capture[cs.cap].idx ~= 0 and capture[cs.cap].candelete == 0 |  | ||||||
|         pushcapture(cs, out, valuetable) |  | ||||||
|         if notdelete then |  | ||||||
|             start = cs.cap |  | ||||||
|         else |  | ||||||
|             n = n + cs.cap - start |  | ||||||
|             for i = 0, captop - cs.cap - 1 do |  | ||||||
|                 ffi.copy(capture + start + i, capture + cs.cap + i, ffi.sizeof('CAPTURE')) |  | ||||||
|             end |  | ||||||
|             max = max - (cs.cap - start) |  | ||||||
|             captop = captop - (cs.cap - start) |  | ||||||
|             cs.cap = start |  | ||||||
|         end |  | ||||||
|     until cs.cap == max |  | ||||||
|     assert(out.outindex < 7998, "(too many captures)") |  | ||||||
|     return n, out.out, out.outindex |  | ||||||
| end |  | ||||||
|  |  | ||||||
| return { |  | ||||||
|     getcaptures = getcaptures, |  | ||||||
|     runtimecap = runtimecap, |  | ||||||
|     getcapturesruntime = getcapturesruntime, |  | ||||||
| } |  | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1373
									
								
								tools/lpeg/lpeg.lua
									
									
									
									
									
								
							
							
						
						
									
										1373
									
								
								tools/lpeg/lpeg.lua
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,356 +0,0 @@ | |||||||
| --[[ |  | ||||||
| LPEGLJ |  | ||||||
| lpprint.lua |  | ||||||
| Tree, code and debug print function (only for debuging) |  | ||||||
| Copyright (C) 2014 Rostislav Sacek. |  | ||||||
| based on LPeg v1.0 - PEG pattern matching for Lua |  | ||||||
| Lua.org & PUC-Rio  written by Roberto Ierusalimschy |  | ||||||
| http://www.inf.puc-rio.br/~roberto/lpeg/ |  | ||||||
|  |  | ||||||
| ** Permission is hereby granted, free of charge, to any person obtaining |  | ||||||
| ** a copy of this software and associated documentation files (the |  | ||||||
| ** "Software"), to deal in the Software without restriction, including |  | ||||||
| ** without limitation the rights to use, copy, modify, merge, publish, |  | ||||||
| ** distribute, sublicense, and/or sell copies of the Software, and to |  | ||||||
| ** permit persons to whom the Software is furnished to do so, subject to |  | ||||||
| ** the following conditions: |  | ||||||
| ** |  | ||||||
| ** The above copyright notice and this permission notice shall be |  | ||||||
| ** included in all copies or substantial portions of the Software. |  | ||||||
| ** |  | ||||||
| ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |  | ||||||
| ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |  | ||||||
| ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |  | ||||||
| ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |  | ||||||
| ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |  | ||||||
| ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |  | ||||||
| ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |  | ||||||
| ** |  | ||||||
| ** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] |  | ||||||
| --]] |  | ||||||
|  |  | ||||||
| local ffi = require"ffi" |  | ||||||
| local band, rshift, lshift = bit.band, bit.rshift, bit.lshift |  | ||||||
|  |  | ||||||
| ffi.cdef[[ |  | ||||||
|   int isprint ( int c ); |  | ||||||
| ]] |  | ||||||
|  |  | ||||||
| local RuleLR = 0x10000 |  | ||||||
| local Ruleused = 0x20000 |  | ||||||
|  |  | ||||||
| -- {====================================================== |  | ||||||
| -- Printing patterns (for debugging) |  | ||||||
| -- ======================================================= |  | ||||||
|  |  | ||||||
| local TChar = 0 |  | ||||||
| local TSet = 1 |  | ||||||
| local TAny = 2 -- standard PEG elements |  | ||||||
| local TTrue = 3 |  | ||||||
| local TFalse = 4 |  | ||||||
| local TRep = 5 |  | ||||||
| local TSeq = 6 |  | ||||||
| local TChoice = 7 |  | ||||||
| local TNot = 8 |  | ||||||
| local TAnd = 9 |  | ||||||
| local TCall = 10 |  | ||||||
| local TOpenCall = 11 |  | ||||||
| local TRule = 12 -- sib1 is rule's pattern, sib2 is 'next' rule |  | ||||||
| local TGrammar = 13 -- sib1 is initial (and first) rule |  | ||||||
| local TBehind = 14 -- match behind |  | ||||||
| local TCapture = 15 -- regular capture |  | ||||||
| local TRunTime = 16 -- run-time capture |  | ||||||
|  |  | ||||||
| local IAny = 0 -- if no char, fail |  | ||||||
| local IChar = 1 -- if char != aux, fail |  | ||||||
| local ISet = 2 -- if char not in val, fail |  | ||||||
| local ITestAny = 3 -- in no char, jump to 'offset' |  | ||||||
| local ITestChar = 4 -- if char != aux, jump to 'offset' |  | ||||||
| local ITestSet = 5 -- if char not in val, jump to 'offset' |  | ||||||
| local ISpan = 6 -- read a span of chars in val |  | ||||||
| local IBehind = 7 -- walk back 'aux' characters (fail if not possible) |  | ||||||
| local IRet = 8 -- return from a rule |  | ||||||
| local IEnd = 9 -- end of pattern |  | ||||||
| local IChoice = 10 -- stack a choice; next fail will jump to 'offset' |  | ||||||
| local IJmp = 11 -- jump to 'offset' |  | ||||||
| local ICall = 12 -- call rule at 'offset' |  | ||||||
| local IOpenCall = 13 -- call rule number 'offset' (must be closed to a ICall) |  | ||||||
| local ICommit = 14 -- pop choice and jump to 'offset' |  | ||||||
| local IPartialCommit = 15 -- update top choice to current position and jump |  | ||||||
| local IBackCommit = 16 -- "fails" but jump to its own 'offset' |  | ||||||
| local IFailTwice = 17 -- pop one choice and then fail |  | ||||||
| local IFail = 18 -- go back to saved state on choice and jump to saved offset |  | ||||||
| local IGiveup = 19 -- internal use |  | ||||||
| local IFullCapture = 20 -- complete capture of last 'off' chars |  | ||||||
| local IOpenCapture = 21 -- start a capture |  | ||||||
| local ICloseCapture = 22 |  | ||||||
| local ICloseRunTime = 23 |  | ||||||
|  |  | ||||||
| local Cclose = 0 |  | ||||||
| local Cposition = 1 |  | ||||||
| local Cconst = 2 |  | ||||||
| local Cbackref = 3 |  | ||||||
| local Carg = 4 |  | ||||||
| local Csimple = 5 |  | ||||||
| local Ctable = 6 |  | ||||||
| local Cfunction = 7 |  | ||||||
| local Cquery = 8 |  | ||||||
| local Cstring = 9 |  | ||||||
| local Cnum = 10 |  | ||||||
| local Csubst = 11 |  | ||||||
| local Cfold = 12 |  | ||||||
| local Cruntime = 13 |  | ||||||
| local Cgroup = 14 |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- number of siblings for each tree |  | ||||||
| local numsiblings = { |  | ||||||
|     [TRep] = 1, |  | ||||||
|     [TSeq] = 2, |  | ||||||
|     [TChoice] = 2, |  | ||||||
|     [TNot] = 1, |  | ||||||
|     [TAnd] = 1, |  | ||||||
|     [TRule] = 2, |  | ||||||
|     [TGrammar] = 1, |  | ||||||
|     [TBehind] = 1, |  | ||||||
|     [TCapture] = 1, |  | ||||||
|     [TRunTime] = 1, |  | ||||||
| } |  | ||||||
| local names = { |  | ||||||
|     [IAny] = "any", |  | ||||||
|     [IChar] = "char", |  | ||||||
|     [ISet] = "set", |  | ||||||
|     [ITestAny] = "testany", |  | ||||||
|     [ITestChar] = "testchar", |  | ||||||
|     [ITestSet] = "testset", |  | ||||||
|     [ISpan] = "span", |  | ||||||
|     [IBehind] = "behind", |  | ||||||
|     [IRet] = "ret", |  | ||||||
|     [IEnd] = "end", |  | ||||||
|     [IChoice] = "choice", |  | ||||||
|     [IJmp] = "jmp", |  | ||||||
|     [ICall] = "call", |  | ||||||
|     [IOpenCall] = "open_call", |  | ||||||
|     [ICommit] = "commit", |  | ||||||
|     [IPartialCommit] = "partial_commit", |  | ||||||
|     [IBackCommit] = "back_commit", |  | ||||||
|     [IFailTwice] = "failtwice", |  | ||||||
|     [IFail] = "fail", |  | ||||||
|     [IGiveup] = "giveup", |  | ||||||
|     [IFullCapture] = "fullcapture", |  | ||||||
|     [IOpenCapture] = "opencapture", |  | ||||||
|     [ICloseCapture] = "closecapture", |  | ||||||
|     [ICloseRunTime] = "closeruntime" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local function printcharset(st) |  | ||||||
|     io.write("["); |  | ||||||
|     local i = 0 |  | ||||||
|     while i <= 255 do |  | ||||||
|         local first = i; |  | ||||||
|         while band(st[rshift(i, 5)], lshift(1, band(i, 31))) ~= 0 and i <= 255 do |  | ||||||
|             i = i + 1 |  | ||||||
|         end |  | ||||||
|         if i - 1 == first then -- unary range? |  | ||||||
|             io.write(("(%02x)"):format(first)) |  | ||||||
|         elseif i - 1 > first then -- non-empty range? |  | ||||||
|             io.write(("(%02x-%02x)"):format(first, i - 1)) |  | ||||||
|         end |  | ||||||
|         i = i + 1 |  | ||||||
|     end |  | ||||||
|     io.write("]") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local modes = { |  | ||||||
|     [Cclose] = "close", |  | ||||||
|     [Cposition] = "position", |  | ||||||
|     [Cconst] = "constant", |  | ||||||
|     [Cbackref] = "backref", |  | ||||||
|     [Carg] = "argument", |  | ||||||
|     [Csimple] = "simple", |  | ||||||
|     [Ctable] = "table", |  | ||||||
|     [Cfunction] = "function", |  | ||||||
|     [Cquery] = "query", |  | ||||||
|     [Cstring] = "string", |  | ||||||
|     [Cnum] = "num", |  | ||||||
|     [Csubst] = "substitution", |  | ||||||
|     [Cfold] = "fold", |  | ||||||
|     [Cruntime] = "runtime", |  | ||||||
|     [Cgroup] = "group" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local function printcapkind(kind) |  | ||||||
|     io.write(("%s"):format(modes[kind])) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function printjmp(p, index) |  | ||||||
|     io.write(("-> %d"):format(index + p[index].offset)) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function printrulename(p, index, rulenames) |  | ||||||
|     if rulenames and rulenames[index + p[index].offset] then |  | ||||||
|         io.write(' ', rulenames[index + p[index].offset]) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function printinst(p, index, valuetable, rulenames) |  | ||||||
|     local code = p[index].code |  | ||||||
|     if rulenames and rulenames[index] then |  | ||||||
|         io.write(rulenames[index], '\n') |  | ||||||
|     end |  | ||||||
|     io.write(("%04d: %s "):format(index, names[code])) |  | ||||||
|     if code == IChar then |  | ||||||
|         io.write(("'%s'"):format(string.char(p[index].val))) |  | ||||||
|     elseif code == ITestChar then |  | ||||||
|         io.write(("'%s'"):format(string.char(p[index].val))) |  | ||||||
|         printjmp(p, index) |  | ||||||
|         printrulename(p, index, rulenames) |  | ||||||
|     elseif code == IFullCapture then |  | ||||||
|         printcapkind(band(p[index].val, 0x0f)); |  | ||||||
|         io.write((" (size = %d)  (idx = %s)"):format(band(rshift(p[index].val, 4), 0xF), tostring(valuetable[p[index].offset]))) |  | ||||||
|     elseif code == IOpenCapture then |  | ||||||
|         printcapkind(band(p[index].val, 0x0f)) |  | ||||||
|         io.write((" (idx = %s)"):format(tostring(valuetable[p[index].offset]))) |  | ||||||
|     elseif code == ISet then |  | ||||||
|         printcharset(valuetable[p[index].val]); |  | ||||||
|     elseif code == ITestSet then |  | ||||||
|         printcharset(valuetable[p[index].val]) |  | ||||||
|         printjmp(p, index); |  | ||||||
|         printrulename(p, index, rulenames) |  | ||||||
|     elseif code == ISpan then |  | ||||||
|         printcharset(valuetable[p[index].val]); |  | ||||||
|     elseif code == IOpenCall then |  | ||||||
|         io.write(("-> %d"):format(p[index].offset)) |  | ||||||
|     elseif code == IBehind then |  | ||||||
|         io.write(("%d"):format(p[index].val)) |  | ||||||
|     elseif code == IJmp or code == ICall or code == ICommit or code == IChoice or |  | ||||||
|             code == IPartialCommit or code == IBackCommit or code == ITestAny then |  | ||||||
|         printjmp(p, index); |  | ||||||
|         if (code == ICall or code == IJmp) and p[index].aux > 0 then |  | ||||||
|             io.write(' ', valuetable[p[index].aux]) |  | ||||||
|         else |  | ||||||
|             printrulename(p, index, rulenames) |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     io.write("\n") |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function printpatt(p, valuetable) |  | ||||||
|     local ruleNames = {} |  | ||||||
|     for i = 0, p.size - 1 do |  | ||||||
|         local code = p.p[i].code |  | ||||||
|         if (code == ICall or code == IJmp) and p.p[i].aux > 0 then |  | ||||||
|             local index = i + p.p[i].offset |  | ||||||
|             ruleNames[index] = valuetable[p.p[i].aux] |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     for i = 0, p.size - 1 do |  | ||||||
|         printinst(p.p, i, valuetable, ruleNames) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function printcap(cap, index, valuetable) |  | ||||||
|     printcapkind(cap[index].kind) |  | ||||||
|     io.write((" (idx: %s - size: %d) -> %d\n"):format(valuetable[cap[index].idx], cap[index].siz, cap[index].s)) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function printcaplist(cap, limit, valuetable) |  | ||||||
|     io.write(">======\n") |  | ||||||
|     local index = 0 |  | ||||||
|     while cap[index].s and index < limit do |  | ||||||
|         printcap(cap, index, valuetable) |  | ||||||
|         index = index + 1 |  | ||||||
|     end |  | ||||||
|     io.write("=======\n") |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- ====================================================== |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- {====================================================== |  | ||||||
| -- Printing trees (for debugging) |  | ||||||
| -- ======================================================= |  | ||||||
|  |  | ||||||
| local tagnames = { |  | ||||||
|     [TChar] = "char", |  | ||||||
|     [TSet] = "set", |  | ||||||
|     [TAny] = "any", |  | ||||||
|     [TTrue] = "true", |  | ||||||
|     [TFalse] = "false", |  | ||||||
|     [TRep] = "rep", |  | ||||||
|     [TSeq] = "seq", |  | ||||||
|     [TChoice] = "choice", |  | ||||||
|     [TNot] = "not", |  | ||||||
|     [TAnd] = "and", |  | ||||||
|     [TCall] = "call", |  | ||||||
|     [TOpenCall] = "opencall", |  | ||||||
|     [TRule] = "rule", |  | ||||||
|     [TGrammar] = "grammar", |  | ||||||
|     [TBehind] = "behind", |  | ||||||
|     [TCapture] = "capture", |  | ||||||
|     [TRunTime] = "run-time" |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function printtree(tree, ident, index, valuetable) |  | ||||||
|     for i = 1, ident do |  | ||||||
|         io.write(" ") |  | ||||||
|     end |  | ||||||
|     local tag = tree[index].tag |  | ||||||
|     io.write(("%s"):format(tagnames[tag])) |  | ||||||
|     if tag == TChar then |  | ||||||
|         local c = tree[index].val |  | ||||||
|         if ffi.C.isprint(c) then |  | ||||||
|             io.write((" '%c'\n"):format(c)) |  | ||||||
|         else |  | ||||||
|             io.write((" (%02X)\n"):format(c)) |  | ||||||
|         end |  | ||||||
|     elseif tag == TSet then |  | ||||||
|         printcharset(valuetable[tree[index].val]); |  | ||||||
|         io.write("\n") |  | ||||||
|     elseif tag == TOpenCall or tag == TCall then |  | ||||||
|         io.write((" key: %s\n"):format(tostring(valuetable[tree[index].val]))) |  | ||||||
|     elseif tag == TBehind then |  | ||||||
|         io.write((" %d\n"):format(tree[index].val)) |  | ||||||
|         printtree(tree, ident + 2, index + 1, valuetable); |  | ||||||
|     elseif tag == TCapture then |  | ||||||
|         io.write((" cap: %s   n: %s\n"):format(modes[bit.band(tree[index].cap, 0xffff)], valuetable[tree[index].val])) |  | ||||||
|         printtree(tree, ident + 2, index + 1, valuetable); |  | ||||||
|     elseif tag == TRule then |  | ||||||
|         local extra = bit.band(tree[index].cap, RuleLR) == RuleLR and ' left recursive' or '' |  | ||||||
|         extra = extra .. (bit.band(tree[index].cap, Ruleused) ~= Ruleused and ' not used' or '') |  | ||||||
|         io.write((" n: %d  key: %s%s\n"):format(bit.band(tree[index].cap, 0xffff) - 1, valuetable[tree[index].val], extra)) |  | ||||||
|         printtree(tree, ident + 2, index + 1, valuetable); |  | ||||||
|         -- do not print next rule as a sibling |  | ||||||
|     elseif tag == TGrammar then |  | ||||||
|         local ruleindex = index + 1 |  | ||||||
|         io.write((" %d\n"):format(tree[index].val)) -- number of rules |  | ||||||
|         for i = 1, tree[index].val do |  | ||||||
|             printtree(tree, ident + 2, ruleindex, valuetable); |  | ||||||
|             ruleindex = ruleindex + tree[ruleindex].ps |  | ||||||
|         end |  | ||||||
|         assert(tree[ruleindex].tag == TTrue); -- sentinel |  | ||||||
|     else |  | ||||||
|         local sibs = numsiblings[tree[index].tag] or 0 |  | ||||||
|         io.write("\n") |  | ||||||
|         if sibs >= 1 then |  | ||||||
|             printtree(tree, ident + 2, index + 1, valuetable); |  | ||||||
|             if sibs >= 2 then |  | ||||||
|                 printtree(tree, ident + 2, index + tree[index].ps, valuetable) |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- }====================================================== */ |  | ||||||
|  |  | ||||||
| return { |  | ||||||
|     printtree = printtree, |  | ||||||
|     printpatt = printpatt, |  | ||||||
|     printcaplist = printcaplist, |  | ||||||
|     printinst = printinst |  | ||||||
| } |  | ||||||
							
								
								
									
										1041
									
								
								tools/lpeg/lpvm.lua
									
									
									
									
									
								
							
							
						
						
									
										1041
									
								
								tools/lpeg/lpvm.lua
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,286 +0,0 @@ | |||||||
| -- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $ |  | ||||||
| -- 2014/08/15 changes rostislav |  | ||||||
|  |  | ||||||
| -- imported functions and modules |  | ||||||
| local tonumber, print, error = tonumber, print, error |  | ||||||
| local setmetatable = setmetatable |  | ||||||
| local m = require"lpeglj" |  | ||||||
|  |  | ||||||
| -- 'm' will be used to parse expressions, and 'mm' will be used to |  | ||||||
| -- create expressions; that is, 're' runs on 'm', creating patterns |  | ||||||
| -- on 'mm' |  | ||||||
| local mm = m |  | ||||||
|  |  | ||||||
| -- pattern's metatable |  | ||||||
| local mt = getmetatable(mm.P(0)) |  | ||||||
| mt = m.version() == "1.0.0.0LJ" and m or mt |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- No more global accesses after this point |  | ||||||
| local version = _VERSION |  | ||||||
| if version == "Lua 5.2" then _ENV = nil end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local any = m.P(1) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- Pre-defined names |  | ||||||
| local Predef = { nl = m.P"\n" } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local mem |  | ||||||
| local fmem |  | ||||||
| local gmem |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function updatelocale () |  | ||||||
|   mm.locale(Predef) |  | ||||||
|   Predef.a = Predef.alpha |  | ||||||
|   Predef.c = Predef.cntrl |  | ||||||
|   Predef.d = Predef.digit |  | ||||||
|   Predef.g = Predef.graph |  | ||||||
|   Predef.l = Predef.lower |  | ||||||
|   Predef.p = Predef.punct |  | ||||||
|   Predef.s = Predef.space |  | ||||||
|   Predef.u = Predef.upper |  | ||||||
|   Predef.w = Predef.alnum |  | ||||||
|   Predef.x = Predef.xdigit |  | ||||||
|   Predef.A = any - Predef.a |  | ||||||
|   Predef.C = any - Predef.c |  | ||||||
|   Predef.D = any - Predef.d |  | ||||||
|   Predef.G = any - Predef.g |  | ||||||
|   Predef.L = any - Predef.l |  | ||||||
|   Predef.P = any - Predef.p |  | ||||||
|   Predef.S = any - Predef.s |  | ||||||
|   Predef.U = any - Predef.u |  | ||||||
|   Predef.W = any - Predef.w |  | ||||||
|   Predef.X = any - Predef.x |  | ||||||
|   mem = {}    -- restart memoization |  | ||||||
|   fmem = {} |  | ||||||
|   gmem = {} |  | ||||||
|   local mt = {__mode = "v"} |  | ||||||
|   setmetatable(mem, mt) |  | ||||||
|   setmetatable(fmem, mt) |  | ||||||
|   setmetatable(gmem, mt) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| updatelocale() |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function getdef (id, defs) |  | ||||||
|   local c = defs and defs[id] |  | ||||||
|   if not c then error("undefined name: " .. id) end |  | ||||||
|   return c |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function patt_error (s, i) |  | ||||||
|   local msg = (#s < i + 20) and s:sub(i) |  | ||||||
|                              or s:sub(i,i+20) .. "..." |  | ||||||
|   msg = ("pattern error near '%s'"):format(msg) |  | ||||||
|   error(msg, 2) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function mult (p, n) |  | ||||||
|   local np = mm.P(true) |  | ||||||
|   while n >= 1 do |  | ||||||
|     if n%2 >= 1 then np = np * p end |  | ||||||
|     p = p * p |  | ||||||
|     n = n/2 |  | ||||||
|   end |  | ||||||
|   return np |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function equalcap (s, i, c) |  | ||||||
|   if type(c) ~= "string" then return nil end |  | ||||||
|   local e = #c + i |  | ||||||
|   if type(s) == 'function' then  -- stream mode |  | ||||||
|       if s(i, e - 1) == c then return e else return nil end |  | ||||||
|   else |  | ||||||
|       if s:sub(i, e - 1) == c then return e else return nil end |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local S = (Predef.space + "--" * (any - Predef.nl)^0)^0 |  | ||||||
|  |  | ||||||
| local name = m.R("AZ", "az", "__") * m.R("AZ", "az", "__", "09")^0 |  | ||||||
|  |  | ||||||
| local arrow = S * "<-" |  | ||||||
|  |  | ||||||
| local seq_follow = m.P"/" + ")" + "}" + ":}" + "~}" + "|}" + (name * arrow) + -1 |  | ||||||
|  |  | ||||||
| name = m.C(name) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- a defined name only have meaning in a given environment |  | ||||||
| local Def = name * m.Carg(1) |  | ||||||
|  |  | ||||||
| local num = m.C(m.R"09"^1) * S / tonumber |  | ||||||
|  |  | ||||||
| local String = "'" * m.C((any - "'")^0) * "'" + |  | ||||||
|                '"' * m.C((any - '"')^0) * '"' |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local defined = "%" * Def / function (c,Defs) |  | ||||||
|   local cat =  Defs and Defs[c] or Predef[c] |  | ||||||
|   if not cat then error ("name '" .. c .. "' undefined") end |  | ||||||
|   return cat |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R |  | ||||||
|  |  | ||||||
| local item = defined + Range + m.C(any) |  | ||||||
|  |  | ||||||
| local Class = |  | ||||||
|     "[" |  | ||||||
|   * (m.C(m.P"^"^-1))    -- optional complement symbol |  | ||||||
|   * m.Cf(item * (item - "]")^0, mt.__add) / |  | ||||||
|                           function (c, p) return c == "^" and any - p or p end |  | ||||||
|   * "]" |  | ||||||
|  |  | ||||||
| local function adddef (t, k, exp) |  | ||||||
|   if t[k] then |  | ||||||
|     error("'"..k.."' already defined as a rule") |  | ||||||
|   else |  | ||||||
|     t[k] = exp |  | ||||||
|   end |  | ||||||
|   return t |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function firstdef (n, r) return adddef({n}, n, r) end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function NT (n, b, p) |  | ||||||
|   if not b then |  | ||||||
|     error("rule '"..n.."' used outside a grammar") |  | ||||||
|   else return mm.V(n, p or 0) |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local exp = m.P{ "Exp", |  | ||||||
|   Exp = S * ( m.V"Grammar" |  | ||||||
|             + m.Cf(m.V"Seq" * ("/" * S * m.V"Seq")^0, mt.__add) ); |  | ||||||
|   Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix"^0 , mt.__mul) |  | ||||||
|         * (#seq_follow + patt_error); |  | ||||||
|   Prefix = "&" * S * m.V"Prefix" / mt.__len |  | ||||||
|          + "!" * S * m.V"Prefix" / mt.__unm |  | ||||||
|          + m.V"Suffix"; |  | ||||||
|   Suffix = m.Cf(m.V"Primary" * S * |  | ||||||
|           ( ( m.P"+" * m.Cc(1, mt.__pow) |  | ||||||
|             + m.P"*" * m.Cc(0, mt.__pow) |  | ||||||
|             + m.P"?" * m.Cc(-1, mt.__pow) |  | ||||||
|             + "^" * ( m.Cg(num * m.Cc(mult)) |  | ||||||
|                     + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow)) |  | ||||||
|                     ) |  | ||||||
|             + "->" * S * ( m.Cg((String + num) * m.Cc(mt.__div)) |  | ||||||
|                          + m.P"{}" * m.Cc(nil, m.Ct) |  | ||||||
|                          + m.Cg(Def / getdef * m.Cc(mt.__div)) |  | ||||||
|                          ) |  | ||||||
|             + "=>" * S * m.Cg(Def / getdef * m.Cc(m.Cmt)) |  | ||||||
|             ) * S |  | ||||||
|           )^0, function (a,b,f) return f(a,b) end ); |  | ||||||
|   Primary = "(" * m.V"Exp" * ")" |  | ||||||
|             + String / mm.P |  | ||||||
|             + Class |  | ||||||
|             + defined |  | ||||||
|             + "{:" * (name * ":" + m.Cc(nil)) * m.V"Exp" * ":}" / |  | ||||||
|                      function (n, p) return mm.Cg(p, n) end |  | ||||||
|             + "=" * name / function (n) return mm.Cmt(mm.Cb(n), equalcap) end |  | ||||||
|             + m.P"{}" / mm.Cp |  | ||||||
|             + "{~" * m.V"Exp" * "~}" / mm.Cs |  | ||||||
|             + "{|" * m.V"Exp" * "|}" / mm.Ct |  | ||||||
|             + "{" * m.V"Exp" * "}" / mm.C |  | ||||||
|             + m.P"." * m.Cc(any) |  | ||||||
|             + (name * m.Cb("G") * (S * ":" * S * num)^-1 * -arrow + "<" * name * m.Cb("G") * (S * ":" * S * num)^-1 * ">") / NT; |  | ||||||
|   Definition = name * arrow * m.V"Exp"; |  | ||||||
|   Grammar = m.Cg(m.Cc(true), "G") * |  | ||||||
|             m.Cf(m.V"Definition" / firstdef * m.Cg(m.V"Definition")^0, |  | ||||||
|               adddef) / mm.P |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local pattern = S * m.Cg(m.Cc(false), "G") * exp / mm.P * (-any + patt_error) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function compile (p, defs) |  | ||||||
|   if mm.type(p) == "pattern" then return p end   -- already compiled |  | ||||||
|   local cp = pattern:match(p, 1, defs) |  | ||||||
|   if not cp then error("incorrect pattern", 3) end |  | ||||||
|   return cp |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function match (s, p, i) |  | ||||||
|   local cp = mem[p] |  | ||||||
|   if not cp then |  | ||||||
|     cp = compile(p) |  | ||||||
|     mem[p] = cp |  | ||||||
|   end |  | ||||||
|   return cp:match(s, i or 1) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function streammatch (p, i) |  | ||||||
|     local cp = mem[p] |  | ||||||
|     if not cp then |  | ||||||
|         cp = compile(p) |  | ||||||
|         mem[p] = cp |  | ||||||
|     end |  | ||||||
|     return cp:streammatch(i or 1) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Only for testing purpose |  | ||||||
| local function emulatestreammatch(s, p, i) |  | ||||||
|     local cp = mem[p] |  | ||||||
|     if not cp then |  | ||||||
|         cp = compile(p) |  | ||||||
|         mem[p] = cp |  | ||||||
|     end |  | ||||||
|     return cp:emulatestreammatch(s, i or 1) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function find (s, p, i) |  | ||||||
|   local cp = fmem[p] |  | ||||||
|   if not cp then |  | ||||||
|     cp = compile(p) / 0 |  | ||||||
|     cp = mm.P{ mm.Cp() * cp * mm.Cp() + 1 * mm.V(1) } |  | ||||||
|     fmem[p] = cp |  | ||||||
|   end |  | ||||||
|   local i, e = cp:match(s, i or 1) |  | ||||||
|   if i then return i, e - 1 |  | ||||||
|   else return i |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function gsub (s, p, rep) |  | ||||||
|   local g = gmem[p] or {}   -- ensure gmem[p] is not collected while here |  | ||||||
|   gmem[p] = g |  | ||||||
|   local cp = g[rep] |  | ||||||
|   if not cp then |  | ||||||
|     cp = compile(p) |  | ||||||
|     cp = mm.Cs((cp / rep + 1)^0) |  | ||||||
|     g[rep] = cp |  | ||||||
|   end |  | ||||||
|   return cp:match(s) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| -- exported names |  | ||||||
| local re = { |  | ||||||
|   compile = compile, |  | ||||||
|   match = match, |  | ||||||
|   streammatch = streammatch, |  | ||||||
|   emulatestreammatch = emulatestreammatch, |  | ||||||
|   find = find, |  | ||||||
|   gsub = gsub, |  | ||||||
|   updatelocale = updatelocale, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| if version == "Lua 5.1" then _G.re = re end |  | ||||||
|  |  | ||||||
| return re |  | ||||||
| @@ -1,25 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| package.path = package.path .. ";lpeg/?.lua" |  | ||||||
| local decode = require("json.decode") |  | ||||||
| local encode = require("json.encode") |  | ||||||
| local util = require("json.util") |  | ||||||
|  |  | ||||||
| local _G = _G |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local json = { |  | ||||||
| 	_VERSION = "1.3.4", |  | ||||||
| 	_DESCRIPTION = "LuaJSON : customizable JSON decoder/encoder", |  | ||||||
| 	_COPYRIGHT = "Copyright (c) 2007-2014 Thomas Harning Jr. <harningt@gmail.com>", |  | ||||||
| 	decode = decode, |  | ||||||
| 	encode = encode, |  | ||||||
| 	util = util |  | ||||||
| } |  | ||||||
|  |  | ||||||
| _G.json = json |  | ||||||
|  |  | ||||||
| return json |  | ||||||
| @@ -1,171 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local lpeg = require("lpeg") |  | ||||||
|  |  | ||||||
| local error = error |  | ||||||
| local pcall = pcall |  | ||||||
|  |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local merge = jsonutil.merge |  | ||||||
| local util = require("json.decode.util") |  | ||||||
|  |  | ||||||
| local decode_state = require("json.decode.state") |  | ||||||
|  |  | ||||||
| local setmetatable, getmetatable = setmetatable, getmetatable |  | ||||||
| local assert = assert |  | ||||||
| local ipairs, pairs = ipairs, pairs |  | ||||||
| local string_char = require("string").char |  | ||||||
|  |  | ||||||
| local type = type |  | ||||||
|  |  | ||||||
| local require = require |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local modulesToLoad = { |  | ||||||
| 	"composite", |  | ||||||
| 	"strings", |  | ||||||
| 	"number", |  | ||||||
| 	"others" |  | ||||||
| } |  | ||||||
| local loadedModules = { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local json_decode = {} |  | ||||||
|  |  | ||||||
| json_decode.default = { |  | ||||||
| 	unicodeWhitespace = true, |  | ||||||
| 	initialObject = false, |  | ||||||
| 	nothrow = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modes_defined = { "default", "strict", "simple" } |  | ||||||
|  |  | ||||||
| json_decode.simple = {} |  | ||||||
|  |  | ||||||
| json_decode.strict = { |  | ||||||
| 	unicodeWhitespace = true, |  | ||||||
| 	initialObject = true, |  | ||||||
| 	nothrow = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| for _,name in ipairs(modulesToLoad) do |  | ||||||
| 	local mod = require("json.decode." .. name) |  | ||||||
| 	if mod.mergeOptions then |  | ||||||
| 		for _, mode in pairs(modes_defined) do |  | ||||||
| 			mod.mergeOptions(json_decode[mode], mode) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	loadedModules[#loadedModules + 1] = mod |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Shift over default into defaultOptions to permit build optimization |  | ||||||
| local defaultOptions = json_decode.default |  | ||||||
| json_decode.default = nil |  | ||||||
|  |  | ||||||
| local function generateDecoder(lexer, options) |  | ||||||
| 	-- Marker to permit detection of final end |  | ||||||
| 	local marker = {} |  | ||||||
| 	local parser = lpeg.Ct((options.ignored * lexer)^0 * lpeg.Cc(marker)) * options.ignored * (lpeg.P(-1) + util.unexpected()) |  | ||||||
| 	local decoder = function(data) |  | ||||||
| 		local state = decode_state.create(options) |  | ||||||
| 		local parsed = parser:match(data) |  | ||||||
| 		assert(parsed, "Invalid JSON data") |  | ||||||
| 		local i = 0 |  | ||||||
| 		while true do |  | ||||||
| 			i = i + 1 |  | ||||||
| 			local item = parsed[i] |  | ||||||
| 			if item == marker then break end |  | ||||||
| 			if type(item) == 'function' and item ~= jsonutil.undefined and item ~= jsonutil.null then |  | ||||||
| 				item(state) |  | ||||||
| 			else |  | ||||||
| 				state:set_value(item) |  | ||||||
| 			end |  | ||||||
| 		end |  | ||||||
| 		if options.initialObject then |  | ||||||
| 			assert(type(state.previous) == 'table', "Initial value not an object or array") |  | ||||||
| 		end |  | ||||||
| 		-- Make sure stack is empty |  | ||||||
| 		assert(state.i == 0, "Unclosed elements present") |  | ||||||
| 		return state.previous |  | ||||||
| 	end |  | ||||||
| 	if options.nothrow then |  | ||||||
| 		return function(data) |  | ||||||
| 			local status, rv = pcall(decoder, data) |  | ||||||
| 			if status then |  | ||||||
| 				return rv |  | ||||||
| 			else |  | ||||||
| 				return nil, rv |  | ||||||
| 			end |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return decoder |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function buildDecoder(mode) |  | ||||||
| 	mode = mode and merge({}, defaultOptions, mode) or defaultOptions |  | ||||||
| 	for _, mod in ipairs(loadedModules) do |  | ||||||
| 		if mod.mergeOptions then |  | ||||||
| 			mod.mergeOptions(mode) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	local ignored = mode.unicodeWhitespace and util.unicode_ignored or util.ascii_ignored |  | ||||||
| 	-- Store 'ignored' in the global options table |  | ||||||
| 	mode.ignored = ignored |  | ||||||
|  |  | ||||||
| 	--local grammar = { |  | ||||||
| 	--	[1] = mode.initialObject and (ignored * (object_type + array_type)) or value_type |  | ||||||
| 	--} |  | ||||||
| 	local lexer |  | ||||||
| 	for _, mod in ipairs(loadedModules) do |  | ||||||
| 		local new_lexer = mod.generateLexer(mode) |  | ||||||
| 		lexer = lexer and lexer + new_lexer or new_lexer |  | ||||||
| 	end |  | ||||||
| 	return generateDecoder(lexer, mode) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Since 'default' is nil, we cannot take map it |  | ||||||
| local defaultDecoder = buildDecoder(json_decode.default) |  | ||||||
| local prebuilt_decoders = {} |  | ||||||
| for _, mode in pairs(modes_defined) do |  | ||||||
| 	if json_decode[mode] ~= nil then |  | ||||||
| 		prebuilt_decoders[json_decode[mode]] = buildDecoder(json_decode[mode]) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| Options: |  | ||||||
| 	number => number decode options |  | ||||||
| 	string => string decode options |  | ||||||
| 	array  => array decode options |  | ||||||
| 	object => object decode options |  | ||||||
| 	initialObject => whether or not to require the initial object to be a table/array |  | ||||||
| 	allowUndefined => whether or not to allow undefined values |  | ||||||
| ]] |  | ||||||
| local function getDecoder(mode) |  | ||||||
| 	mode = mode == true and json_decode.strict or mode or json_decode.default |  | ||||||
| 	local decoder = mode == nil and defaultDecoder or prebuilt_decoders[mode] |  | ||||||
| 	if decoder then |  | ||||||
| 		return decoder |  | ||||||
| 	end |  | ||||||
| 	return buildDecoder(mode) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function decode(data, mode) |  | ||||||
| 	local decoder = getDecoder(mode) |  | ||||||
| 	return decoder(data) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local mt = {} |  | ||||||
| mt.__call = function(self, ...) |  | ||||||
| 	return decode(...) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| json_decode.getDecoder = getDecoder |  | ||||||
| json_decode.decode = decode |  | ||||||
| json_decode.util = util |  | ||||||
| setmetatable(json_decode, mt) |  | ||||||
|  |  | ||||||
| return json_decode |  | ||||||
| @@ -1,190 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local pairs = pairs |  | ||||||
| local type = type |  | ||||||
|  |  | ||||||
| local lpeg = require("lpeg") |  | ||||||
|  |  | ||||||
| local util = require("json.decode.util") |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
|  |  | ||||||
| local rawset = rawset |  | ||||||
|  |  | ||||||
| local assert = assert |  | ||||||
| local tostring = tostring |  | ||||||
|  |  | ||||||
| local error = error |  | ||||||
| local getmetatable = getmetatable |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| 	array = { |  | ||||||
| 		trailingComma = true |  | ||||||
| 	}, |  | ||||||
| 	object = { |  | ||||||
| 		trailingComma = true, |  | ||||||
| 		number = true, |  | ||||||
| 		identifier = true, |  | ||||||
| 		setObjectKey = rawset |  | ||||||
| 	}, |  | ||||||
| 	calls = { |  | ||||||
| 		defs = nil, |  | ||||||
| 		-- By default, do not allow undefined calls to be de-serialized as call objects |  | ||||||
| 		allowUndefined = false |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = { |  | ||||||
| 	default = nil, |  | ||||||
| 	strict = { |  | ||||||
| 		array = { |  | ||||||
| 			trailingComma = false |  | ||||||
| 		}, |  | ||||||
| 		object = { |  | ||||||
| 			trailingComma = false, |  | ||||||
| 			number = false, |  | ||||||
| 			identifier = false |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local function BEGIN_ARRAY(state) |  | ||||||
| 	state:push() |  | ||||||
| 	state:new_array() |  | ||||||
| end |  | ||||||
| local function END_ARRAY(state) |  | ||||||
| 	state:end_array() |  | ||||||
| 	state:pop() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function BEGIN_OBJECT(state) |  | ||||||
| 	state:push() |  | ||||||
| 	state:new_object() |  | ||||||
| end |  | ||||||
| local function END_OBJECT(state) |  | ||||||
| 	state:end_object() |  | ||||||
| 	state:pop() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function END_CALL(state) |  | ||||||
| 	state:end_call() |  | ||||||
| 	state:pop() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function SET_KEY(state) |  | ||||||
| 	state:set_key() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function NEXT_VALUE(state) |  | ||||||
| 	state:put_value() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, true, 'array', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| 	jsonutil.doOptionMerge(options, true, 'object', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| 	jsonutil.doOptionMerge(options, true, 'calls', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local isPattern |  | ||||||
| if lpeg.type then |  | ||||||
| 	function isPattern(value) |  | ||||||
| 		return lpeg.type(value) == 'pattern' |  | ||||||
| 	end |  | ||||||
| else |  | ||||||
| 	local metaAdd = getmetatable(lpeg.P("")).__add |  | ||||||
| 	function isPattern(value) |  | ||||||
| 		return getmetatable(value).__add == metaAdd |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function generateSingleCallLexer(name, func) |  | ||||||
| 	if type(name) ~= 'string' and not isPattern(name) then |  | ||||||
| 		error("Invalid functionCalls name: " .. tostring(name) .. " not a string or LPEG pattern") |  | ||||||
| 	end |  | ||||||
| 	-- Allow boolean or function to match up w/ encoding permissions |  | ||||||
| 	if type(func) ~= 'boolean' and type(func) ~= 'function' then |  | ||||||
| 		error("Invalid functionCalls item: " .. name .. " not a function") |  | ||||||
| 	end |  | ||||||
| 	local function buildCallCapture(name) |  | ||||||
| 		return function(state) |  | ||||||
| 			if func == false then |  | ||||||
| 				error("Function call on '" .. name .. "' not permitted") |  | ||||||
| 			end |  | ||||||
| 			state:push() |  | ||||||
| 			state:new_call(name, func) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	local nameCallCapture |  | ||||||
| 	if type(name) == 'string' then |  | ||||||
| 		nameCallCapture = lpeg.P(name .. "(") * lpeg.Cc(name) / buildCallCapture |  | ||||||
| 	else |  | ||||||
| 		-- Name matcher expected to produce a capture |  | ||||||
| 		nameCallCapture = name * "(" / buildCallCapture |  | ||||||
| 	end |  | ||||||
| 	-- Call func over nameCallCapture and value to permit function receiving name |  | ||||||
| 	return nameCallCapture |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function generateNamedCallLexers(options) |  | ||||||
| 	if not options.calls or not options.calls.defs then |  | ||||||
| 		return |  | ||||||
| 	end |  | ||||||
| 	local callCapture |  | ||||||
| 	for name, func in pairs(options.calls.defs) do |  | ||||||
| 		local newCapture = generateSingleCallLexer(name, func) |  | ||||||
| 		if not callCapture then |  | ||||||
| 			callCapture = newCapture |  | ||||||
| 		else |  | ||||||
| 			callCapture = callCapture + newCapture |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return callCapture |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function generateCallLexer(options) |  | ||||||
| 	local lexer |  | ||||||
| 	local namedCapture = generateNamedCallLexers(options) |  | ||||||
| 	if options.calls and options.calls.allowUndefined then |  | ||||||
| 		lexer = generateSingleCallLexer(lpeg.C(util.identifier), true) |  | ||||||
| 	end |  | ||||||
| 	if namedCapture then |  | ||||||
| 		lexer = lexer and lexer + namedCapture or namedCapture |  | ||||||
| 	end |  | ||||||
| 	if lexer then |  | ||||||
| 		lexer = lexer + lpeg.P(")") * lpeg.Cc(END_CALL) |  | ||||||
| 	end |  | ||||||
| 	return lexer |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function generateLexer(options) |  | ||||||
| 	local ignored = options.ignored |  | ||||||
| 	local array_options, object_options = options.array, options.object |  | ||||||
| 	local lexer = |  | ||||||
| 		lpeg.P("[") * lpeg.Cc(BEGIN_ARRAY) |  | ||||||
| 		+ lpeg.P("]") * lpeg.Cc(END_ARRAY) |  | ||||||
| 		+ lpeg.P("{") * lpeg.Cc(BEGIN_OBJECT) |  | ||||||
| 		+ lpeg.P("}") * lpeg.Cc(END_OBJECT) |  | ||||||
| 		+ lpeg.P(":") * lpeg.Cc(SET_KEY) |  | ||||||
| 		+ lpeg.P(",") * lpeg.Cc(NEXT_VALUE) |  | ||||||
| 	if object_options.identifier then |  | ||||||
| 		-- Add identifier match w/ validation check that it is in key |  | ||||||
| 		lexer = lexer + lpeg.C(util.identifier) * ignored * lpeg.P(":") * lpeg.Cc(SET_KEY) |  | ||||||
| 	end |  | ||||||
| 	local callLexers = generateCallLexer(options) |  | ||||||
| 	if callLexers then |  | ||||||
| 		lexer = lexer + callLexers |  | ||||||
| 	end |  | ||||||
| 	return lexer |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local composite = { |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	generateLexer = generateLexer |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return composite |  | ||||||
| @@ -1,100 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local lpeg = require("lpeg") |  | ||||||
| local tonumber = tonumber |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local merge = jsonutil.merge |  | ||||||
| local util = require("json.decode.util") |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local digit  = lpeg.R("09") |  | ||||||
| local digits = digit^1 |  | ||||||
|  |  | ||||||
| -- Illegal octal declaration |  | ||||||
| local illegal_octal_detect = #(lpeg.P('0') * digits) * util.denied("Octal numbers") |  | ||||||
|  |  | ||||||
| local int = (lpeg.P('-') + 0) * (lpeg.R("19") * digits + illegal_octal_detect + digit) |  | ||||||
|  |  | ||||||
| local frac = lpeg.P('.') * digits |  | ||||||
|  |  | ||||||
| local exp = lpeg.S("Ee") * (lpeg.S("-+") + 0) * digits |  | ||||||
|  |  | ||||||
| local nan = lpeg.S("Nn") * lpeg.S("Aa") * lpeg.S("Nn") |  | ||||||
| local inf = lpeg.S("Ii") * lpeg.P("nfinity") |  | ||||||
| local ninf = lpeg.P('-') * lpeg.S("Ii") * lpeg.P("nfinity") |  | ||||||
| local hex = (lpeg.P("0x") + lpeg.P("0X")) * lpeg.R("09","AF","af")^1 |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| 	nan = true, |  | ||||||
| 	inf = true, |  | ||||||
| 	frac = true, |  | ||||||
| 	exp = true, |  | ||||||
| 	hex = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = {} |  | ||||||
|  |  | ||||||
| modeOptions.strict = { |  | ||||||
| 	nan = false, |  | ||||||
| 	inf = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local nan_value = 0/0 |  | ||||||
| local inf_value = 1/0 |  | ||||||
| local ninf_value = -1/0 |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	Options: configuration options for number rules |  | ||||||
| 		nan: match NaN |  | ||||||
| 		inf: match Infinity |  | ||||||
| 	   frac: match fraction portion (.0) |  | ||||||
| 	    exp: match exponent portion  (e1) |  | ||||||
| 	DEFAULT: nan, inf, frac, exp |  | ||||||
| ]] |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'number', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function generateLexer(options) |  | ||||||
| 	options = options.number |  | ||||||
| 	local ret = int |  | ||||||
| 	if options.frac then |  | ||||||
| 		ret = ret * (frac + 0) |  | ||||||
| 	else |  | ||||||
| 		ret = ret * (#frac * util.denied("Fractions", "number.frac") + 0) |  | ||||||
| 	end |  | ||||||
| 	if options.exp then |  | ||||||
| 		ret = ret * (exp + 0) |  | ||||||
| 	else |  | ||||||
| 		ret = ret * (#exp * util.denied("Exponents", "number.exp") + 0) |  | ||||||
| 	end |  | ||||||
| 	if options.hex then |  | ||||||
| 		ret = hex + ret |  | ||||||
| 	else |  | ||||||
| 		ret = #hex * util.denied("Hexadecimal", "number.hex") + ret |  | ||||||
| 	end |  | ||||||
| 	-- Capture number now |  | ||||||
| 	ret = ret / tonumber |  | ||||||
| 	if options.nan then |  | ||||||
| 		ret = ret + nan / function() return nan_value end |  | ||||||
| 	else |  | ||||||
| 		ret = ret + #nan * util.denied("NaN", "number.nan") |  | ||||||
| 	end |  | ||||||
| 	if options.inf then |  | ||||||
| 		ret = ret + ninf / function() return ninf_value end + inf / function() return inf_value end |  | ||||||
| 	else |  | ||||||
| 		ret = ret + (#ninf + #inf) * util.denied("+/-Inf", "number.inf") |  | ||||||
| 	end |  | ||||||
| 	return ret |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local number = { |  | ||||||
| 	int = int, |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	generateLexer = generateLexer |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return number |  | ||||||
| @@ -1,62 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local lpeg = require("lpeg") |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local merge = jsonutil.merge |  | ||||||
| local util = require("json.decode.util") |  | ||||||
|  |  | ||||||
| -- Container module for other JavaScript types (bool, null, undefined) |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| -- For null and undefined, use the util.null value to preserve null-ness |  | ||||||
| local booleanCapture = |  | ||||||
| 	lpeg.P("true") * lpeg.Cc(true) |  | ||||||
| 	+ lpeg.P("false") * lpeg.Cc(false) |  | ||||||
|  |  | ||||||
| local nullCapture = lpeg.P("null") |  | ||||||
| local undefinedCapture = lpeg.P("undefined") |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| 	allowUndefined = true, |  | ||||||
| 	null = jsonutil.null, |  | ||||||
| 	undefined = jsonutil.undefined |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = {} |  | ||||||
|  |  | ||||||
| modeOptions.simple = { |  | ||||||
| 	null = false,     -- Mapped to nil |  | ||||||
| 	undefined = false -- Mapped to nil |  | ||||||
| } |  | ||||||
| modeOptions.strict = { |  | ||||||
| 	allowUndefined = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'others', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function generateLexer(options) |  | ||||||
| 	-- The 'or nil' clause allows false to map to a nil value since 'nil' cannot be merged |  | ||||||
| 	options = options.others |  | ||||||
| 	local valueCapture = ( |  | ||||||
| 		booleanCapture |  | ||||||
| 		+ nullCapture * lpeg.Cc(options.null or nil) |  | ||||||
| 	) |  | ||||||
| 	if options.allowUndefined then |  | ||||||
| 		valueCapture = valueCapture + undefinedCapture * lpeg.Cc(options.undefined or nil) |  | ||||||
| 	else |  | ||||||
| 		valueCapture = valueCapture + #undefinedCapture * util.denied("undefined", "others.allowUndefined") |  | ||||||
| 	end |  | ||||||
| 	return valueCapture |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local others = { |  | ||||||
| 	mergeOptions = mergeOptions,	 |  | ||||||
| 	generateLexer = generateLexer |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return others |  | ||||||
| @@ -1,189 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
|  |  | ||||||
| local setmetatable = setmetatable |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local assert = assert |  | ||||||
| local type = type |  | ||||||
| local next = next |  | ||||||
| local unpack = require("table").unpack or unpack |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local state_ops = {} |  | ||||||
| local state_mt = { |  | ||||||
| 	__index = state_ops |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function state_ops.pop(self) |  | ||||||
| 	self.previous_set = true |  | ||||||
| 	self.previous = self.active |  | ||||||
| 	local i = self.i |  | ||||||
| 	-- Load in this array into the active item |  | ||||||
| 	self.active = self.stack[i] |  | ||||||
| 	self.active_state = self.state_stack[i] |  | ||||||
| 	self.active_key = self.key_stack[i] |  | ||||||
| 	self.stack[i] = nil |  | ||||||
| 	self.state_stack[i] = nil |  | ||||||
| 	self.key_stack[i] = nil |  | ||||||
|  |  | ||||||
| 	self.i = i - 1 |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.push(self) |  | ||||||
| 	local i = self.i + 1 |  | ||||||
| 	self.i = i |  | ||||||
| 	 |  | ||||||
| 	self.stack[i] = self.active |  | ||||||
| 	self.state_stack[i] = self.active_state |  | ||||||
| 	self.key_stack[i] = self.active_key |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.put_object_value(self, trailing) |  | ||||||
| 	local object_options = self.options.object |  | ||||||
| 	if trailing and object_options.trailingComma then |  | ||||||
| 		if not self.active_key then |  | ||||||
| 			return |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	assert(self.active_key, "Missing key value") |  | ||||||
| 	object_options.setObjectKey(self.active, self.active_key, self:grab_value()) |  | ||||||
| 	self.active_key = nil |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.put_array_value(self, trailing) |  | ||||||
| 	-- Safety check |  | ||||||
| 	if trailing and not self.previous_set and self.options.array.trailingComma then |  | ||||||
| 		return |  | ||||||
| 	end |  | ||||||
| 	local new_index = self.active_state + 1 |  | ||||||
| 	self.active_state = new_index |  | ||||||
| 	self.active[new_index] = self:grab_value() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.put_value(self, trailing) |  | ||||||
| 	if self.active_state == 'object' then |  | ||||||
| 		self:put_object_value(trailing) |  | ||||||
| 	else |  | ||||||
| 		self:put_array_value(trailing) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.new_array(self) |  | ||||||
| 	local new_array = {} |  | ||||||
| 	if jsonutil.InitArray then |  | ||||||
| 		new_array = jsonutil.InitArray(new_array) or new_array |  | ||||||
| 	end |  | ||||||
| 	self.active = new_array |  | ||||||
| 	self.active_state = 0 |  | ||||||
| 	self.active_key = nil |  | ||||||
| 	self:unset_value() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.end_array(self) |  | ||||||
| 	if self.previous_set or self.active_state ~= 0 then |  | ||||||
| 		-- Not an empty array |  | ||||||
| 		self:put_value(true) |  | ||||||
| 	end |  | ||||||
| 	if self.active_state ~= #self.active then |  | ||||||
| 		-- Store the length in |  | ||||||
| 		self.active.n = self.active_state |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.new_object(self) |  | ||||||
| 	local new_object = {} |  | ||||||
| 	self.active = new_object |  | ||||||
| 	self.active_state = 'object' |  | ||||||
| 	self.active_key = nil |  | ||||||
| 	self:unset_value() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.end_object(self) |  | ||||||
| 	if self.previous_set or next(self.active) then |  | ||||||
| 		-- Not an empty object |  | ||||||
| 		self:put_value(true) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.new_call(self, name, func) |  | ||||||
| 	-- TODO setup properly |  | ||||||
| 	local new_call = {} |  | ||||||
| 	new_call.name = name |  | ||||||
| 	new_call.func = func |  | ||||||
| 	self.active = new_call |  | ||||||
| 	self.active_state = 0 |  | ||||||
| 	self.active_key = nil |  | ||||||
| 	self:unset_value() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.end_call(self) |  | ||||||
| 	if self.previous_set or self.active_state ~= 0 then |  | ||||||
| 		-- Not an empty array |  | ||||||
| 		self:put_value(true) |  | ||||||
| 	end |  | ||||||
| 	if self.active_state ~= #self.active then |  | ||||||
| 		-- Store the length in |  | ||||||
| 		self.active.n = self.active_state |  | ||||||
| 	end |  | ||||||
| 	local func = self.active.func |  | ||||||
| 	if func == true then |  | ||||||
| 		func = jsonutil.buildCall |  | ||||||
| 	end |  | ||||||
| 	self.active = func(self.active.name, unpack(self.active, 1, self.active.n or #self.active)) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| function state_ops.unset_value(self) |  | ||||||
| 	self.previous_set = false |  | ||||||
| 	self.previous = nil |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.grab_value(self) |  | ||||||
| 	assert(self.previous_set, "Previous value not set") |  | ||||||
| 	self.previous_set = false |  | ||||||
| 	return self.previous |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.set_value(self, value) |  | ||||||
| 	assert(not self.previous_set, "Value set when one already in slot") |  | ||||||
| 	self.previous_set = true |  | ||||||
| 	self.previous = value |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function state_ops.set_key(self) |  | ||||||
| 	assert(self.active_state == 'object', "Cannot set key on array") |  | ||||||
| 	local value = self:grab_value() |  | ||||||
| 	local value_type = type(value) |  | ||||||
| 	if self.options.object.number then |  | ||||||
| 		assert(value_type == 'string' or value_type == 'number', "As configured, a key must be a number or string")  |  | ||||||
| 	else |  | ||||||
| 		assert(value_type == 'string', "As configured, a key must be a string") |  | ||||||
| 	end |  | ||||||
| 	self.active_key = value |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function create(options) |  | ||||||
| 	local ret = { |  | ||||||
| 		options = options, |  | ||||||
| 		stack = {}, |  | ||||||
| 		state_stack = {}, |  | ||||||
| 		key_stack = {}, |  | ||||||
| 		i = 0, |  | ||||||
| 		active = nil, |  | ||||||
| 		active_key = nil, |  | ||||||
| 		previous = nil, |  | ||||||
| 		active_state = nil |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
| 	return setmetatable(ret, state_mt) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local state = { |  | ||||||
| 	create = create |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return state |  | ||||||
| @@ -1,133 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local lpeg = require("lpeg") |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local util = require("json.decode.util") |  | ||||||
| local merge = jsonutil.merge |  | ||||||
|  |  | ||||||
| local tonumber = tonumber |  | ||||||
| local string_char = require("string").char |  | ||||||
| local floor = require("math").floor |  | ||||||
| local table_concat = require("table").concat |  | ||||||
|  |  | ||||||
| local error = error |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local function get_error(item) |  | ||||||
| 	local fmt_string = item .. " in string [%q] @ %i:%i" |  | ||||||
| 	return lpeg.P(function(data, index) |  | ||||||
| 		local line, line_index, bad_char, last_line = util.get_invalid_character_info(data, index) |  | ||||||
| 		local err = fmt_string:format(bad_char, line, line_index) |  | ||||||
| 		error(err) |  | ||||||
| 	end) * 1 |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local bad_unicode   = get_error("Illegal unicode escape") |  | ||||||
| local bad_hex       = get_error("Illegal hex escape") |  | ||||||
| local bad_character = get_error("Illegal character") |  | ||||||
| local bad_escape    = get_error("Illegal escape") |  | ||||||
|  |  | ||||||
| local knownReplacements = { |  | ||||||
| 	["'"] = "'", |  | ||||||
| 	['"'] = '"', |  | ||||||
| 	['\\'] = '\\', |  | ||||||
| 	['/'] = '/', |  | ||||||
| 	b = '\b', |  | ||||||
| 	f = '\f', |  | ||||||
| 	n = '\n', |  | ||||||
| 	r = '\r', |  | ||||||
| 	t = '\t', |  | ||||||
| 	v = '\v', |  | ||||||
| 	z = '\z' |  | ||||||
| } |  | ||||||
|  |  | ||||||
| -- according to the table at http://da.wikipedia.org/wiki/UTF-8 |  | ||||||
| local function utf8DecodeUnicode(code1, code2) |  | ||||||
| 	code1, code2 = tonumber(code1, 16), tonumber(code2, 16) |  | ||||||
| 	if code1 == 0 and code2 < 0x80 then |  | ||||||
| 		return string_char(code2) |  | ||||||
| 	end |  | ||||||
| 	if code1 < 0x08 then |  | ||||||
| 		return string_char( |  | ||||||
| 			0xC0 + code1 * 4 + floor(code2 / 64), |  | ||||||
| 			0x80 + code2 % 64) |  | ||||||
| 	end |  | ||||||
| 	return string_char( |  | ||||||
| 		0xE0 + floor(code1 / 16), |  | ||||||
| 		0x80 + (code1 % 16) * 4 + floor(code2 / 64), |  | ||||||
| 		0x80 + code2 % 64) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function decodeX(code) |  | ||||||
| 	code = tonumber(code, 16) |  | ||||||
| 	return string_char(code) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local doSimpleSub = lpeg.C(lpeg.S("'\"\\/bfnrtvz")) / knownReplacements |  | ||||||
| local doUniSub = lpeg.P('u') * (lpeg.C(util.hexpair) * lpeg.C(util.hexpair) + bad_unicode) |  | ||||||
| local doXSub = lpeg.P('x') * (lpeg.C(util.hexpair) + bad_hex) |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| 	badChars = '', |  | ||||||
| 	additionalEscapes = false, -- disallow untranslated escapes |  | ||||||
| 	escapeCheck = #lpeg.S('bfnrtv/\\"xu\'z'), -- no check on valid characters |  | ||||||
| 	decodeUnicode = utf8DecodeUnicode, |  | ||||||
| 	strict_quotes = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = {} |  | ||||||
|  |  | ||||||
| modeOptions.strict = { |  | ||||||
| 	badChars = '\b\f\n\r\t\v', |  | ||||||
| 	additionalEscapes = false, -- no additional escapes |  | ||||||
| 	escapeCheck = #lpeg.S('bfnrtv/\\"u'), --only these chars are allowed to be escaped |  | ||||||
| 	strict_quotes = true |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'strings', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function buildCaptureString(quote, badChars, escapeMatch) |  | ||||||
| 	local captureChar = (1 - lpeg.S("\\" .. badChars .. quote)) + (lpeg.P("\\") / "" * escapeMatch) |  | ||||||
| 	-- During error, force end |  | ||||||
| 	local captureString = captureChar^0 + (-#lpeg.P(quote) * bad_character + -1) |  | ||||||
| 	return lpeg.P(quote) * lpeg.Cs(captureString) * lpeg.P(quote) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function generateLexer(options) |  | ||||||
| 	options = options.strings |  | ||||||
| 	local quotes = { '"' } |  | ||||||
| 	if not options.strict_quotes then |  | ||||||
| 		quotes[#quotes + 1] = "'" |  | ||||||
| 	end |  | ||||||
| 	local escapeMatch = doSimpleSub |  | ||||||
| 	escapeMatch = escapeMatch + doXSub / decodeX |  | ||||||
| 	escapeMatch = escapeMatch + doUniSub / options.decodeUnicode |  | ||||||
| 	if options.escapeCheck then |  | ||||||
| 		escapeMatch = options.escapeCheck * escapeMatch + bad_escape |  | ||||||
| 	end |  | ||||||
| 	if options.additionalEscapes then |  | ||||||
| 		escapeMatch = options.additionalEscapes + escapeMatch |  | ||||||
| 	end |  | ||||||
| 	local captureString |  | ||||||
| 	for i = 1, #quotes do |  | ||||||
| 		local cap = buildCaptureString(quotes[i], options.badChars, escapeMatch) |  | ||||||
| 		if captureString == nil then |  | ||||||
| 			captureString = cap |  | ||||||
| 		else |  | ||||||
| 			captureString = captureString + cap |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return captureString |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local strings = { |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	generateLexer = generateLexer |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return strings |  | ||||||
| @@ -1,121 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local lpeg = require("lpeg") |  | ||||||
| local select = select |  | ||||||
| local pairs, ipairs = pairs, ipairs |  | ||||||
| local tonumber = tonumber |  | ||||||
| local string_char = require("string").char |  | ||||||
| local rawset = rawset |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
|  |  | ||||||
| local error = error |  | ||||||
| local setmetatable = setmetatable |  | ||||||
|  |  | ||||||
| local table_concat = require("table").concat |  | ||||||
|  |  | ||||||
| local merge = require("json.util").merge |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local function get_invalid_character_info(input, index) |  | ||||||
| 	local parsed = input:sub(1, index) |  | ||||||
| 	local bad_character = input:sub(index, index) |  | ||||||
| 	local _, line_number = parsed:gsub('\n',{}) |  | ||||||
| 	local last_line = parsed:match("\n([^\n]+.)$") or parsed |  | ||||||
| 	return line_number, #last_line, bad_character, last_line |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function build_report(msg) |  | ||||||
| 	local fmt = msg:gsub("%%", "%%%%") .. " @ character: %i %i:%i [%s] line:\n%s" |  | ||||||
| 	return lpeg.P(function(data, pos) |  | ||||||
| 		local line, line_index, bad_char, last_line = get_invalid_character_info(data, pos) |  | ||||||
| 		local text = fmt:format(pos, line, line_index, bad_char, last_line) |  | ||||||
| 		error(text) |  | ||||||
| 	end) * 1 |  | ||||||
| end |  | ||||||
| local function unexpected() |  | ||||||
| 	local msg = "unexpected character" |  | ||||||
| 	return build_report(msg) |  | ||||||
| end |  | ||||||
| local function denied(item, option) |  | ||||||
| 	local msg |  | ||||||
| 	if option then |  | ||||||
| 		msg = ("'%s' denied by option set '%s'"):format(item, option) |  | ||||||
| 	else |  | ||||||
| 		msg = ("'%s' denied"):format(item) |  | ||||||
| 	end |  | ||||||
| 	return build_report(msg) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- 09, 0A, 0B, 0C, 0D, 20 |  | ||||||
| local ascii_space = lpeg.S("\t\n\v\f\r ") |  | ||||||
| local unicode_space |  | ||||||
| do |  | ||||||
| 	local chr = string_char |  | ||||||
| 	local u_space = ascii_space |  | ||||||
| 	-- \u0085 \u00A0 |  | ||||||
| 	u_space = u_space + lpeg.P(chr(0xC2)) * lpeg.S(chr(0x85) .. chr(0xA0)) |  | ||||||
| 	-- \u1680 \u180E |  | ||||||
| 	u_space = u_space + lpeg.P(chr(0xE1)) * (lpeg.P(chr(0x9A, 0x80)) + chr(0xA0, 0x8E)) |  | ||||||
| 	-- \u2000 - \u200A, also 200B |  | ||||||
| 	local spacing_end = "" |  | ||||||
| 	for i = 0x80,0x8b do |  | ||||||
| 		spacing_end = spacing_end .. chr(i) |  | ||||||
| 	end |  | ||||||
| 	-- \u2028 \u2029 \u202F |  | ||||||
| 	spacing_end = spacing_end .. chr(0xA8) .. chr(0xA9) .. chr(0xAF) |  | ||||||
| 	u_space = u_space + lpeg.P(chr(0xE2, 0x80)) * lpeg.S(spacing_end) |  | ||||||
| 	-- \u205F |  | ||||||
| 	u_space = u_space + lpeg.P(chr(0xE2, 0x81, 0x9F)) |  | ||||||
| 	-- \u3000 |  | ||||||
| 	u_space = u_space + lpeg.P(chr(0xE3, 0x80, 0x80)) |  | ||||||
| 	-- BOM \uFEFF |  | ||||||
| 	u_space = u_space + lpeg.P(chr(0xEF, 0xBB, 0xBF)) |  | ||||||
| 	unicode_space = u_space |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local identifier = lpeg.R("AZ","az","__") * lpeg.R("AZ","az", "__", "09") ^0 |  | ||||||
|  |  | ||||||
| local hex = lpeg.R("09","AF","af") |  | ||||||
| local hexpair = hex * hex |  | ||||||
|  |  | ||||||
| local comments = { |  | ||||||
| 	cpp = lpeg.P("//") * (1 - lpeg.P("\n"))^0 * lpeg.P("\n"), |  | ||||||
| 	c = lpeg.P("/*") * (1 - lpeg.P("*/"))^0 * lpeg.P("*/") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local comment = comments.cpp + comments.c |  | ||||||
|  |  | ||||||
| local ascii_ignored = (ascii_space + comment)^0 |  | ||||||
|  |  | ||||||
| local unicode_ignored = (unicode_space + comment)^0 |  | ||||||
|  |  | ||||||
| -- Parse the lpeg version skipping patch-values |  | ||||||
| -- LPEG <= 0.7 have no version value... so 0.7 is value |  | ||||||
| local DecimalLpegVersion = lpeg.version and tonumber(lpeg.version():match("^(%d+%.%d+)")) or 0.7 |  | ||||||
|  |  | ||||||
| local function setObjectKeyForceNumber(t, key, value) |  | ||||||
| 	key = tonumber(key) or key |  | ||||||
| 	return rawset(t, key, value) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local util = { |  | ||||||
| 	unexpected = unexpected, |  | ||||||
| 	denied = denied, |  | ||||||
| 	ascii_space = ascii_space, |  | ||||||
| 	unicode_space = unicode_space, |  | ||||||
| 	identifier = identifier, |  | ||||||
| 	hex = hex, |  | ||||||
| 	hexpair = hexpair, |  | ||||||
| 	comments = comments, |  | ||||||
| 	comment = comment, |  | ||||||
| 	ascii_ignored = ascii_ignored, |  | ||||||
| 	unicode_ignored = unicode_ignored, |  | ||||||
| 	DecimalLpegVersion = DecimalLpegVersion, |  | ||||||
| 	get_invalid_character_info = get_invalid_character_info, |  | ||||||
| 	setObjectKeyForceNumber = setObjectKeyForceNumber |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return util |  | ||||||
| @@ -1,161 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local type = type |  | ||||||
| local assert, error = assert, error |  | ||||||
| local getmetatable, setmetatable = getmetatable, setmetatable |  | ||||||
|  |  | ||||||
| local ipairs, pairs = ipairs, pairs |  | ||||||
| local require = require |  | ||||||
|  |  | ||||||
| local output = require("json.encode.output") |  | ||||||
|  |  | ||||||
| local util = require("json.util") |  | ||||||
| local util_merge, isCall = util.merge, util.isCall |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	List of encoding modules to load. |  | ||||||
| 	Loaded in sequence such that earlier encoders get priority when |  | ||||||
| 	duplicate type-handlers exist. |  | ||||||
| ]] |  | ||||||
| local modulesToLoad = { |  | ||||||
| 	"strings", |  | ||||||
| 	"number", |  | ||||||
| 	"calls", |  | ||||||
| 	"others", |  | ||||||
| 	"array", |  | ||||||
| 	"object" |  | ||||||
| } |  | ||||||
| -- Modules that have been loaded |  | ||||||
| local loadedModules = {} |  | ||||||
|  |  | ||||||
| local json_encode = {} |  | ||||||
|  |  | ||||||
| -- Configuration bases for client apps |  | ||||||
| local modes_defined = { "default", "strict" } |  | ||||||
|  |  | ||||||
| json_encode.default = {} |  | ||||||
| json_encode.strict = { |  | ||||||
| 	initialObject = true -- Require an object at the root |  | ||||||
| } |  | ||||||
|  |  | ||||||
| -- For each module, load it and its defaults |  | ||||||
| for _,name in ipairs(modulesToLoad) do |  | ||||||
| 	local mod = require("json.encode." .. name) |  | ||||||
| 	if mod.mergeOptions then |  | ||||||
| 		for _, mode in pairs(modes_defined) do |  | ||||||
| 			mod.mergeOptions(json_encode[mode], mode) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	loadedModules[name] = mod |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- NOTE: Nested not found, so assume unsupported until use case arises |  | ||||||
| local function flattenOutput(out, value) |  | ||||||
|     assert(type(value) ~= 'table') |  | ||||||
| 	out = out or {} |  | ||||||
|     out[#out + 1] = value |  | ||||||
|     return out |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Prepares the encoding map from the already provided modules and new config |  | ||||||
| local function prepareEncodeMap(options) |  | ||||||
| 	local map = {} |  | ||||||
| 	for _, name in ipairs(modulesToLoad) do |  | ||||||
| 		local encodermap = loadedModules[name].getEncoder(options[name]) |  | ||||||
| 		for valueType, encoderSet in pairs(encodermap) do |  | ||||||
| 			map[valueType] = flattenOutput(map[valueType], encoderSet) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return map |  | ||||||
| end |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	Encode a value with a given encoding map and state |  | ||||||
| ]] |  | ||||||
| local function encodeWithMap(value, map, state, isObjectKey) |  | ||||||
| 	local t = type(value) |  | ||||||
| 	local encoderList = assert(map[t], "Failed to encode value, unhandled type: " .. t) |  | ||||||
| 	for _, encoder in ipairs(encoderList) do |  | ||||||
| 		local ret = encoder(value, state, isObjectKey) |  | ||||||
| 		if false ~= ret then |  | ||||||
| 			return ret |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	error("Failed to encode value, encoders for " .. t .. " deny encoding") |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function getBaseEncoder(options) |  | ||||||
| 	local encoderMap = prepareEncodeMap(options) |  | ||||||
| 	if options.preProcess then |  | ||||||
| 		local preProcess = options.preProcess |  | ||||||
| 		return function(value, state, isObjectKey) |  | ||||||
| 			local ret = preProcess(value, isObjectKey or false) |  | ||||||
| 			if nil ~= ret then |  | ||||||
| 				value = ret |  | ||||||
| 			end |  | ||||||
| 			return encodeWithMap(value, encoderMap, state) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return function(value, state, isObjectKey) |  | ||||||
| 		return encodeWithMap(value, encoderMap, state) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
| --[[ |  | ||||||
| 	Retreive an initial encoder instance based on provided options |  | ||||||
| 	the initial encoder is responsible for initializing state |  | ||||||
| 		State has at least these values configured: encode, check_unique, already_encoded |  | ||||||
| ]] |  | ||||||
| function json_encode.getEncoder(options) |  | ||||||
| 	options = options and util_merge({}, json_encode.default, options) or json_encode.default |  | ||||||
| 	local encode = getBaseEncoder(options) |  | ||||||
|  |  | ||||||
| 	local function initialEncode(value) |  | ||||||
| 		if options.initialObject then |  | ||||||
| 			local errorMessage = "Invalid arguments: expects a JSON Object or Array at the root" |  | ||||||
| 			assert(type(value) == 'table' and not isCall(value, options), errorMessage) |  | ||||||
| 		end |  | ||||||
|  |  | ||||||
| 		local alreadyEncoded = {} |  | ||||||
| 		local function check_unique(value) |  | ||||||
| 			assert(not alreadyEncoded[value], "Recursive encoding of value") |  | ||||||
| 			alreadyEncoded[value] = true |  | ||||||
| 		end |  | ||||||
|  |  | ||||||
| 		local outputEncoder = options.output and options.output() or output.getDefault() |  | ||||||
| 		local state = { |  | ||||||
| 			encode = encode, |  | ||||||
| 			check_unique = check_unique, |  | ||||||
| 			already_encoded = alreadyEncoded, -- To unmark encoding when moving up stack |  | ||||||
| 			outputEncoder = outputEncoder |  | ||||||
| 		} |  | ||||||
| 		local ret = encode(value, state) |  | ||||||
| 		if nil ~= ret then |  | ||||||
| 			return outputEncoder.simple and outputEncoder.simple(ret) or ret |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return initialEncode |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- CONSTRUCT STATE WITH FOLLOWING (at least) |  | ||||||
| --[[ |  | ||||||
| 	encoder |  | ||||||
| 	check_unique -- used by inner encoders to make sure value is unique |  | ||||||
| 	already_encoded -- used to unmark a value as unique |  | ||||||
| ]] |  | ||||||
| function json_encode.encode(data, options) |  | ||||||
| 	return json_encode.getEncoder(options)(data) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local mt = {} |  | ||||||
| mt.__call = function(self, ...) |  | ||||||
| 	return json_encode.encode(...) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| setmetatable(json_encode, mt) |  | ||||||
|  |  | ||||||
| return json_encode |  | ||||||
| @@ -1,110 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
|  |  | ||||||
| local type = type |  | ||||||
| local pairs = pairs |  | ||||||
| local assert = assert |  | ||||||
|  |  | ||||||
| local table = require("table") |  | ||||||
| local math = require("math") |  | ||||||
| local table_concat = table.concat |  | ||||||
| local math_floor, math_modf = math.floor, math.modf |  | ||||||
|  |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local util_IsArray = jsonutil.IsArray |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| 	isArray = util_IsArray |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = {} |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'array', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	Utility function to determine whether a table is an array or not. |  | ||||||
| 	Criteria for it being an array: |  | ||||||
| 		* ExternalIsArray returns true (or false directly reports not-array) |  | ||||||
| 		* If the table has an 'n' value that is an integer >= 1 then it |  | ||||||
| 		  is an array... may result in false positives (should check some values |  | ||||||
| 		  before it) |  | ||||||
| 		* It is a contiguous list of values with zero string-based keys |  | ||||||
| ]] |  | ||||||
| local function isArray(val, options) |  | ||||||
| 	local externalIsArray = options and options.isArray |  | ||||||
|  |  | ||||||
| 	if externalIsArray then |  | ||||||
| 		local ret = externalIsArray(val) |  | ||||||
| 		if ret == true or ret == false then |  | ||||||
| 			return ret |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	-- Use the 'n' element if it's a number |  | ||||||
| 	if type(val.n) == 'number' and math_floor(val.n) == val.n and val.n >= 1 then |  | ||||||
| 		return true |  | ||||||
| 	end |  | ||||||
| 	local len = #val |  | ||||||
| 	for k,v in pairs(val) do |  | ||||||
| 		if type(k) ~= 'number' then |  | ||||||
| 			return false |  | ||||||
| 		end |  | ||||||
| 		local _, decim = math_modf(k) |  | ||||||
| 		if not (decim == 0 and 1<=k) then |  | ||||||
| 			return false |  | ||||||
| 		end |  | ||||||
| 		if k > len then -- Use Lua's length as absolute determiner |  | ||||||
| 			return false |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	return true |  | ||||||
| end |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	Cleanup function to unmark a value as in the encoding process and return |  | ||||||
| 	trailing results |  | ||||||
| ]] |  | ||||||
| local function unmarkAfterEncode(tab, state, ...) |  | ||||||
| 	state.already_encoded[tab] = nil |  | ||||||
| 	return ... |  | ||||||
| end |  | ||||||
| local function getEncoder(options) |  | ||||||
| 	options = options and jsonutil.merge({}, defaultOptions, options) or defaultOptions |  | ||||||
| 	local function encodeArray(tab,  state) |  | ||||||
| 		if not isArray(tab, options) then |  | ||||||
| 			return false |  | ||||||
| 		end |  | ||||||
| 		-- Make sure this value hasn't been encoded yet |  | ||||||
| 		state.check_unique(tab) |  | ||||||
| 		local encode = state.encode |  | ||||||
| 		local compositeEncoder = state.outputEncoder.composite |  | ||||||
| 		local valueEncoder = [[ |  | ||||||
| 		for i = 1, (composite.n or #composite) do |  | ||||||
| 			local val = composite[i] |  | ||||||
| 			PUTINNER(i ~= 1) |  | ||||||
| 			val = encode(val, state) |  | ||||||
| 			val = val or '' |  | ||||||
| 			if val then |  | ||||||
| 				PUTVALUE(val) |  | ||||||
| 			end |  | ||||||
| 		end |  | ||||||
| 		]] |  | ||||||
| 		return unmarkAfterEncode(tab, state, compositeEncoder(valueEncoder, '[', ']', ',', tab, encode, state)) |  | ||||||
| 	end |  | ||||||
| 	return { table = encodeArray } |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local array = { |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	isArray = isArray, |  | ||||||
| 	getEncoder = getEncoder |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return array |  | ||||||
| @@ -1,68 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local table = require("table") |  | ||||||
| local table_concat = table.concat |  | ||||||
|  |  | ||||||
| local select = select |  | ||||||
| local getmetatable, setmetatable = getmetatable, setmetatable |  | ||||||
| local assert = assert |  | ||||||
|  |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
|  |  | ||||||
| local isCall, decodeCall = jsonutil.isCall, jsonutil.decodeCall |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| -- No real default-option handling needed... |  | ||||||
| local modeOptions = {} |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'calls', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	Encodes 'value' as a function call |  | ||||||
| 	Must have parameters in the 'callData' field of the metatable |  | ||||||
| 		name == name of the function call |  | ||||||
| 		parameters == array of parameters to encode |  | ||||||
| ]] |  | ||||||
| local function getEncoder(options) |  | ||||||
| 	options = options and jsonutil.merge({}, defaultOptions, options) or defaultOptions |  | ||||||
| 	local function encodeCall(value, state) |  | ||||||
| 		if not isCall(value) then |  | ||||||
| 			return false |  | ||||||
| 		end |  | ||||||
| 		local encode = state.encode |  | ||||||
| 		local name, params = decodeCall(value) |  | ||||||
| 		local compositeEncoder = state.outputEncoder.composite |  | ||||||
| 		local valueEncoder = [[ |  | ||||||
| 		for i = 1, (composite.n or #composite) do |  | ||||||
| 			local val = composite[i] |  | ||||||
| 			PUTINNER(i ~= 1) |  | ||||||
| 			val = encode(val, state) |  | ||||||
| 			val = val or '' |  | ||||||
| 			if val then |  | ||||||
| 				PUTVALUE(val) |  | ||||||
| 			end |  | ||||||
| 		end |  | ||||||
| 		]] |  | ||||||
| 		return compositeEncoder(valueEncoder, name .. '(', ')', ',', params, encode, state) |  | ||||||
| 	end |  | ||||||
| 	return { |  | ||||||
| 		table = encodeCall, |  | ||||||
| 		['function'] = encodeCall |  | ||||||
| 	} |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local calls = { |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	getEncoder = getEncoder |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return calls |  | ||||||
| @@ -1,58 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local tostring = tostring |  | ||||||
| local assert = assert |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local huge = require("math").huge |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| 	nan = true, |  | ||||||
| 	inf = true |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = {} |  | ||||||
| modeOptions.strict = { |  | ||||||
| 	nan = false, |  | ||||||
| 	inf = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'number', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local function encodeNumber(number, options) |  | ||||||
| 	if number ~= number then |  | ||||||
| 		assert(options.nan, "Invalid number: NaN not enabled") |  | ||||||
| 		return "NaN" |  | ||||||
| 	end |  | ||||||
| 	if number == huge then |  | ||||||
| 		assert(options.inf, "Invalid number: Infinity not enabled") |  | ||||||
| 		return "Infinity" |  | ||||||
| 	end |  | ||||||
| 	if number == -huge then |  | ||||||
| 		assert(options.inf, "Invalid number: Infinity not enabled") |  | ||||||
| 		return "-Infinity" |  | ||||||
| 	end |  | ||||||
| 	return tostring(number) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function getEncoder(options) |  | ||||||
| 	options = options and jsonutil.merge({}, defaultOptions, options) or defaultOptions |  | ||||||
| 	return { |  | ||||||
| 		number = function(number, state) |  | ||||||
| 			return encodeNumber(number, options) |  | ||||||
| 		end |  | ||||||
| 	} |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local number = { |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	getEncoder = getEncoder |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return number |  | ||||||
| @@ -1,77 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local pairs = pairs |  | ||||||
| local assert = assert |  | ||||||
|  |  | ||||||
| local type = type |  | ||||||
| local tostring = tostring |  | ||||||
|  |  | ||||||
| local table_concat = require("table").concat |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = {} |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'object', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	Cleanup function to unmark a value as in the encoding process and return |  | ||||||
| 	trailing results |  | ||||||
| ]] |  | ||||||
| local function unmarkAfterEncode(tab, state, ...) |  | ||||||
| 	state.already_encoded[tab] = nil |  | ||||||
| 	return ... |  | ||||||
| end |  | ||||||
| --[[ |  | ||||||
| 	Encode a table as a JSON Object ( keys = strings, values = anything else ) |  | ||||||
| ]] |  | ||||||
| local function encodeTable(tab, options, state) |  | ||||||
| 	-- Make sure this value hasn't been encoded yet |  | ||||||
| 	state.check_unique(tab) |  | ||||||
| 	local encode = state.encode |  | ||||||
| 	local compositeEncoder = state.outputEncoder.composite |  | ||||||
| 	local valueEncoder = [[ |  | ||||||
| 	local first = true |  | ||||||
| 	for k, v in pairs(composite) do |  | ||||||
| 		local ti = type(k) |  | ||||||
| 		assert(ti == 'string' or ti == 'number' or ti == 'boolean', "Invalid object index type: " .. ti) |  | ||||||
| 		local name = encode(tostring(k), state, true) |  | ||||||
| 		if first then |  | ||||||
| 			first = false |  | ||||||
| 		else |  | ||||||
| 			name = ',' .. name |  | ||||||
| 		end |  | ||||||
| 		PUTVALUE(name .. ':') |  | ||||||
| 		local val = encode(v, state) |  | ||||||
| 		val = val or '' |  | ||||||
| 		if val then |  | ||||||
| 			PUTVALUE(val) |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	]] |  | ||||||
| 	return unmarkAfterEncode(tab, state, compositeEncoder(valueEncoder, '{', '}', nil, tab, encode, state)) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function getEncoder(options) |  | ||||||
| 	options = options and jsonutil.merge({}, defaultOptions, options) or defaultOptions |  | ||||||
| 	return { |  | ||||||
| 		table = function(tab, state) |  | ||||||
| 			return encodeTable(tab, options, state) |  | ||||||
| 		end |  | ||||||
| 	} |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local object = { |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	getEncoder = getEncoder |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return object |  | ||||||
| @@ -1,66 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local tostring = tostring |  | ||||||
|  |  | ||||||
| local assert = assert |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local type = type |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| -- Shortcut that works |  | ||||||
| local encodeBoolean = tostring |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| 	allowUndefined = true, |  | ||||||
| 	null = jsonutil.null, |  | ||||||
| 	undefined = jsonutil.undefined |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = {} |  | ||||||
|  |  | ||||||
| modeOptions.strict = { |  | ||||||
| 	allowUndefined = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'others', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
| local function getEncoder(options) |  | ||||||
| 	options = options and jsonutil.merge({}, defaultOptions, options) or defaultOptions |  | ||||||
| 	local function encodeOthers(value, state) |  | ||||||
| 		if value == options.null then |  | ||||||
| 			return 'null' |  | ||||||
| 		elseif value == options.undefined then |  | ||||||
| 			assert(options.allowUndefined, "Invalid value: Unsupported 'Undefined' parameter") |  | ||||||
| 			return 'undefined' |  | ||||||
| 		else |  | ||||||
| 			return false |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	local function encodeBoolean(value, state) |  | ||||||
| 		return value and 'true' or 'false' |  | ||||||
| 	end |  | ||||||
| 	local nullType = type(options.null) |  | ||||||
| 	local undefinedType = options.undefined and type(options.undefined) |  | ||||||
| 	-- Make sure that all of the types handled here are handled |  | ||||||
| 	local ret = { |  | ||||||
| 		boolean = encodeBoolean, |  | ||||||
| 		['nil'] = function() return 'null' end, |  | ||||||
| 		[nullType] = encodeOthers |  | ||||||
| 	} |  | ||||||
| 	if undefinedType then |  | ||||||
| 		ret[undefinedType] = encodeOthers |  | ||||||
| 	end |  | ||||||
| 	return ret |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local others = { |  | ||||||
| 	encodeBoolean = encodeBoolean, |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	getEncoder = getEncoder |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return others |  | ||||||
| @@ -1,91 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local type = type |  | ||||||
| local assert, error = assert, error |  | ||||||
| local table_concat = require("table").concat |  | ||||||
| local loadstring = loadstring or load |  | ||||||
|  |  | ||||||
| local io = require("io") |  | ||||||
|  |  | ||||||
| local setmetatable = setmetatable |  | ||||||
|  |  | ||||||
| local output_utility = require("json.encode.output_utility") |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local tableCompositeCache = setmetatable({}, {__mode = 'v'}) |  | ||||||
|  |  | ||||||
| local TABLE_VALUE_WRITER = [[ |  | ||||||
| 	ret[#ret + 1] = %VALUE% |  | ||||||
| ]] |  | ||||||
|  |  | ||||||
| local TABLE_INNER_WRITER = "" |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	nextValues can output a max of two values to throw into the data stream |  | ||||||
| 	expected to be called until nil is first return value |  | ||||||
| 	value separator should either be attached to v1 or in innerValue |  | ||||||
| ]] |  | ||||||
| local function defaultTableCompositeWriter(nextValues, beginValue, closeValue, innerValue, composite, encode, state) |  | ||||||
| 	if type(nextValues) == 'string' then |  | ||||||
| 		local fun = output_utility.prepareEncoder(defaultTableCompositeWriter, nextValues, innerValue, TABLE_VALUE_WRITER, TABLE_INNER_WRITER) |  | ||||||
| 		local ret = {} |  | ||||||
| 		fun(composite, ret, encode, state) |  | ||||||
| 		return beginValue .. table_concat(ret, innerValue) .. closeValue |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- no 'simple' as default action is just to return the value |  | ||||||
| local function getDefault() |  | ||||||
| 	return { composite = defaultTableCompositeWriter } |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- BEGIN IO-WRITER OUTPUT |  | ||||||
| local IO_INNER_WRITER = [[ |  | ||||||
| 	if %WRITE_INNER% then |  | ||||||
| 		state.__outputFile:write(%INNER_VALUE%) |  | ||||||
| 	end |  | ||||||
| ]] |  | ||||||
| local IO_VALUE_WRITER = [[ |  | ||||||
| 	state.__outputFile:write(%VALUE%) |  | ||||||
| ]] |  | ||||||
|  |  | ||||||
| local function buildIoWriter(output) |  | ||||||
| 	if not output then -- Default to stdout |  | ||||||
| 		output = io.output() |  | ||||||
| 	end |  | ||||||
| 	local function ioWriter(nextValues, beginValue, closeValue, innerValue, composite, encode, state) |  | ||||||
| 		-- HOOK OUTPUT STATE |  | ||||||
| 		state.__outputFile = output |  | ||||||
| 		if type(nextValues) == 'string' then |  | ||||||
| 			local fun = output_utility.prepareEncoder(ioWriter, nextValues, innerValue, IO_VALUE_WRITER, IO_INNER_WRITER) |  | ||||||
| 			local ret = {} |  | ||||||
| 			output:write(beginValue) |  | ||||||
| 			fun(composite, ret, encode, state) |  | ||||||
| 			output:write(closeValue) |  | ||||||
| 			return nil |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
|  |  | ||||||
| 	local function ioSimpleWriter(encoded) |  | ||||||
| 		if encoded then |  | ||||||
| 			output:write(encoded) |  | ||||||
| 		end |  | ||||||
| 		return nil |  | ||||||
| 	end |  | ||||||
| 	return { composite = ioWriter, simple = ioSimpleWriter } |  | ||||||
| end |  | ||||||
| local function getIoWriter(output) |  | ||||||
| 	return function() |  | ||||||
| 		return buildIoWriter(output) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local output = { |  | ||||||
| 	getDefault = getDefault, |  | ||||||
| 	getIoWriter = getIoWriter |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return output |  | ||||||
| @@ -1,54 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local setmetatable = setmetatable |  | ||||||
| local assert, loadstring = assert, loadstring or load |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| -- Key == weak, if main key goes away, then cache cleared |  | ||||||
| local outputCache = setmetatable({}, {__mode = 'k'}) |  | ||||||
| -- TODO: inner tables weak? |  | ||||||
|  |  | ||||||
| local function buildFunction(nextValues, innerValue, valueWriter, innerWriter) |  | ||||||
| 	local putInner = "" |  | ||||||
| 	if innerValue and innerWriter then |  | ||||||
| 		-- Prepare the lua-string representation of the separator to put in between values |  | ||||||
| 		local formattedInnerValue = ("%q"):format(innerValue) |  | ||||||
| 		-- Fill in the condition %WRITE_INNER% and the %INNER_VALUE% to actually write |  | ||||||
| 		putInner = innerWriter:gsub("%%WRITE_INNER%%", "%%1"):gsub("%%INNER_VALUE%%", formattedInnerValue) |  | ||||||
| 	end |  | ||||||
| 	-- Template-in the value writer (if present) and its conditional argument |  | ||||||
| 	local functionCode = nextValues:gsub("PUTINNER(%b())", putInner) |  | ||||||
| 	-- %VALUE% is to be filled in by the value-to-write |  | ||||||
| 	valueWriter = valueWriter:gsub("%%VALUE%%", "%%1") |  | ||||||
| 	-- Template-in the value writer with its argument |  | ||||||
| 	functionCode = functionCode:gsub("PUTVALUE(%b())", valueWriter) |  | ||||||
| 	functionCode = [[ |  | ||||||
| 		return function(composite, ret, encode, state) |  | ||||||
| 	]] .. functionCode .. [[ |  | ||||||
| 		end |  | ||||||
| 	]] |  | ||||||
| 	return assert(loadstring(functionCode))() |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function prepareEncoder(cacheKey, nextValues, innerValue, valueWriter, innerWriter) |  | ||||||
| 	local cache = outputCache[cacheKey] |  | ||||||
| 	if not cache then |  | ||||||
| 		cache = {} |  | ||||||
| 		outputCache[cacheKey] = cache |  | ||||||
| 	end |  | ||||||
| 	local fun = cache[nextValues] |  | ||||||
| 	if not fun then |  | ||||||
| 		fun = buildFunction(nextValues, innerValue, valueWriter, innerWriter) |  | ||||||
| 		cache[nextValues] = fun |  | ||||||
| 	end |  | ||||||
| 	return fun |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local output_utility = { |  | ||||||
| 	prepareEncoder = prepareEncoder |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return output_utility |  | ||||||
| @@ -1,88 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local string_char = require("string").char |  | ||||||
| local pairs = pairs |  | ||||||
|  |  | ||||||
| local jsonutil = require("json.util") |  | ||||||
| local util_merge = jsonutil.merge |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local normalEncodingMap = { |  | ||||||
| 	['"'] = '\\"', |  | ||||||
| 	['\\'] = '\\\\', |  | ||||||
| 	['/'] = '\\/', |  | ||||||
| 	['\b'] = '\\b', |  | ||||||
| 	['\f'] = '\\f', |  | ||||||
| 	['\n'] = '\\n', |  | ||||||
| 	['\r'] = '\\r', |  | ||||||
| 	['\t'] = '\\t', |  | ||||||
| 	['\v'] = '\\v' -- not in official spec, on report, removing |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local xEncodingMap = {} |  | ||||||
| for char, encoded in pairs(normalEncodingMap) do |  | ||||||
| 	xEncodingMap[char] = encoded |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Pre-encode the control characters to speed up encoding... |  | ||||||
| -- NOTE: UTF-8 may not work out right w/ JavaScript |  | ||||||
| -- JavaScript uses 2 bytes after a \u... yet UTF-8 is a |  | ||||||
| -- byte-stream encoding, not pairs of bytes (it does encode |  | ||||||
| -- some letters > 1 byte, but base case is 1) |  | ||||||
| for i = 0, 255 do |  | ||||||
| 	local c = string_char(i) |  | ||||||
| 	if c:match('[%z\1-\031\128-\255]') and not normalEncodingMap[c] then |  | ||||||
| 		-- WARN: UTF8 specializes values >= 0x80 as parts of sequences... |  | ||||||
| 		--       without \x encoding, do not allow encoding > 7F |  | ||||||
| 		normalEncodingMap[c] = ('\\u%.4X'):format(i) |  | ||||||
| 		xEncodingMap[c] = ('\\x%.2X'):format(i) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local defaultOptions = { |  | ||||||
| 	xEncode = false, -- Encode single-bytes as \xXX |  | ||||||
| 	processor = nil, -- Simple processor for the string prior to quoting |  | ||||||
| 	-- / is not required to be quoted but it helps with certain decoding |  | ||||||
| 	-- Required encoded characters, " \, and 00-1F  (0 - 31) |  | ||||||
| 	encodeSet = '\\"/%z\1-\031', |  | ||||||
| 	encodeSetAppend = nil -- Chars to append to the default set |  | ||||||
| } |  | ||||||
|  |  | ||||||
| local modeOptions = {} |  | ||||||
|  |  | ||||||
| local function mergeOptions(options, mode) |  | ||||||
| 	jsonutil.doOptionMerge(options, false, 'strings', defaultOptions, mode and modeOptions[mode]) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function getEncoder(options) |  | ||||||
| 	options = options and util_merge({}, defaultOptions, options) or defaultOptions |  | ||||||
| 	local encodeSet = options.encodeSet |  | ||||||
| 	if options.encodeSetAppend then |  | ||||||
| 		encodeSet = encodeSet .. options.encodeSetAppend |  | ||||||
| 	end |  | ||||||
| 	local encodingMap = options.xEncode and xEncodingMap or normalEncodingMap |  | ||||||
| 	local encodeString |  | ||||||
| 	if options.processor then |  | ||||||
| 		local processor = options.processor |  | ||||||
| 		encodeString = function(s, state) |  | ||||||
| 			return '"' .. processor(s:gsub('[' .. encodeSet .. ']', encodingMap)) .. '"' |  | ||||||
| 		end |  | ||||||
| 	else |  | ||||||
| 		encodeString = function(s, state) |  | ||||||
| 			return '"' .. s:gsub('[' .. encodeSet .. ']', encodingMap) .. '"' |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return { |  | ||||||
| 		string = encodeString |  | ||||||
| 	} |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local strings = { |  | ||||||
| 	mergeOptions = mergeOptions, |  | ||||||
| 	getEncoder = getEncoder |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return strings |  | ||||||
| @@ -1,152 +0,0 @@ | |||||||
| --[[ |  | ||||||
| 	Licensed according to the included 'LICENSE' document |  | ||||||
| 	Author: Thomas Harning Jr <harningt@gmail.com> |  | ||||||
| ]] |  | ||||||
| local type = type |  | ||||||
| local print = print |  | ||||||
| local tostring = tostring |  | ||||||
| local pairs = pairs |  | ||||||
| local getmetatable, setmetatable = getmetatable, setmetatable |  | ||||||
| local select = select |  | ||||||
|  |  | ||||||
| local _ENV = nil |  | ||||||
|  |  | ||||||
| local function foreach(tab, func) |  | ||||||
| 	for k, v in pairs(tab) do |  | ||||||
| 		func(k,v) |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
| local function printValue(tab, name) |  | ||||||
|         local parsed = {} |  | ||||||
|         local function doPrint(key, value, space) |  | ||||||
|                 space = space or '' |  | ||||||
|                 if type(value) == 'table' then |  | ||||||
|                         if parsed[value] then |  | ||||||
|                                 print(space .. key .. '= <' .. parsed[value] .. '>') |  | ||||||
|                         else |  | ||||||
|                                 parsed[value] = key |  | ||||||
|                                 print(space .. key .. '= {') |  | ||||||
|                                 space = space .. ' ' |  | ||||||
|                                 foreach(value, function(key, value) doPrint(key, value, space) end) |  | ||||||
|                         end |  | ||||||
|                 else |  | ||||||
| 					if type(value) == 'string' then |  | ||||||
| 						value = '[[' .. tostring(value) .. ']]' |  | ||||||
| 					end |  | ||||||
| 					print(space .. key .. '=' .. tostring(value)) |  | ||||||
|                 end |  | ||||||
|         end |  | ||||||
|         doPrint(name, tab) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function clone(t) |  | ||||||
| 	local ret = {} |  | ||||||
| 	for k,v in pairs(t) do |  | ||||||
| 		ret[k] = v |  | ||||||
| 	end |  | ||||||
| 	return ret |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function inner_merge(t, remaining, from, ...) |  | ||||||
| 	if remaining == 0 then |  | ||||||
| 		return t |  | ||||||
| 	end |  | ||||||
| 	if from then |  | ||||||
| 		for k,v in pairs(from) do |  | ||||||
| 			t[k] = v |  | ||||||
| 		end |  | ||||||
| 	end |  | ||||||
| 	return inner_merge(t, remaining - 1, ...) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| --[[* |  | ||||||
|     Shallow-merges tables in order onto the first table. |  | ||||||
|  |  | ||||||
|     @param t table to merge entries onto |  | ||||||
|     @param ... sequence of 0 or more tables to merge onto 't' |  | ||||||
|  |  | ||||||
|     @returns table 't' from input |  | ||||||
| ]] |  | ||||||
| local function merge(t, ...) |  | ||||||
| 	return inner_merge(t, select('#', ...), ...) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Function to insert nulls into the JSON stream |  | ||||||
| local function null() |  | ||||||
| 	return null |  | ||||||
| end |  | ||||||
|  |  | ||||||
| -- Marker for 'undefined' values |  | ||||||
| local function undefined() |  | ||||||
| 	return undefined |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local ArrayMT = {} |  | ||||||
|  |  | ||||||
| --[[ |  | ||||||
| 	Return's true if the metatable marks it as an array.. |  | ||||||
| 	Or false if it has no array component at all |  | ||||||
| 	Otherwise nil to get the normal detection component working |  | ||||||
| ]] |  | ||||||
| local function IsArray(value) |  | ||||||
| 	if type(value) ~= 'table' then return false end |  | ||||||
| 	local meta = getmetatable(value) |  | ||||||
| 	local ret = meta == ArrayMT or (meta ~= nil and meta.__is_luajson_array) |  | ||||||
| 	if not ret then |  | ||||||
| 		if #value == 0 then return false end |  | ||||||
| 	else |  | ||||||
| 		return ret |  | ||||||
| 	end |  | ||||||
| end |  | ||||||
| local function InitArray(array) |  | ||||||
| 	setmetatable(array, ArrayMT) |  | ||||||
| 	return array |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local CallMT = {} |  | ||||||
|  |  | ||||||
| local function isCall(value) |  | ||||||
| 	return CallMT == getmetatable(value) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function buildCall(name, ...) |  | ||||||
| 	local callData = { |  | ||||||
| 		name = name, |  | ||||||
| 		parameters = {n = select('#', ...), ...} |  | ||||||
| 	} |  | ||||||
| 	return setmetatable(callData, CallMT) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function decodeCall(callData) |  | ||||||
| 	if not isCall(callData) then return nil end |  | ||||||
| 	return callData.name, callData.parameters |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local function doOptionMerge(options, nested, name, defaultOptions, modeOptions) |  | ||||||
| 	if nested then |  | ||||||
| 		modeOptions = modeOptions and modeOptions[name] |  | ||||||
| 		defaultOptions = defaultOptions and defaultOptions[name] |  | ||||||
| 	end |  | ||||||
| 	options[name] = merge( |  | ||||||
| 		{}, |  | ||||||
| 		defaultOptions, |  | ||||||
| 		modeOptions, |  | ||||||
| 		options[name] |  | ||||||
| 	) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local json_util = { |  | ||||||
| 	printValue = printValue, |  | ||||||
| 	clone = clone, |  | ||||||
| 	merge = merge, |  | ||||||
| 	null = null, |  | ||||||
| 	undefined = undefined, |  | ||||||
| 	IsArray = IsArray, |  | ||||||
| 	InitArray = InitArray, |  | ||||||
| 	isCall = isCall, |  | ||||||
| 	buildCall = buildCall, |  | ||||||
| 	decodeCall = decodeCall, |  | ||||||
| 	doOptionMerge = doOptionMerge |  | ||||||
| } |  | ||||||
|  |  | ||||||
| return json_util |  | ||||||
| @@ -1,95 +0,0 @@ | |||||||
| package.path = package.path .. ";lua_scripts/libraries/luajson/?.lua" |  | ||||||
|  |  | ||||||
| local JSON = require"json" |  | ||||||
|  |  | ||||||
| local jsontest = [[{ 1:{"scn_ptz_id":"", |  | ||||||
| "scn_ptz_prepos":"Preset 176", |  | ||||||
| "scn_ptz_order":1, |  | ||||||
| "scn_ptz_duration":"30", |  | ||||||
| "scn_ptz_rally_delay":"2"} |  | ||||||
| , |  | ||||||
| 2:{"scn_ptz_id":"","scn_ptz_prepos":"route","scn_ptz_order":2,"scn_ptz_duration":"30","scn_ptz_rally_delay":"2"} } |  | ||||||
| ]] |  | ||||||
| local jsontest2 = [[{ |  | ||||||
| 	"extension":"mpg", |  | ||||||
| 	"id":1545148451781, |  | ||||||
| 	"name":"Foule_1280x720p.mpg", |  | ||||||
| 	"size":67240746, |  | ||||||
| 	"date":1545148451, |  | ||||||
| 	"mime":"video\/mpeg", |  | ||||||
| 	"filename":"1545148451781.mpg", |  | ||||||
| 	"dir":"\/home\/pixalarm_data\/fileprocessor_data", |  | ||||||
| 	"function_metadatas": |  | ||||||
| 	{ |  | ||||||
| 		"function_faceblur": |  | ||||||
| 		{ |  | ||||||
| 		   "date":1545228627, |  | ||||||
| 		   "current_frame":"845", |  | ||||||
| 		   "polygons":[ |  | ||||||
| 			{ |  | ||||||
| 				"polygon_id":"new_1", |  | ||||||
| 				"polygon_vertex":"[ |  | ||||||
| 				   [0.14254859611231102,0.12476007677543186],[0.13174946004319654,0.4740882917466411], |  | ||||||
| 				   [0.3898488120950324,0.6621880998080614],[0.4038876889848812,0.11516314779270634] |  | ||||||
| 				]", |  | ||||||
| 				"polygon_frame_start":"1", |  | ||||||
| 				"polygon_frame_stop":"300", |  | ||||||
|                                 "polygon_type":"full_blur" |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				"polygon_id":"new_2", |  | ||||||
| 				"polygon_vertex":"[ |  | ||||||
| 				   [0.6198704103671706,0.1727447216890595],[0.5496760259179265,0.6007677543186181], |  | ||||||
| 				   [0.7775377969762419,0.7946257197696737],[0.9028077753779697,0.761996161228407], |  | ||||||
| 				   [0.9481641468682506,0.2821497120921305],[0.7829373650107991,0.04798464491362764] |  | ||||||
| 				]", |  | ||||||
| 				"polygon_frame_start":"200", |  | ||||||
| 				"polygon_frame_stop":"845", |  | ||||||
|                                 "polygon_type":"no_blur" |  | ||||||
| 			} |  | ||||||
|                    ], |  | ||||||
| 		   "framecuts":[ |  | ||||||
| 		      ["17","110"], |  | ||||||
| 		      ["248","298"], |  | ||||||
| 		      ["488","620"], |  | ||||||
| 		      ["378","428"] |  | ||||||
| 		   ], |  | ||||||
|                    "face_selection":[ |  | ||||||
|                        { |  | ||||||
|                          "frame":"21", |  | ||||||
|                           "x":"0.5", |  | ||||||
|                           "y":"0.356" |  | ||||||
|                        }, |  | ||||||
|                        { |  | ||||||
|                           "frame":"108", |  | ||||||
|                           "x":"0.4289", |  | ||||||
|                           "y":"0.275" |  | ||||||
|                        }, |  | ||||||
|                        { |  | ||||||
|                           "frame":"294", |  | ||||||
|                           "x":"0.726", |  | ||||||
|                            "y":"0.2364" |  | ||||||
|                        } |  | ||||||
|                     ], |  | ||||||
| 		    "blur_type":"blur", |  | ||||||
| 		    "blur_area":"face" |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	"total_frame":"845", |  | ||||||
| 	"status":"DECODE_FINISHED", |  | ||||||
| 	"fps":"25.00" |  | ||||||
| }]] |  | ||||||
|  |  | ||||||
| local res = JSON.decode(jsontest2) |  | ||||||
| for k, v in pairs(res) do |  | ||||||
|   print( k, v) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| res = JSON.decode( '{"content" : {},"date" : "2014-12-30T08:29:48Z","error" : {"code" : 0,"httpcode" : 200,"message" : ""},"status" : 1}' ) |  | ||||||
| for k, v in pairs(res) do |  | ||||||
|   print( k, v) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local jsondata = JSON.encode( res ) |  | ||||||
| print(jsondata) |  | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user